/* ══════════════════════════════════════════════════════════════════════════
   app.css — every layout and component style for the usage pages.
   Rules (src/web/CLAUDE.md): values come from tokens.css only. Mobile-first: base styles fit
   320px; breakpoints are min-width 860px and 1024px, nothing else. BEM-ish names, no utility
   classes (one exception, .visually-hidden, below). One section per view or component.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Base ── */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg-main);
  color: var(--text-body);
  font-family: var(--font-family);
  font-size: var(--font-size-m);
  line-height: var(--line-height-body);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

h1, h2, h3, h4 {
  margin: 0;
  color: var(--text-heading);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-heading);
}

p { margin: 0; }

a { color: var(--link); }

/* Buttons get their ring from tokens.css; links and focusable containers get the same one. */
a:focus-visible,
[tabindex]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-blue-400);
  outline-offset: var(--focus-ring-offset);
}

/* Screen-reader-only text. The one helper class: captions, "(opens in a new tab)", the live region. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── Skip link ── first focusable element; visible only on focus (FRONTEND-SPEC §2). */
.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 10;
  padding: var(--space-2) var(--space-4);
  background: var(--bg-card);
  color: var(--link);
  font-weight: var(--font-weight-medium);
  border-radius: var(--radius-default);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }
/* White ring: the default blue ring vanishes against the blue header. */
.skip-link:focus-visible { outline-color: var(--color-neutral-000); }

/* ── Layout: header, main, footer ── */
/* Header is the wordmark only. No navbar: admins may not hold a license (src/web/CLAUDE.md). */
/* Dark blue because ES_Logo_WebHeader.svg is a white wordmark drawn for a dark bar; on white
   only the colored mark shows (found 2026-09-29). */
.site-header {
  background: var(--color-blue-400);
  padding: var(--space-3) var(--space-4);
}
.site-header__logo { display: block; height: var(--logo-height); width: auto; }

.site-main {
  flex: 1 0 auto;
  width: 100%;
  max-width: var(--layout-max-width);
  margin: 0 auto;
  padding: var(--space-4);
}
/* The skip link targets main, and Retry focuses the new h1 (tabindex -1). Both take focus from
   script, not the user tabbing, so they draw no ring. */
.site-main:focus,
h1[tabindex="-1"]:focus { outline: none; }

/* Light blue band with two help links, each with a line on what it's for (Mo, 2026-09-29). */
.site-footer {
  margin-top: var(--space-8);
  padding: var(--space-7) var(--space-4) var(--space-6);
  background: var(--color-blue-000);
  border-top: var(--border-width) solid var(--color-blue-100);
}
.site-footer__inner { max-width: var(--layout-max-width); margin: 0 auto; }
.site-footer__links { display: grid; gap: var(--space-5); margin: 0; padding: 0; list-style: none; }
.site-footer__item { display: flex; align-items: flex-start; gap: var(--space-3); }
.site-footer__icon { margin-top: var(--space-1); color: var(--color-blue-400); font-size: var(--font-size-l); }
.site-footer__link { font-weight: var(--font-weight-semibold); }
.site-footer__help { margin-top: var(--space-1); color: var(--text-muted); font-size: var(--font-size-s); }
.site-footer__copy { margin-top: var(--space-6); color: var(--text-muted); font-size: var(--font-size-xs); }

@media (min-width: 860px) {
  .site-header { padding: var(--space-4) var(--space-6); }
  .site-main { padding: var(--space-6); }
  .site-footer { padding-left: var(--space-6); padding-right: var(--space-6); }
  .site-footer__links { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
}

/* ── Card ── shared by every block on every view (FRONTEND-SPEC §2). */
.card {
  background: var(--bg-card);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-xl);
  padding: var(--space-4);
}
@media (min-width: 860px) {
  .card { padding: var(--space-6); }
}

/* ── Views ── one view shows at a time, chosen by body[data-state] (set by the page script). */
.view { display: none; }
body[data-state="loading"] .view--loading,
body[data-state="needs_confirm"] .view--landing,
body[data-state="no_access"] .view--landing,
body[data-state="not_admin"] .view--landing,
body[data-state="no_recipient"] .view--landing,
body[data-state="link_sent"] .view--landing,
body[data-state="error"] .view--landing,
body[data-state="report"] .view--report,
body[data-state="overview"] .view--overview { display: block; }

/* ── Loading ── the district-name placeholder and one "Loading…" line. */
.loading__title {
  width: 60%;
  height: calc(var(--font-size-3xl) * var(--line-height-heading));
  background: var(--border-subtle);
  border-radius: var(--radius-default);
}
.loading__line { margin-top: var(--space-3); color: var(--text-muted); }

/* ── Landing ── confirm, bad link, link sent, error (FRONTEND-SPEC §3). */
.landing {
  max-width: var(--landing-max-width);
  margin: var(--space-7) auto;
  padding-top: var(--space-9);
  padding-bottom: var(--space-9);
  text-align: center;
}
.landing__kicker { color: var(--text-muted); font-size: var(--font-size-s); }
.landing__title { margin-top: var(--space-2); font-size: var(--font-size-2xl); overflow-wrap: anywhere; }
.landing__body { margin-top: var(--space-6); }
.landing__text { margin-top: var(--space-4); }
.landing__text--muted { color: var(--text-muted); font-size: var(--font-size-s); }
/* The admin note's second line: italic for look, not stress, so a span, not <em> (Mo, 2026-09-30). */
.landing__text-ask { font-style: italic; }
/* The accounts a link names, above View report, when there are several: a gray box centered in
   the card, its list left-aligned so each bullet sits by its name (Mo, 2026-09-30). */
