/* Hallmark · genre: modern-minimal · nav: N5 floating pill (top-centred, content-sized, sticky)
 * footer: Ft1 mast-headed · theme: studied-DNA (.docs/datafluvia/ui-concepts/*.png)
 * Every colour here resolves through a --df-* token from Css/Datafluvia/Tokens.css.
 *
 * ============================================================
 * Public shell — landing / auth / error pages.
 *
 * Light-first, per `ui-design-standards.md` §1: white and light surfaces, navy
 * typography, indigo action, teal for verification and freshness. The dark
 * theme is the same system on the sanctioned navy ramp — not a second design.
 *
 * `.pub-*` keeps the shell/auth/error class names the existing pages already
 * bind to; `.df-*` is the Datafluvia component vocabulary that arrived with the
 * landing page and is the one to extend from here.
 * ============================================================ */

html,
body {
  /* `clip` not `hidden`: `hidden` on the root silently kills position: sticky. */
  overflow-x: clip;
}

/* Neutralise DesignPack's body flex for public pages only */
body:has(.pub-shell) {
  display: block;
  margin: 0;
  min-height: 100vh;
  background: var(--df-canvas);
}

.pub-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--df-canvas);
  color: var(--df-ink);
  font-family: var(--df-font-sans);
  font-size: var(--df-text-body);
  line-height: var(--df-leading-body);
  -webkit-font-smoothing: antialiased;
}
.pub-shell *,
.pub-shell *::before,
.pub-shell *::after { box-sizing: border-box; }
/* Wrapped in :where() so the reset carries zero specificity. As a plain
   `.pub-shell a` it scored (0,1,1) and silently beat every single-class
   component rule — .df-btn--primary, .df-btn--secondary and .df-nav__link all
   had their `color` ignored and inherited the page ink instead. In light that
   happened to land near navy and looked right; in dark it painted white ink on
   the white CTA. Components must win over a reset, so: zero. */
:where(.pub-shell a) { text-decoration: none; color: inherit; }
/* Same `:where()` trick as the link reset above, and for the same reason: as
   plain `.pub-shell h2` / `.pub-shell p` these scored (0,1,1) and beat every
   single-class component rule, so `margin-top` on `.lp-hero__lede`,
   `.lp-head__lede`, `.pf-lede` and friends silently computed to 0px and
   the whole page's vertical rhythm collapsed into line-height. A reset must
   never outrank the components that consume it, so: zero specificity. The
   properties that are genuinely non-negotiable (roman display type, safe
   wrapping) stay here and are simply never overridden. */
:where(.pub-shell h1, .pub-shell h2, .pub-shell h3) {
  /* Display type is always roman, and long compound words break inside
     themselves rather than pushing the page sideways. */
  font-style: normal;
  color: var(--df-ink-strong);
  margin: 0;
}
/* Not in :where() — these two must hold everywhere, including against a
   component rule that forgets them. They cost nothing to keep specific. */
.pub-shell h1,
.pub-shell h2,
.pub-shell h3 {
  overflow-wrap: anywhere;
  min-width: 0;
}
:where(.pub-shell p) { margin: 0; }

.pub-main {
  flex: 1;
  width: 100%;
  max-width: var(--df-page-max);
  margin: 0 auto;
  padding: var(--df-space-16) var(--df-space-6) var(--df-space-20);
}

/* The landing page opts out of the column: its ink bands run edge to edge and
   each section re-establishes the 1200px measure through `.lp-shell`. Without
   this, a full-bleed band would have to be faked with 100vw negative margins,
   which overshoots by the scrollbar width on every desktop browser. */
.pub-main--fluid {
  max-width: none;
  padding: 0;
}

/* ---------------- Focus + motion, globally ---------------- */
/* The ring is never transitioned: a keyboard user must see it on frame one. */
.pub-shell :focus-visible {
  outline: 2px solid var(--df-focus);
  outline-offset: 2px;
  border-radius: var(--df-radius-control);
}

@media (prefers-reduced-motion: reduce) {
  .pub-shell *,
  .pub-shell *::before,
  .pub-shell *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

.df-skip-link {
  position: absolute;
  left: var(--df-space-4);
  top: calc(var(--df-space-4) * -6);
  z-index: var(--df-z-dropdown);
  padding: var(--df-space-3) var(--df-space-4);
  background: var(--df-surface);
  color: var(--df-action-link);
  border: var(--df-rule) solid var(--df-border);
  border-radius: var(--df-radius-control);
  font-weight: var(--df-weight-strong);
}
/* The lift arrives with the link, not before it. Parked at -96px the element
   itself is off-screen but a 32px shadow is not: on a dark canvas it printed a
   faint smudge along the top edge of every page. A shadow on something nobody
   can see has no job to do. */
.df-skip-link:focus {
  top: var(--df-space-4);
  box-shadow: var(--df-shadow-lift);
}

/* ============================================================
   Brand mark
   ============================================================ */
.df-mark { display: block; flex: none; }
.df-mark__flow { stroke: var(--df-action); }
.df-mark__flow--2 { stroke: var(--df-accent); }
.df-mark__flow--3 { stroke: var(--df-action); opacity: .45; }

/* ============================================================
   Nav — N5 floating pill. Centred, sticky, content-sized.
   Sticky (not fixed) so the pill keeps its own space in the flow and never
   has to be compensated for with a magic padding-top on <main>.
   ============================================================ */
.df-nav {
  position: sticky;
  top: var(--df-space-4);
  z-index: var(--df-z-sticky);
  display: flex;
  justify-content: center;
  margin-top: var(--df-space-4);
  padding-inline: var(--df-space-4);
  pointer-events: none;
}

.df-nav__pill {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--df-space-4);
  /* A definite width, not a cap: the pill used to be content-sized (~764px) and
     the old 940px max-width never bound, so raising the cap alone changed
     nothing. 1146px is 1.5× that natural width; 100% keeps it inside the
     gutter on narrow viewports. */
  width: min(100%, 1146px);
  padding: var(--df-space-2) var(--df-space-2) var(--df-space-2) var(--df-space-4);
  background: var(--df-surface);
  border: var(--df-rule) solid var(--df-border);
  border-radius: var(--df-radius-pill);
  box-shadow: var(--df-shadow);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .df-nav__pill {
    /* Translucent only so the page reads as moving *under* the control.
       Kept at 88% so it never becomes a decorative frosted panel. */
    background: color-mix(in srgb, var(--df-surface) 88%, transparent);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    backdrop-filter: blur(14px) saturate(140%);
  }
}

.df-nav__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-2);
  font-weight: var(--df-weight-display);
  font-size: var(--df-text-card);
  letter-spacing: -0.015em;
  color: var(--df-ink-strong);
  white-space: nowrap;
}
.df-nav__wordmark { color: var(--df-ink-strong); }

.df-nav__rule {
  width: var(--df-rule);
  height: 20px;
  background: var(--df-border);
  flex: none;
}

/* The wrapper is layout-transparent above the collapse width: `contents`
   promotes `.df-nav__links` and `.df-nav__controls` back to direct flex
   children of the pill, so grouping them for the mobile disclosure costs the
   desktop layout nothing. */
.df-nav__collapse { display: contents; }

/* Centred, by giving the list an auto margin on BOTH sides: it takes the
   space left over between the brand and the controls and splits it in two.
   Not `position: absolute; left: 50%`, which centres on the pill and would
   therefore slide under the brand as soon as the two sides stop matching in
   width. */
.df-nav__links {
  display: flex;
  align-items: center;
  gap: var(--df-space-1);
  margin: 0 auto;
  padding: 0;
  list-style: none;
}
.df-nav__link {
  display: inline-flex;
  align-items: center;
  height: var(--df-control-sm);
  padding-inline: var(--df-space-3);
  border-radius: var(--df-radius-control);
  font-size: var(--df-text-body);
  font-weight: var(--df-weight-medium);
  color: var(--df-ink-body);
  white-space: nowrap;
  transition: color var(--df-dur-micro) var(--df-ease),
              background-color var(--df-dur-micro) var(--df-ease);
}
.df-nav__link:hover {
  color: var(--df-ink-strong);
  background: var(--df-surface-sunk);
}
/* No auto margin any more: `.df-nav__links` now carries one on each side, and
   a second one here would eat the right-hand half of it and shove the links
   back against the brand. */