.landing__accounts {
  width: fit-content;
  max-width: 100%;
  margin: var(--space-2) auto 0;
  padding: var(--space-3) var(--space-5);
  background: var(--bg-main);
  border-radius: var(--radius-lg);
  text-align: left;
}
.landing__accounts-label { color: var(--text-muted); font-size: var(--font-size-s); }
.landing__list { margin: var(--space-2) 0 0; padding-left: var(--space-5); list-style: disc; }
.landing__list-item { overflow-wrap: anywhere; }
.landing__list-item + .landing__list-item { margin-top: var(--space-1); }
.landing__accounts + .landing__action { margin-top: var(--space-5); }
.landing__action { margin-top: var(--space-2); }
/* Busy (request in flight): keep the "Opening…" label fully readable, unlike a disabled button. */
.es-btn[aria-busy="true"] { opacity: 1; cursor: progress; }

/* ── Buttons, page overrides ── Below 860px labels wrap instead of overflowing; the kit's
   es-btn is nowrap (FRONTEND-SPEC §4.4, decided 2026-09-29). */
.es-btn {
  white-space: normal;
  text-align: center;
  line-height: var(--line-height-heading);
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}
/* Hover contrast: the kit's hover fill (blue-200) with white text is 3.2:1, under 4.5:1 for
   14px labels (a11y-auditor, 2026-09-29). Outline hovers to a pale fill with blue text (8.6:1);
   secondary keeps its fill and gets only the shadow. Kit issue to raise upstream. */
.es-btn-outline:hover:not(:disabled) { background: var(--color-blue-000); color: var(--color-blue-400); }
.es-btn-secondary:hover:not(:disabled) { background: var(--color-blue-400); }

@media (min-width: 860px) {
  .es-btn { white-space: nowrap; }
}

/* ── Card titles ── every report block is a <section> with an <h2> (FRONTEND-SPEC §7). */
.card__title { font-size: var(--font-size-xl); }
.card__intro { margin-top: var(--space-1); color: var(--text-muted); font-size: var(--font-size-s); }

/* ── Report header ── district and "label · Updated" line (FRONTEND-SPEC §4.1). */
.report__header { margin-bottom: var(--space-6); }
.report__title { font-size: var(--font-size-3xl); overflow-wrap: anywhere; }
.report__meta { margin-top: var(--space-2); color: var(--text-muted); }
.report__block + .report__block { margin-top: var(--space-4); }
@media (min-width: 860px) {
  .report__block + .report__block { margin-top: var(--space-6); }
}

/* ── CTA strip ── expand and intervene only: one sentence and a text link to the rep
   (FRONTEND-SPEC §4.5; link, not button, since 2026-09-29). Stacked on phones; one row from 860px. */
.cta {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--color-blue-000);
  border: var(--border-width) solid var(--color-blue-100);
  border-radius: var(--radius-xl);
}
.cta__sentence { font-size: var(--font-size-l); font-weight: var(--font-weight-medium); }
.cta__link { align-self: flex-start; }
/* Hover: a thicker underline in the same blue, no highlight (Mo, 2026-09-29; the kit's text
   button hovers yellow). Padding shrinks as the border grows, so the text doesn't shift. Focus
   keeps a ring so keyboard users still see where they are. */
.cta__link:hover, .cta__link:focus-visible {
  background: transparent;
  border-bottom: 3px solid var(--color-blue-400);
  padding-bottom: calc(var(--space-1) - 2px);
}
.cta__link:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); }
@media (min-width: 860px) {
  .cta { flex-direction: row; align-items: center; justify-content: space-between; padding: var(--space-5) var(--space-6); }
  .cta__link { flex: 0 0 auto; align-self: center; }
}

/* ── Testing notes ── REMOVE BEFORE LAUNCH (Mo, 2026-09-30). Red, dashed and flagged, so a
   reviewer can't mistake them for the page: data the backend didn't send or the page doesn't
   recognize yet (js/cu-view.js SHOW_TEST_NOTES). Color is never the only signal: each starts
   with "Testing note:". */
.test-note {
  padding: var(--space-3) var(--space-4);
  background: var(--status-bad-bg);
  color: var(--status-bad-fg);
  border: var(--border-width-strong) dashed var(--status-bad-fg);
  border-radius: var(--radius-lg);
  overflow-wrap: anywhere;   /* the tier is the server's raw string */
}
.test-note .fa-flag { margin-right: var(--space-2); }
.test-note__label { font-weight: var(--font-weight-semibold); }

/* ── Ended note ── an expired account's plain note, where the CTA strip would be. */
.ended-note {
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: var(--border-width) solid var(--color-blue-100);
  border-left: var(--border-width-accent) solid var(--color-blue-400);
  border-radius: var(--radius-lg);
}
.tabs__panel > .test-note, .tabs__panel > .ended-note { margin-bottom: var(--space-4); }

/* ── Subscription card ── stats and rep block (FRONTEND-SPEC §4.2). Each stat sits in its own
   tile so the four read apart (Mo, 2026-09-29). Two per row on phones; four across with the rep
   to the right from 860px. */
.sub__body { margin-top: var(--space-4); }
/* Two tiles per row on phones; one per row when text is enlarged. The column minimum is in rem,
   so at 200% text it doubles and the tiles stack instead of pushing past the card (1.4.4/1.4.10,
   found 2026-09-29). 7rem = two columns in a 320px card at normal size. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 7rem), 1fr));
  gap: var(--space-4);
  margin: 0;
}
/* <dt> comes first for screen readers; the number shows on top. */
.stat {
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-main);
  border-radius: var(--radius-lg);
}
.stat__label { color: var(--text-muted); font-size: var(--font-size-s); }
.stat__value {
  margin: 0;
  color: var(--text-heading);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-heading);
}
.stat__number, .stat__pct { white-space: nowrap; }
/* Renewal: "Aug 18" over a smaller "2027" (Mo, 2026-09-29). */
.stat__year { display: block; font-size: var(--font-size-l); font-weight: var(--font-weight-medium); }
/* The percentage is smaller and never colored by health: the tier sets tone, not the number. */
.stat__pct { display: inline-block; font-size: var(--font-size-m); font-weight: var(--font-weight-regular); color: var(--text-muted); }
/* Manage licenses, under Licenses purchased (Mo, 2026-09-30). The tile is column-reverse (number
   on top), so order -1 puts this last in the DOM order's reverse: the foot of the tile. Its label
   may wrap so a narrow tile never widens for it. */
.stat__action { order: -1; margin: var(--space-1) 0 0; }
.stat__manage { white-space: normal; padding-block: var(--space-2); line-height: var(--line-height-heading); }

.rep {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: var(--border-width) solid var(--border-subtle);
}
.rep__label { color: var(--text-muted); font-size: var(--font-size-s); }
.rep__name { font-weight: var(--font-weight-medium); }
.rep__action { margin-top: var(--space-3); }

@media (min-width: 860px) {
  .sub__body { display: flex; align-items: flex-start; gap: var(--space-6); }
  /* Four across (FRONTEND-SPEC §6). Labels wrap; numbers never do, so each column is at least
     as wide as its number. */
  .stats { flex: 1 1 auto; grid-template-columns: repeat(4, minmax(min-content, 1fr)); gap: var(--space-3); }
  .rep {
    flex: 0 0 auto;
    margin-top: 0;
    padding-top: 0;
    padding-left: var(--space-6);
    border-top: 0;
    border-left: var(--border-width) solid var(--border-subtle);
  }
}

/* ── Top materials card ── names only, no counts (FRONTEND-SPEC §4.3). Names link into SLP only
   for roles that can open materials (T17; Mo, 2026-09-30; was never links). */
.materials__cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); margin-top: var(--space-4); }
.materials__heading { font-size: var(--font-size-m); }
/* Numbers in small gray circles, styled apart from the names and quieter than them, so the names
   scan first (Mo, 2026-09-30; were larger blue circles, 2026-09-29). */
.materials__list { margin: var(--space-3) 0 0; padding: 0; list-style: none; counter-reset: rank; }
.materials__item { display: flex; align-items: flex-start; gap: var(--space-3); counter-increment: rank; }
.materials__item + .materials__item { margin-top: var(--space-3); }
.materials__item::before {
  content: counter(rank);
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--rank-size);
  height: var(--rank-size);
  margin-top: 1px;   /* centers the circle on the first line of the name */
  border-radius: var(--radius-full);
  background: var(--border-subtle);
  color: var(--text-muted);   /* 5.9:1 on the circle */
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: 1;
}
/* min-width 0 so a long title can wrap inside the flex row at large text sizes (2026-09-29). */
.materials__name { min-width: 0; line-height: var(--line-height-heading); overflow-wrap: anywhere; }
/* A name that links into SLP (roles that can open materials, T17): body color with a subtle gray
   underline that says "link" without shouting; blue on hover and focus (Mo, 2026-09-30). The
   underline is the signal, never color alone. The last word sits in an inline-block with its
   type tag, which an underline doesn't reach, so it is underlined on its own; the tag is not. */
.materials__link,
.materials__link .materials__word {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--border-default);
  text-decoration-thickness: var(--border-width);
  text-underline-offset: 3px;
}
.materials__link:hover,
.materials__link:hover .materials__word,
.materials__link:focus-visible,
.materials__link:focus-visible .materials__word { color: var(--link); text-decoration-color: currentColor; }
.materials__link:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); border-radius: var(--radius-sm); }
.materials__none { margin-top: var(--space-2); color: var(--text-muted); }
/* The title's last word and its type tag stay together as one unit on the line (js/cu-view.js
   materialsContent). An inline-block, not nowrap: when the unit is wider than a phone line at
   large text sizes it can still wrap inside itself, so nothing scrolls sideways (1.4.10; a11y
   audit 2026-09-30). */
.materials__tail { display: inline-block; max-width: 100%; }
/* Materials get the widest column so titles and their tags fit on fewer lines; skills and goals
   are short (Mo, 2026-09-30; was three equal columns). */
@media (min-width: 860px) {
  .materials__cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, var(--materials-wide-col)); gap: var(--space-6); }
}

/* Type tag: all caps, rounded corners, the kit's light material fill with body text, outlined in
   the type's accent color so it holds its shape on the gray Top materials box (Mo, 2026-09-29;
   before that no outline, and briefly a solid accent fill). Body text on every tint is 15:1+. */