.df-nav__controls {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-1);
}
.df-nav__actions {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-2);
}
/* Scoped to `.df-nav` on purpose. As a bare `.df-nav__burger` this scored the
   same (0,1,0) as `.df-icon-btn`, which is declared *below* it and sets
   `display: inline-flex` — so the burger was painted at every width, including
   1440px next to the links it is supposed to replace. The extra class wins the
   cascade without an !important. */
.df-nav .df-nav__burger { display: none; }
/* One button, two glyphs — Base.js flips `.is-open` alongside aria-expanded
   and the accessible name, so the state is never carried by the icon alone. */
.df-nav__burger-close { display: none; }
.df-nav__burger.is-open .df-nav__burger-open { display: none; }
.df-nav__burger.is-open .df-nav__burger-close { display: block; }

/* ---------------- Icon button ---------------- */
.df-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--df-space-2);
  width: var(--df-control-sm);
  height: var(--df-control-sm);
  padding: 0;
  background: transparent;
  border: var(--df-rule) solid transparent;
  border-radius: var(--df-radius-control);
  color: var(--df-ink-muted);
  cursor: pointer;
  font: inherit;
  transition: color var(--df-dur-micro) var(--df-ease),
              background-color var(--df-dur-micro) var(--df-ease),
              border-color var(--df-dur-micro) var(--df-ease);
}
.df-icon-btn:hover {
  color: var(--df-ink-strong);
  background: var(--df-surface-sunk);
  box-shadow: var(--dp-shadow-control-inset);
}
.df-icon-btn:active { background: var(--df-slate-100); }
.df-icon-btn[disabled] { opacity: 0.55; cursor: not-allowed; pointer-events: none; }
/* The icon button still owns its own press tint. The secondary button used to
   ride along here, but it now resolves through --df-ghost-active-bg, which is
   already per-theme — keeping it in this selector would out-specify that. */
[data-theme="dark"] .df-icon-btn:active { background: var(--df-ghost-active-bg); }
.df-icon-btn--wide {
  width: auto;
  padding-inline: var(--df-space-2);
}
.df-icon { flex: none; }

/* The toggle offers the theme you'd switch *to*.
   Both marks are always in the DOM and this picks between them — which is
   what lets the theme flip without a re-render: since 2026-09-06 Base.js just
   sets `data-theme` on <html> and the swap follows from the cascade. Every
   chrome in the product uses this pair, so it lives here in the one
   stylesheet Base.html loads on every page, not next to any one of them.
   `inline-flex` rather than `block`: the platform topbar's marks are `.dp-fa`
   glyph spans, which centre their glyph with flexbox, and the inline SVGs in
   the navbar sit inside flex buttons that blockify them regardless. */
.df-icon--sun { display: none; }
.df-icon--moon { display: inline-flex; }
[data-theme="dark"] .df-icon--sun { display: inline-flex; }
[data-theme="dark"] .df-icon--moon { display: none; }

/* ---------------- Language switcher ---------------- */
.df-lang { position: relative; }
/* The flag: a 3:2 chip with our own corner radius, never a raw rectangle.
   `border-radius` and not an SVG clipPath, because a clipPath needs an id and
   the same flag renders twice per page — the outer <svg> already clips the
   Union Flag's diagonals to its viewport, so this only rounds the corner. */
.df-flag {
  flex: none;
  display: block;
  border-radius: 3px;
}
/* Flag + language name travel together on the left of a menu row; the short
   code stays pushed to the right by the row's own space-between. */