.chip {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 0 var(--space-2);
  border: var(--border-width) solid;
  border-radius: var(--radius-default);
  color: var(--text-body);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: text-bottom;
  white-space: nowrap;
}
.chip--video { background: var(--material-video-bg); border-color: var(--material-video-accent); }
.chip--activity { background: var(--material-activity-bg); border-color: var(--material-activity-accent); }
.chip--game { background: var(--material-game-bg); border-color: var(--material-game-accent); }
.chip--edsw { background: var(--material-edsw-bg); border-color: var(--material-edsw-accent); }

/* ── Educators card ── summary, actions, then one <table> (FRONTEND-SPEC §4.4, §6). */
.edu__bar { margin-top: var(--space-3); }
.edu__actions { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-4); }
/* Activate your team: a dark blue pill. Its helper line is helper text: small, muted, to the left
   of the button with an arrow pointing at it; above it, arrow pointing down, on phones
   (Mo, 2026-09-30; was body-size text to the right). */
.edu__activate { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }
.edu__activate-help { color: var(--text-muted); font-size: var(--font-size-xs); line-height: var(--line-height-heading); }
.edu__activate-tail { white-space: nowrap; }
.edu__activate-arrow { margin-left: var(--space-1); transform: rotate(90deg); }
@media (min-width: 860px) {
  .edu__actions { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); }
  .edu__activate { flex-direction: row; align-items: center; gap: var(--space-2); }
  .edu__activate-help { max-width: 15rem; text-align: right; }
  .edu__activate-arrow { transform: none; }
}
/* The summary and the actions share a row only while the actions fit; with three buttons they
   drop under the summary rather than squeeze it. */
@media (min-width: 1024px) {
  .edu__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3) var(--space-4); }
  .edu__actions { margin-top: 0; }
}

/* Below 1024px the table stacks as a list: email on line one (bold), "Logged in · Last active"
   on line two. Below 860px those two get a line each: together they don't fit 320px and wrapped
   badly (2026-09-29). Same DOM in every layout; cu-view.js sets explicit roles so it stays a table. */
.edu-table { display: block; width: 100%; margin-top: var(--space-4); border-collapse: collapse; }
.edu-table tbody, .edu-table tr, .edu-table td { display: block; }
.edu-table__head {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.edu-table__row { padding: var(--space-3) 0; border-top: var(--border-width) solid var(--border-subtle); }
.edu-table__email { font-weight: var(--font-weight-semibold); overflow-wrap: anywhere; }
.edu-table__status, .edu-table__last { color: var(--text-muted); font-size: var(--font-size-s); }
.edu-table__sep { display: none; margin: 0 var(--space-2); }
@media (min-width: 860px) {
  .edu-table .edu-table__status, .edu-table .edu-table__last { display: inline; }
  .edu-table__sep { display: inline; }
}
.edu-table__icon--yes { color: var(--status-ok-fg); }
.edu-table__icon--no { color: var(--text-muted); }
.edu-table__status .fa-solid { margin-right: var(--space-1); }
/* Icon only in the Activated column, so it reads at a glance (Mo, 2026-09-30). */
.edu-table__icon { font-size: var(--font-size-m); }

/* Real table from 1024px, and always in print: far shorter on paper than the stacked list. */
@media print, (min-width: 1024px) {
  .edu-table { display: table; }
  .edu-table__head {
    display: table-header-group; position: static; width: auto; height: auto; margin: 0;
    overflow: visible; clip: auto; white-space: normal;
  }
  .edu-table tbody { display: table-row-group; }
  .edu-table tr { display: table-row; }
  .edu-table th, .edu-table td,
  .edu-table .edu-table__status, .edu-table .edu-table__last { display: table-cell; padding: var(--space-3) var(--space-4) var(--space-3) 0; text-align: left; vertical-align: top; }
  .edu-table th {
    color: var(--text-heading);
    font-size: var(--font-size-s);
    font-weight: var(--font-weight-semibold);
    border-bottom: var(--border-width) solid var(--border-default);
  }
  .edu-table__row td { border-top: var(--border-width) solid var(--border-subtle); }
  .edu-table__email { font-weight: var(--font-weight-regular); }
  .edu-table__status, .edu-table__last { color: var(--text-body); font-size: var(--font-size-m); white-space: nowrap; }
  .edu-table__sep, .edu-table__prefix { display: none; }
  /* The check or X and the date sit centered under their headers (Mo, 2026-09-30; were
     left-aligned). The icon's list-mode gap would pull it off center. */
  .edu-table th.edu-table__th--center, .edu-table .edu-table__status, .edu-table .edu-table__last { text-align: center; }
  .edu-table__status .fa-solid { margin-right: 0; }
}

/* ── Info tooltip ── the (i) beside "Activated account?" (Mo, 2026-09-30). A caret-and-box
   tooltip above the icon on hover or keyboard focus; hovering the box keeps it; Escape hides it
   (js/cu-view.js infoTip; WCAG 1.4.13). The header row is hidden in the stacked list, so the
   button shows only with the real table, never as an invisible tab stop. */
.tip { position: relative; display: none; }
.tip__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;   /* 2.5.8 target size */
  padding: 0;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--font-size-s);
  vertical-align: middle;
  cursor: pointer;
}
.tip__button:hover, .tip__button:focus-visible { color: var(--link); }
.tip__button:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: 0; }
.tip__box {
  position: absolute;
  bottom: calc(100% + var(--tooltip-caret));
  left: 50%;
  z-index: 10;
  width: max-content;
  max-width: var(--tooltip-max-width);
  padding: var(--space-3) var(--space-4);   /* roomier, Mo 2026-09-30 (was space-2/space-3) */
  border-radius: var(--radius-md);
  background: var(--text-body);
  color: var(--color-neutral-000);   /* 17:1 */
  box-shadow: var(--shadow-modal);
  font-size: var(--font-size-s);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-heading);
  text-align: left;
  white-space: normal;
  transform: translateX(-50%);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.12s ease-in;
}
/* The caret, pointing down at the icon; the ::before fills the gap so moving onto the box keeps it. */
.tip__box::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: calc(-1 * var(--tooltip-caret));
  border: var(--tooltip-caret) solid transparent;
  border-top-color: var(--text-body);
}
.tip__box::before { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: var(--tooltip-caret); }
.tip:hover .tip__box, .tip__button:focus-visible + .tip__box { visibility: visible; opacity: 1; }
.tip.tip--dismissed .tip__box { visibility: hidden; opacity: 0; }
@media (prefers-reduced-motion: reduce) { .tip__box { transition: none; } }
@media (min-width: 1024px) { .tip { display: inline-block; } }

/* ── Modal ── support educators who haven't logged in (FRONTEND-SPEC §4.6). Kit modal: blue-400
   title bar, white content, radius 2xl. Its own screen, so its Copy button may be gold. */
.modal {
  width: calc(100% - 2 * var(--space-4));
  max-width: var(--modal-max-width);
  max-height: calc(100vh - 2 * var(--space-4));
  max-height: calc(100dvh - 2 * var(--space-4));   /* dvh excludes a phone's browser toolbar */
  padding: 0;
  border: 0;
  border-radius: var(--radius-2xl);
  background: var(--bg-card);
  color: var(--text-body);
  box-shadow: var(--shadow-modal);
  overflow: hidden;
}
.modal[open] { display: flex; flex-direction: column; }
.modal::backdrop { background: var(--backdrop); }
.modal__bar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-5);
  background: var(--color-blue-400);
}
.modal__title { color: var(--color-neutral-000); font-size: var(--font-size-l); }
.modal__close {
  flex: 0 0 auto;
  min-width: 38px;
  min-height: 38px;
  margin: calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) 0 0;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-neutral-000);
  font-size: var(--font-size-l);
  cursor: pointer;
}
.modal__close:hover { background: var(--color-blue-300); }
.modal__close:focus-visible { outline: var(--focus-ring-width) solid var(--color-neutral-000); outline-offset: calc(-1 * var(--focus-ring-width)); }
.modal__content { flex: 1 1 auto; overflow-y: auto; padding: var(--space-5); }
.modal__intro { font-weight: var(--font-weight-medium); }
.modal__step { margin-top: var(--space-5); padding-top: var(--space-5); border-top: var(--border-width) solid var(--border-subtle); }
.modal__step-title { display: flex; align-items: center; gap: var(--space-3); font-size: var(--font-size-m); }
.modal__step-num {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--rank-size);
  height: var(--rank-size);
  border-radius: var(--radius-full);
  background: var(--color-blue-100);
  color: var(--color-blue-400);
  font-size: var(--font-size-xs);
}
.modal__help { margin-top: var(--space-2); color: var(--text-muted); font-size: var(--font-size-s); }
.modal__emails {
  max-height: var(--modal-list-max-height);
  overflow-y: auto;
  margin: var(--space-3) 0 0;
  padding: var(--space-2) var(--space-3);
  list-style: none;
  background: var(--bg-main);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-md);
  font-size: var(--font-size-s);
}
.modal__email { padding: var(--space-1) 0; overflow-wrap: anywhere; }
.modal__label { display: block; margin-top: var(--space-3); color: var(--text-muted); font-size: var(--font-size-s); }
.modal__field {
  display: block;
  width: 100%;
  margin-top: var(--space-1);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-main);
  /* --border-hover, not --border-default: the field edge needs 3:1 (1.4.11; #B3B3B3 is 2.1:1). */
  border: var(--border-width) solid var(--border-hover);
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-family: var(--font-family);
  font-size: var(--font-size-s);
  line-height: var(--line-height-body);
}
.modal__field--body { resize: vertical; }
.modal__field:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); }
.modal__copy { margin-top: var(--space-3); }
.modal__actions { display: flex; justify-content: flex-end; padding: var(--space-4) var(--space-5); border-top: var(--border-width) solid var(--border-subtle); }
@media (min-width: 860px) {
  .modal { max-height: calc(100vh - 2 * var(--space-8)); max-height: calc(100dvh - 2 * var(--space-8)); }
}

/* ── Tester modal ── REMOVE BEFORE LAUNCH with the testing notes (Mo, 2026-09-30). Styled like
   a testing note (red, dashed, flagged) so nobody mistakes it for the product. */
.modal--test { border: var(--border-width-strong) dashed var(--status-bad-fg); }
.modal__bar--test { background: var(--status-bad-fg); }
.modal__bar--test .modal__close:hover { background: var(--status-bad-bg); color: var(--status-bad-fg); }
.modal__bar--test .fa-flag { margin-right: var(--space-2); }
.test-modal__lead { font-weight: var(--font-weight-semibold); }
.test-modal__line { margin-top: var(--space-2); }
.test-modal__facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-1) var(--space-3);
  margin: var(--space-4) 0 0;
  padding: var(--space-3);
  background: var(--status-bad-bg);
  border-radius: var(--radius-md);
  font-size: var(--font-size-s);
}
.test-modal__facts dt { color: var(--status-bad-fg); font-weight: var(--font-weight-semibold); }
.test-modal__facts dd { margin: 0; overflow-wrap: anywhere; }
.test-modal__foot { margin-top: var(--space-4); color: var(--text-muted); font-size: var(--font-size-s); }