.df-lang__label {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-3);
}
.df-lang__current {
  font-size: var(--df-text-small);
  font-weight: var(--df-weight-strong);
  letter-spacing: 0.02em;
}
.df-lang__menu {
  position: absolute;
  top: calc(100% + var(--df-space-2));
  right: 0;
  z-index: var(--df-z-dropdown);
  min-width: 168px;
  margin: 0;
  padding: var(--df-space-1);
  list-style: none;
  background: var(--df-surface);
  border: var(--df-rule) solid var(--df-border);
  border-radius: var(--df-radius-card);
  box-shadow: var(--df-shadow-lift);
  display: none;
}
.df-lang.open .df-lang__menu { display: block; }
.df-lang__option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--df-space-4);
  min-height: var(--df-control-md);
  padding: var(--df-space-2) var(--df-space-3);
  border-radius: var(--df-radius-control);
  font-size: var(--df-text-body);
  color: var(--df-ink-body);
  white-space: nowrap;
  transition: background-color var(--df-dur-micro) var(--df-ease),
              color var(--df-dur-micro) var(--df-ease);
}
.df-lang__option:hover { background: var(--df-surface-sunk); color: var(--df-ink-strong); }
.df-lang__option.is-active { color: var(--df-action-link); font-weight: var(--df-weight-strong); }
.df-lang__code {
  font-size: var(--df-text-small);
  font-weight: var(--df-weight-strong);
  /* ink-body, not ink-muted: on the sunk hover surface muted drops to 4.4:1. */
  color: var(--df-ink-body);
}

/* ============================================================
   Buttons — §10 geometry: 32 / 40 / 48px heights, 8px radius.
   One primary per main region; destructive never wears the action colour.
   ============================================================ */
.df-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--df-space-2);
  height: var(--df-control-md);
  padding-inline: var(--df-space-5);
  border: var(--df-rule) solid transparent;
  border-radius: var(--df-radius-control);
  font-family: inherit;
  font-size: var(--df-text-body);
  font-weight: var(--df-weight-strong);
  line-height: 1;
  /* A clickable label is a one-line object. */
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--df-dur-micro) var(--df-ease),
              border-color var(--df-dur-micro) var(--df-ease),
              color var(--df-dur-micro) var(--df-ease);
}
.df-btn--sm { height: var(--df-control-sm); padding-inline: var(--df-space-4); }
.df-btn--lg { height: var(--df-control-lg); padding-inline: var(--df-space-6); font-size: var(--df-text-card); }

/* Eight states. Hover lifts the control by exactly 1px and the press settles
   it by 1px — motion primitive #2, and the only transform a button ever gets.
   No scale, no bounce, no shadow animation. */
.df-btn:hover { transform: translateY(-1px); }
.df-btn:active { transform: translateY(1px); }
.df-btn { transition: background-color var(--df-dur-micro) var(--df-ease),
                      border-color var(--df-dur-micro) var(--df-ease),
                      color var(--df-dur-micro) var(--df-ease),
                      transform var(--df-dur-micro) var(--df-ease); }
/* Reduced motion means the spatial move does not happen at all, not that it
   happens in 0.01ms — the transition override alone would still teleport it. */
@media (prefers-reduced-motion: reduce) {
  .df-btn:hover,
  .df-btn:active { transform: none; }
}
.df-btn[disabled],
.df-btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

/* No borders in this family. The primary is a filled indigo block (§2) — the
   fill carries the control, so there is no edge left to draw. That frees the
   secondary to drop to the §4 ghost tier: on a white body its only substance
   was the hairline, and once that goes it should read as the text action it
   is, not as an empty box. Hierarchy is now fill vs. no-fill, which is a
   louder separation than the two-weights-of-border pair it replaces.
   Geometry is untouched — .df-btn still reserves a 1px transparent border, so
   the 40px control row lines up exactly as before. */
.df-btn--primary {
  background: var(--df-cta-bg);
  color: var(--df-cta-ink);
}
.df-btn--primary:hover,
.df-btn--primary:active { background: var(--df-cta-hover-bg); }