/* ── Overview ── (FRONTEND-SPEC §5). Reuses the report's blocks; these are its additions. */

/* Renewals list above the tiles: each line names the accounts, then "renews {date}". */
.renewals { margin-top: var(--space-4); padding: var(--space-3) var(--space-4); background: var(--bg-main); border-radius: var(--radius-lg); }
.renewals__label { color: var(--text-muted); font-size: var(--font-size-s); font-weight: var(--font-weight-regular); }
.renewals__list { margin: var(--space-2) 0 0; padding: 0; list-style: none; }
.renewals__item { display: flex; flex-wrap: wrap; gap: 0 var(--space-2); }
.renewals__item + .renewals__item { margin-top: var(--space-2); }
.renewals__accounts { font-weight: var(--font-weight-medium); overflow-wrap: anywhere; }
.renewals__date { color: var(--text-heading); font-weight: var(--font-weight-semibold); }   /* may wrap: at 200% text it can't fit one line */
/* Three tiles (the date moved to the list above) on the overview. */
@media (min-width: 860px) {
  .stats.stats--three { grid-template-columns: repeat(3, minmax(min-content, 1fr)); }
}

/* Several reps: one line each with its own button. */
.rep__list { margin: 0; padding: 0; list-style: none; }
.rep__person + .rep__person { margin-top: var(--space-4); }

/* Tabs (the overview's Accounts card): All accounts, then each account. They wrap onto
   more rows instead of scrolling sideways, so no account is hidden off the edge (8 tabs for
   Elkhorn). The chosen tab has a pale blue fill and a blue border, distinct from the filled
   Activate button. */
.tabs { display: none; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }
/* Phones: a dropdown instead of the tabs (Mo, 2026-09-29). From 860px the tabs return. */
.tabs-select { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-4); }
.tabs-select__label { color: var(--text-muted); font-size: var(--font-size-s); font-weight: var(--font-weight-medium); }
.tabs-select__control {
  width: 100%;
  min-height: 44px;
  padding: 0 var(--space-3);
  background: var(--bg-card);
  border: var(--border-width) solid var(--border-hover);   /* 3:1 edge (1.4.11) */
  border-radius: var(--radius-md);
  color: var(--text-body);
  font-family: var(--font-family);
  font-size: var(--font-size-m);
}
.tabs-select__control:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); }
@media (min-width: 860px) {
  .tabs { display: flex; }
  .tabs-select { display: none; }
}
.tabs__tab {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  min-height: 38px;
  padding: var(--space-1) var(--space-3);
  background: var(--bg-main);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-lg);   /* not a pill: tabs with a status chip wrap onto two lines on phones */
  color: var(--text-body);
  font-family: var(--font-family);
  font-size: var(--font-size-s);
  font-weight: var(--font-weight-medium);
  text-align: left;
  cursor: pointer;
}
.tabs__tab:hover { border-color: var(--border-hover); }
/* Selected: the second pixel of border is an inset shadow and the weight stays the same, so the
   tab keeps its size and the row never re-wraps on selection (audit 2026-09-29). */
.tabs__tab[aria-selected="true"] {
  background: var(--color-blue-000);
  border-color: var(--color-blue-400);
  box-shadow: inset 0 0 0 1px var(--color-blue-400);
  color: var(--color-blue-400);
}
.tabs__tab:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); }
.tabs__meta { color: var(--text-muted); font-weight: var(--font-weight-regular); }
.tabs__panel { margin-top: var(--space-4); padding-top: var(--space-4); border-top: var(--border-width) solid var(--border-subtle); }
.tabs__panel:focus-visible { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); }
/* Inside the one Accounts panel: Top materials in a gray box, the same fill and radius as the
   stat tiles, so it reads apart from Your educators below (Mo, 2026-09-29). The box does the
   separating, so Your educators needs no divider. */
.tabs__materials {
  padding: var(--space-4);
  background: var(--bg-main);
  border-radius: var(--radius-lg);
}
@media (min-width: 860px) {
  .tabs__materials { padding: var(--space-5) var(--space-6); }
}
.materials__title { font-size: var(--font-size-l); }
.tabs__educators { margin-top: var(--space-6); }
.tabs__panel > .tabs__educators:first-child { margin-top: 0; }
.tabs__educators-title { font-size: var(--font-size-l); }

/* Status chip: the word is always shown; the tint only supports it. Every pair passes 4.5:1
   (--status-bad-fg darkened 2026-09-29 for this). */
.status-chip {
  justify-self: start;
  padding: 0 var(--space-2);
  border-radius: var(--radius-default);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-body);
  white-space: nowrap;
}
.status-chip--expand { background: var(--status-ok-bg); color: var(--status-ok-fg); }
.status-chip--deepen, .status-chip--intervene { background: var(--status-warn-bg); color: var(--status-warn-fg); }
.status-chip--recover { background: var(--status-bad-bg); color: var(--status-bad-fg); }
/* Testing only: a missing or unknown tier (remove with the testing notes, below). The dashed
   border tells it apart from Recover, which shares the red. */
.status-chip--unknown { background: var(--status-bad-bg); color: var(--status-bad-fg); outline: var(--border-width-strong) dashed var(--status-bad-fg); outline-offset: 0; }

/* Educators table's Account column: a muted line above the email in the stacked list, a real
   first column from 1024px. */
.edu-table__account { color: var(--text-muted); font-size: var(--font-size-s); overflow-wrap: anywhere; }
/* After the base rule so it wins (same specificity; audit 2026-09-29 caught the order). */
@media print, (min-width: 1024px) {
  .edu-table__account { color: var(--text-body); font-size: var(--font-size-m); }
}

/* ── Launcher ── index.html only; never deployed. */
.launcher__title { font-size: var(--font-size-2xl); }
.launcher__intro { margin-top: var(--space-2); color: var(--text-muted); }
.launcher__section { margin-top: var(--space-6); }
.launcher__heading { font-size: var(--font-size-xl); }
.launcher__group { margin-top: var(--space-4); font-size: var(--font-size-m); color: var(--text-body); }
.launcher__list { margin: var(--space-2) 0 0; padding: 0; list-style: none; }
.launcher__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-4);
  padding: var(--space-3) 0;
  border-top: var(--border-width) solid var(--border-subtle);
}
.launcher__item:first-child { border-top: 0; }
.launcher__name { flex: 1 1 16rem; font-weight: var(--font-weight-medium); overflow-wrap: anywhere; }
.launcher__meta { display: block; color: var(--text-muted); font-size: var(--font-size-s); font-weight: var(--font-weight-regular); }
.launcher__flags { display: block; color: var(--status-warn-fg); font-size: var(--font-size-s); font-weight: var(--font-weight-regular); }
.launcher__links { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.launcher__check { margin-top: var(--space-2); font-size: var(--font-size-s); }
/* What the page says for each account, for internal review. Label column, then text. */
.launcher__msgs {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-1) var(--space-3);
  margin: var(--space-3) 0 0;
  padding: var(--space-3);
  background: var(--bg-main);
  border-radius: var(--radius-md);
  font-size: var(--font-size-s);
  font-weight: var(--font-weight-regular);
}
.launcher__msg-label { color: var(--text-muted); }
.launcher__msg-text { margin: 0; color: var(--text-body); overflow-wrap: anywhere; }
.launcher__intro code, .launcher__meta code { font-size: var(--font-size-xs); }
.launcher__check--fail { color: var(--status-bad-fg); }

/* For review: the part testers use (Mo, 2026-09-30). Step 1 picks the role, step 2 opens one of
   the five districts. Everything below .context is the logic, for the team. */
.review { margin-top: var(--space-6); border: var(--border-width-strong) solid var(--color-blue-400); }
.review__kicker {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--color-blue-400);
  color: var(--color-neutral-000);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.review__title { margin-top: var(--space-3); font-size: var(--font-size-xl); }
.review__intro { margin-top: var(--space-2); max-width: 44rem; }
.review__step { margin: var(--space-6) 0 0; padding: 0; border: 0; min-width: 0; }
.review__step-title { display: flex; align-items: center; gap: var(--space-3); padding: 0; color: var(--text-heading); font-size: var(--font-size-l); font-weight: var(--font-weight-semibold); }
.review__num {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 1.75rem; height: 1.75rem;
  border-radius: var(--radius-full);
  background: var(--color-blue-100);
  color: var(--color-blue-400);
  font-size: var(--font-size-s);
}
.review__hint { margin-top: var(--space-2); color: var(--text-muted); font-size: var(--font-size-s); }
.review__note { margin-top: var(--space-6); color: var(--status-bad-fg); font-size: var(--font-size-s); }
.review__note .fa-flag { margin-right: var(--space-1); }

/* Role choices: one card per role, the whole card clickable. */
.role-picker__options { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); margin-top: var(--space-3); }
.role-picker__option {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  cursor: pointer;
}
.role-picker__option:hover { border-color: var(--color-blue-400); }
.role-picker__option:has(.role-picker__input:checked) { border: var(--border-width-strong) solid var(--color-blue-400); background: var(--color-blue-000); }
.role-picker__option:has(.role-picker__input:focus-visible) { outline: var(--focus-ring-width) solid var(--color-blue-400); outline-offset: var(--focus-ring-offset); }
.role-picker__input { flex: 0 0 auto; width: 1.125rem; height: 1.125rem; margin: 2px 0 0; accent-color: var(--color-blue-400); }
.role-picker__name { display: block; font-weight: var(--font-weight-semibold); }
.role-picker__about { display: block; margin-top: var(--space-1); color: var(--text-muted); font-size: var(--font-size-s); }