.df-btn--secondary {
  background: transparent;
  color: var(--df-ink-strong);
}
.df-btn--secondary:hover { background: var(--df-ghost-hover-bg); }
.df-btn--secondary:active { background: var(--df-ghost-active-bg); }

/* ============================================================
   Badges — always paired with a text label, never colour alone.
   ============================================================ */
.df-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-1);
  padding: var(--df-space-1) var(--df-space-2);
  border-radius: var(--df-radius-pill);
  font-size: var(--df-text-small);
  font-weight: var(--df-weight-strong);
  line-height: 1.5;
  white-space: nowrap;
}
.df-badge--verified { background: var(--df-accent-soft); color: var(--df-accent); }
.df-badge--now     { background: var(--df-success-100); color: var(--df-success-700); }
.df-badge--next    { background: var(--df-info-100); color: var(--df-info-700); }
.df-badge--later   { background: var(--df-slate-100); color: var(--df-ink-body); }
[data-theme="dark"] .df-badge--later { background: var(--df-surface-sunk); }

/* ============================================================
   Footer — a structural close, not a sitemap.

   `Connect. Ask. Decide.` is set at display size and carries the closing beat;
   two link groups sit beside it. There is no third or fourth column, because
   there is no third or fourth destination.
   ============================================================ */
.df-foot {
  border-top: var(--df-rule) solid var(--df-border);
  padding: var(--df-space-16) var(--df-gutter) var(--df-space-8);
}
.df-foot__inner {
  max-width: var(--df-page-max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--df-space-12) var(--df-space-16);
  align-items: start;
}
.df-foot__mast { min-width: 0; }
.df-foot__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-2);
  font-size: var(--df-text-card);
  font-weight: var(--df-weight-display);
  letter-spacing: -0.015em;
  color: var(--df-ink-strong);
}
.df-foot__statement {
  margin-top: var(--df-space-5);
  font-family: var(--df-font-display);
  font-size: var(--df-text-display);
  font-weight: var(--df-weight-display);
  line-height: var(--df-leading-tight);
  letter-spacing: -0.025em;
  color: var(--df-ink-strong);
  overflow-wrap: anywhere;
  min-width: 0;
}
.df-foot__description {
  max-width: 46ch;
  margin-top: var(--df-space-4);
  font-size: var(--df-text-body);
  line-height: var(--df-leading-body);
  color: var(--df-ink-body);
}

.df-foot__groups {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--df-space-8);
}
.df-foot__group-title {
  font-size: var(--df-text-small);
  font-weight: var(--df-weight-strong);
  /* ink-body, not muted: a 12px group heading has to clear AA on the canvas. */
  color: var(--df-ink-body);
  letter-spacing: 0.01em;
}
.df-foot__group ul {
  margin: var(--df-space-4) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--df-space-1);
}
.df-foot__group a {
  display: inline-flex;
  align-items: center;
  min-height: var(--df-control-sm);
  font-size: var(--df-text-body);
  font-weight: var(--df-weight-medium);
  color: var(--df-ink-body);
  white-space: nowrap;
  transition: color var(--df-dur-micro) var(--df-ease);
}
.df-foot__group a:hover { color: var(--df-action-link); }

.df-foot__legal {
  max-width: var(--df-page-max);
  margin: var(--df-space-12) auto 0;
  padding-top: var(--df-space-5);
  border-top: var(--df-rule) solid var(--df-border);
  font-size: var(--df-text-small);
  color: var(--df-ink-muted);
}

/* ============================================================
   Auth form leftovers still shared with the platform pages.

   The centred auth card that used to live here (.pub-auth / .pub-card /
   .pub-input / .pub-form-row …) is gone along with `Layouts/Auth.html`: the
   sign-in, sign-up and reset pages are the full-bleed split in
   `Css/Pages/Auth.css` now. What is left below is the vocabulary the platform
   pages still bind to.
   ============================================================ */