/* District cards. */
.review__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); margin: var(--space-3) 0 0; padding: 0; list-style: none; }
.review-card {
  display: flex; flex-direction: column;
  padding: var(--space-4) var(--space-5);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-xl);
  background: var(--bg-main);
}
.review-card__title { font-size: var(--font-size-l); overflow-wrap: anywhere; }
.review-card__setup { margin-top: var(--space-1); font-weight: var(--font-weight-medium); }
.review-card__accounts { margin-top: var(--space-1); color: var(--text-muted); font-size: var(--font-size-s); }
.review-card__tags { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 0; padding: 0; list-style: none; }
.review-card__tag {
  padding: 0 var(--space-2);
  border: var(--border-width) solid var(--color-blue-200);
  border-radius: var(--radius-full);
  background: var(--bg-card);
  color: var(--color-blue-400);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-body);
}
.review-card__facts { flex: 1 1 auto; margin: var(--space-3) 0 0; padding-left: var(--space-5); color: var(--text-body); font-size: var(--font-size-s); }
.review-card__facts li + li { margin-top: var(--space-1); }
.review-card__action { margin-top: var(--space-4); }
.review-card__who { margin-top: var(--space-2); color: var(--text-muted); font-size: var(--font-size-xs); overflow-wrap: anywhere; }
@media (min-width: 860px) {
  .role-picker__options { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .review__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .role-picker__options { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .review__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* For context: the logic, set apart from the review section. */
.context { margin-top: var(--space-9); padding-top: var(--space-6); border-top: var(--border-width-strong) solid var(--border-default); }
.context__title { font-size: var(--font-size-xl); color: var(--text-body); }

/* ── Forced colors (Windows High Contrast) ── backgrounds and shadows are dropped there, so the
   selected tab takes the system highlight, and boxes drawn only by a fill get a border
   (PR 7 audit, 2026-09-29). Transparent borders show only in this mode. */
@media (forced-colors: active) {
  .tabs__tab[aria-selected="true"] {
    forced-color-adjust: none;
    background: Highlight;
    color: HighlightText;
    border-color: Highlight;
  }
  .tabs__tab[aria-selected="true"] .tabs__meta { color: HighlightText; }
  .stat, .renewals, .tabs__materials, .cta, .modal, .landing__accounts, .tip__box { border: var(--border-width) solid CanvasText; }
}

/* ── Email preview chrome ── email.html only, never deployed. The email below it uses inline
   styles (email constraint), not these classes. */
body.email-preview { display: block; }
.email-preview__bar {
  max-width: 600px;
  margin: 0 auto;
  padding: var(--space-4) var(--space-3) 0;
  font-size: var(--font-size-s);
}
.email-preview__controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); }
.email-preview__label { font-weight: var(--font-weight-medium); }
.email-preview__select {
  max-width: 100%;
  min-height: 38px;
  padding: 0 var(--space-2);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-card);
  font-family: var(--font-family);
  font-size: var(--font-size-s);
}
.email-preview__check { display: inline-flex; align-items: center; gap: var(--space-2); }
.email-preview__inbox {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-1) var(--space-3);
  margin: var(--space-3) 0 0;
  padding: var(--space-3);
  background: var(--bg-card);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.email-preview__inbox dt { color: var(--text-muted); }
.email-preview__inbox dd { margin: 0; overflow-wrap: anywhere; }
.email-preview__notice { margin-top: var(--space-3); padding: var(--space-2) var(--space-3); background: var(--status-warn-bg); color: var(--status-warn-fg); border-radius: var(--radius-md); }

/* ── Print ── the report (or the overview's chosen tab) as a record: no banner, no buttons, no
   navigation (FRONTEND-SPEC §6). Checked 2026-09-29 by printing every fixture to PDF. */
@media print {
  @page { margin: 12mm; }
  body { background: var(--bg-card); font-size: var(--font-size-s); -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* The header's white wordmark would print white-on-white (browsers drop the blue fill), and
     the footer links do nothing on paper. */
  .site-header, .site-footer, .skip-link, #cu-live, .modal, .modal[open] { display: none; }
  .accounts > .card__intro { display: none; }   /* "…one at a time" means nothing on paper */
  .site-main { max-width: none; padding: 0; }
  .cta, .es-btn, .edu__actions, .rep__action, .stat__action, .tip { display: none; }
  /* Overview: only the chosen tab prints, as a plain label above its panel (the tabs, not the
     phone dropdown, whatever the paper width). */
  .tabs { display: flex; }
  .tabs-select { display: none; }
  .tabs__tab:not([aria-selected="true"]) { display: none; }
  .tabs__tab[aria-selected="true"] { border: 0; box-shadow: none; background: none; padding: 0; min-height: 0; font-size: var(--font-size-l); }
  .card { border-color: var(--border-subtle); padding: var(--space-4); }
  .report__block + .report__block { margin-top: var(--space-4); }
  /* Paper is narrower than 860px, so print uses the desktop layout explicitly instead of the
     phone one: tiles in a row with the rep beside them, materials in three columns. */
  .sub__body { display: flex; align-items: flex-start; gap: var(--space-5); }
  .stats { flex: 1 1 auto; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-2); }
  .stats.stats--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stat { padding: var(--space-2) var(--space-3); }
  .stat__value { font-size: var(--font-size-xl); }
  .rep { flex: 0 0 auto; margin-top: 0; padding-top: 0; padding-left: var(--space-4); border-top: 0; border-left: var(--border-width) solid var(--border-subtle); }
  .materials__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); margin-top: var(--space-3); }
  .materials__item + .materials__item { margin-top: var(--space-1); }
  /* Small pieces never split across pages; big cards may, so no page is left mostly empty. */
  .stat, .renewals, .materials__col, .edu-table tr, h2, h3 { break-inside: avoid; }
  h2, h3 { break-after: avoid; }
  .edu-table__head { display: table-header-group; }   /* repeats on each page */
  .edu-table th, .edu-table td,
  .edu-table .edu-table__status, .edu-table .edu-table__last, .edu-table__account {
    padding-top: var(--space-1); padding-bottom: var(--space-1); font-size: var(--font-size-s); vertical-align: baseline;
  }
  a { color: var(--text-body); text-decoration: none; }
}