.pub-form-error {
  font-size: var(--df-text-body);
  color: var(--df-danger-700);
  background: var(--df-danger-100);
  border: var(--df-rule) solid var(--df-danger-700);
  border-radius: var(--df-radius-control);
  padding: var(--df-space-3);
  margin-bottom: var(--df-space-4);
}
.pub-form-foot {
  text-align: center;
  font-size: var(--df-text-body);
  color: var(--df-ink-body);
  margin-top: var(--df-space-5);
}
.pub-form-foot a { color: var(--df-action-link); font-weight: var(--df-weight-strong); }
.pub-block { width: 100%; }

/* DesignPack ships a gold `--color-primary` in dark mode and its own control
   geometry; the error pages use `.btn.btn-primary`, so pin them to the
   Datafluvia action token and the standard control spec. (The auth pages used
   to be the other consumer; they now carry `.auth-btn` from Pages/Auth.css.) */
.pub-shell .btn {
  font-family: var(--df-font-sans);
  min-height: var(--df-control-md);
  border-radius: var(--df-radius-control);
  transition: background-color var(--df-dur-micro) var(--df-ease),
              border-color var(--df-dur-micro) var(--df-ease);
}
.pub-shell .btn:disabled { opacity: 0.55; cursor: not-allowed; }
.pub-shell .btn-primary {
  background: var(--df-action);
  border-color: var(--df-action);
  color: var(--df-action-ink);
}
.pub-shell .btn-primary:hover {
  background: var(--df-action-hover);
  border-color: var(--df-action-hover);
  box-shadow: var(--dp-shadow-control-inset);
}

/* ============================================================
   Platform sign-in — Datafluvia staff, not tenants.
   AdminPanelTasks C0-2: the platform context must be visible at all times and
   must never be mistaken for tenant chrome. On the platform shell that job
   falls to one solid pill, because there is no platform sidebar or topbar yet.

   These pieces are shared with `Css/Pages/PlatformDoor.css`, which owns the
   platform door's action column; what lives here is the vocabulary that column
   uses — the context pill, the Microsoft button, the notice and the fact rows.
   (It used to say `PlatformAuth.css`, a second two-pane shell that was retired
   when the access-denied page joined the login door on `Layouts/AuthSplit.html`.)
   ============================================================ */
.pub-context {
  display: flex;
  align-items: center;
  gap: var(--df-space-2);
  margin-bottom: var(--df-space-4);
  font-size: var(--df-text-small);
  color: var(--df-ink-body);
}

/* Inverted rather than tinted: the other badges are status (success/info/
   slate) and a fifth tint would read as a sixth status. Solid ink reads as
   "different context", which is what it is. Flips correctly in dark, where
   ink-strong is white and surface is navy. */
.df-badge--platform {
  background: var(--df-ink-strong);
  color: var(--df-surface);
  letter-spacing: .01em;
}

/* Informational, not alarming — distinct from .pub-form-error, which is red
   because something the user did failed. A missing server config did not. */
.pub-notice {
  font-size: var(--df-text-body);
  color: var(--df-info-700);
  background: var(--df-info-100);
  border: var(--df-rule) solid var(--df-info-700);
  border-radius: var(--df-radius-control);
  padding: var(--df-space-3);
  margin-bottom: var(--df-space-4);
}
.pub-notice__title {
  display: block;
  margin-bottom: var(--df-space-1);
  font-weight: var(--df-weight-strong);
}

/* Label/value pairs on the platform landing card. A <dl>, because that is what
   a set of term-definition rows is — the shape carries to a screen reader. */
.pub-facts {
  margin: 0 0 var(--df-space-5);
  border-top: var(--df-rule) solid var(--df-border);
}
.pub-facts__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--df-space-4);
  padding: var(--df-space-3) 0;
  border-bottom: var(--df-rule) solid var(--df-border);
}
.pub-facts__row dt {
  font-size: var(--df-text-small);
  color: var(--df-ink-muted);
}
.pub-facts__row dd {
  margin: 0;
  font-size: var(--df-text-body);
  font-weight: var(--df-weight-strong);
  color: var(--df-ink);
  text-align: right;
  /* An e-mail address is the longest value here and must not push the label
     off the card on a narrow viewport. */
  overflow-wrap: anywhere;
}

/* ============================================================
   Error pages
   ============================================================ */
.pub-error {
  text-align: center;
  max-width: 480px;
  margin: var(--df-space-10) auto;
  padding: var(--df-space-16) var(--df-space-6);
}
.pub-error-code {
  font-size: 72px;
  font-weight: var(--df-weight-display);
  letter-spacing: -0.03em;
  line-height: 1;
  margin: 0;
  color: var(--df-action);
  font-variant-numeric: tabular-nums;
}
.pub-error h1 {
  font-size: var(--df-text-title);
  font-weight: var(--df-weight-display);
  letter-spacing: -0.02em;
  margin: var(--df-space-5) 0 var(--df-space-2);
}
.pub-error p {
  font-size: var(--df-text-card);
  color: var(--df-ink-body);
  margin: 0 0 var(--df-space-6);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 62rem) {
  .df-nav__rule { display: none; }
  .df-nav .df-nav__burger { display: inline-flex; }
  /* The links go into the disclosure, taking their auto margins with them, so
     the job of pushing the right-hand group over falls to the actions. */
  .df-nav__actions { margin-left: auto; }

  /* The collapsed pill drops links *and* the theme/language controls into one
     panel beneath itself — the pill keeps only the brand, the primary action
     and the disclosure button, which is what fits at 320px. */
  .df-nav__pill { position: relative; }
  .df-nav__collapse { display: none; }
  .df-nav__collapse.open {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--df-space-2);
    position: absolute;
    top: calc(100% + var(--df-space-2));
    left: 0;
    right: 0;
    padding: var(--df-space-2);
    background: var(--df-surface);
    border: var(--df-rule) solid var(--df-border);
    border-radius: var(--df-radius-card);
    box-shadow: var(--df-shadow-lift);
  }
  .df-nav__collapse.open .df-nav__links {
    flex-direction: column;
    align-items: stretch;
    gap: var(--df-space-1);
    /* Stacked, the centring margins would centre the list in the panel and
       leave the rows floating; here they run edge to edge. */
    margin: 0;
  }
  .df-nav__collapse.open .df-nav__link { height: var(--df-control-lg); justify-content: flex-start; }
  .df-nav__collapse.open .df-nav__controls {
    margin-left: 0;
    padding-top: var(--df-space-2);
    border-top: var(--df-rule) solid var(--df-border);
  }
  /* Dropped out of the pill, the menu is the only place the language list can
     open — it needs room below the trigger, not above the panel edge. */
  .df-nav__collapse.open .df-lang__menu { right: auto; left: 0; }
}

@media (max-width: 40rem) {
  .pub-main { padding: var(--df-space-10) clamp(1rem, 4vw, 1.5rem) var(--df-space-16); }
  .df-nav { padding-inline: clamp(1rem, 4vw, 1.5rem); }
  .df-nav__pill {
    width: 100%;
    gap: var(--df-space-2);
    padding-left: var(--df-space-3);
  }
  .df-nav__actions .df-btn--sm { height: 44px; }
  /* At 375px the pill has ~343px to spend and the brand wordmark costs ~82 of
     them. The mark alone still identifies the page, and the name is one line
     down in the <title> and the footer, so the wordmark is what gives way —
     not the primary action. */
  .df-nav__wordmark { display: none; }
  .df-icon-btn { width: 44px; height: 44px; }
  .df-foot { padding-top: var(--df-space-12); }
  .df-foot__inner { grid-template-columns: minmax(0, 1fr); gap: var(--df-space-10); }
  .df-foot__groups { gap: var(--df-space-6); }
  /* WCAG 2.2 AA target size — a text link is still a tap target. */
  .df-foot__group a { min-height: 44px; }
  .df-foot__legal { margin-top: var(--df-space-10); }
  .pub-error { padding: var(--df-space-12) var(--df-space-5); }
  .pub-error-code { font-size: 56px; }
}
