/*
 * Reusable components. Requires tokens.css and base.css.
 * Nothing here depends on the catalogue layout in catalogue.css.
 */

/* =========================================================
   Material: frosted surface
   ========================================================= */

.surface-frost {
  position: relative;
  isolation: isolate;
  background: var(--frost-fill);
  border: var(--border-hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--frost-highlight), var(--frost-shadow);
  -webkit-backdrop-filter: blur(var(--frost-blur)) saturate(var(--frost-saturate));
  backdrop-filter: blur(var(--frost-blur)) saturate(var(--frost-saturate));
}

.surface-frost::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background-image: var(--grain);
  opacity: calc(var(--grain-opacity) * 0.8);
  mix-blend-mode: multiply;
  pointer-events: none;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .surface-frost { background: var(--frost-fill-strong); }
}

/* =========================================================
   Buttons: primary · secondary · quiet
   ========================================================= */

.button {
  --button-bg: transparent;
  --button-bg-hover: var(--button-bg);
  --button-fg: var(--text-primary);
  --button-border: transparent;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  padding: 0 var(--space-4);
  border: 1px solid var(--button-border);
  border-radius: var(--radius-sm);
  background: var(--button-bg);
  color: var(--button-fg);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: var(--weight-medium);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

.button:hover { background: var(--button-bg-hover); }
.button:active { transform: translateY(1px); }

.button--primary {
  --button-bg: var(--color-ink-900);
  --button-bg-hover: #2c2f37;
  --button-fg: var(--color-paper-0);
  --button-border: var(--color-ink-900);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.12), 0 1px 2px rgb(27 29 34 / 0.16);
}

.button--secondary {
  --button-bg: var(--frost-fill-strong);
  --button-bg-hover: var(--color-white);
  --button-border: var(--color-line-strong);
  box-shadow: var(--frost-highlight);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.button--quiet {
  --button-bg-hover: rgb(27 29 34 / 0.05);
  padding: 0 var(--space-3);
}

.button--sm {
  min-height: var(--control-height-sm);
  padding: 0 var(--space-3);
  font-size: 0.875rem;
}

.button:disabled,
.button[aria-disabled="true"] {
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.button--primary:disabled,
.button--primary[aria-disabled="true"]:not([aria-busy="true"]) {
  --button-bg: var(--color-paper-2);
  --button-bg-hover: var(--color-paper-2);
  --button-border: var(--color-paper-2);
  --button-fg: var(--color-ink-500);
}

.button--secondary:disabled,
.button--secondary[aria-disabled="true"]:not([aria-busy="true"]),
.button--quiet:disabled,
.button--quiet[aria-disabled="true"]:not([aria-busy="true"]) {
  --button-bg-hover: var(--button-bg);
  --button-fg: var(--text-disabled);
}

.button__arrow {
  display: inline-block;
  transition: transform var(--duration-base) var(--ease-out);
}

.button:hover .button__arrow { transform: translateX(2px); }

/* Busy: the label keeps its width; a spinner replaces it visually. */
.button[aria-busy="true"] {
  cursor: progress;
  color: transparent;
}

.button[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1rem;
  height: 1rem;
  border: 1.5px solid var(--button-fg);
  border-right-color: transparent;
  border-radius: 50%;
  animation: ha-spin 700ms linear infinite;
}

@keyframes ha-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .button[aria-busy="true"]::after { animation-duration: 2.4s; }
}

.button-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* =========================================================
   Form controls
   ========================================================= */

.field {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

.field__label {
  font-size: var(--type-label-size);
  line-height: var(--type-label-line);
  font-weight: 500;
}

.field__optional {
  color: var(--text-meta);
  font-weight: 400;
}

.field__hint,
.field__error {
  font-size: var(--type-small-size);
  line-height: var(--type-small-line);
}

.field__hint { color: var(--text-meta); }

.field__error {
  display: none;
  color: var(--state-error-text);
}

.field[data-invalid="true"] .field__error { display: block; }
.field[data-invalid="true"] .field__hint { display: none; }

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--control-height);
  padding: 0 var(--space-3);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-sm);
  background-color: var(--frost-fill-strong);
  box-shadow: inset 0 1px 2px rgb(27 29 34 / 0.04);
  font-size: 1rem; /* 16px prevents zoom on iOS focus */
  line-height: 1.4;
  transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}

.textarea {
  min-height: 5.5rem;
  padding: var(--space-3);
  resize: vertical;
}

.input::placeholder,
.textarea::placeholder { color: var(--color-ink-300); }

.input:hover,
.select:hover,
.textarea:hover { border-color: rgb(27 29 34 / 0.28); }

.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
  outline: none;
  border-color: var(--color-electric);
  box-shadow: 0 0 0 3px rgb(46 91 255 / 0.18);
}

.input[aria-invalid="true"],
.textarea[aria-invalid="true"] {
  border-color: var(--state-error);
  background-color: rgb(255 255 255 / 0.92);
}

.input[aria-invalid="true"]:focus-visible { box-shadow: 0 0 0 3px rgb(228 100 75 / 0.22); }

.input:disabled,
.select:disabled,
.textarea:disabled {
  background-color: var(--surface-recessed);
  color: var(--text-disabled);
  cursor: not-allowed;
}

.input--mono {
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: 0.9375rem;
}

.select {
  appearance: none;
  padding-right: 2.5rem;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-ink-700) 50%),
    linear-gradient(135deg, var(--color-ink-700) 50%, transparent 50%);
  background-position: calc(100% - 19px) 52%, calc(100% - 14px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* Checkbox and radio */
.choice-group {
  display: grid;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.choice-group > legend {
  padding: 0;
  margin-bottom: var(--space-1);
}

.choice {
  display: grid;
  grid-template-columns: 1.125rem 1fr;
  align-items: start;
  column-gap: var(--space-3);
  min-height: var(--control-height-sm);
  padding-block: var(--space-2);
  cursor: pointer;
}

.choice__input {
  appearance: none;
  display: grid;
  place-content: center;
  width: 1.125rem;
  height: 1.125rem;
  margin: 0.125rem 0 0;
  border: 1px solid rgb(27 29 34 / 0.34);
  border-radius: 5px;
  background: var(--color-white);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}

.choice__input[type="radio"] { border-radius: 50%; }

.choice__input::before {
  content: "";
  width: 0.625rem;
  height: 0.625rem;
  background: var(--color-paper-0);
  clip-path: polygon(14% 52%, 0 66%, 38% 100%, 100% 22%, 86% 9%, 37% 72%);
  transform: scale(0);
  transition: transform var(--duration-fast) var(--ease-out);
}

.choice__input[type="radio"]::before {
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  clip-path: none;
}

.choice__input:checked {
  background: var(--color-ink-900);
  border-color: var(--color-ink-900);
}

.choice__input:checked::before { transform: scale(1); }

.choice__input:disabled {
  background: var(--surface-recessed);
  border-color: var(--color-line-strong);
  cursor: not-allowed;
}

.choice__text { display: grid; gap: 2px; min-width: 0; }
.choice__title { font-size: 1rem; line-height: 1.4; }
.choice__hint { font-size: var(--type-small-size); line-height: 1.45; color: var(--text-meta); }
.choice__hint code { font-size: 0.75rem; }

/* Switch */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--control-height-sm);
  cursor: pointer;
}

.switch__input {
  appearance: none;
  position: relative;
  flex: none;
  width: 2.5rem;
  height: 1.5rem;
  margin: 0;
  border-radius: var(--radius-pill);
  background: var(--color-paper-2);
  box-shadow: inset 0 0 0 1px var(--color-line-strong);
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease-out);
}

.switch__input::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  background: var(--color-white);
  box-shadow: 0 1px 2px rgb(27 29 34 / 0.22);
  transition: transform var(--duration-base) var(--ease-out);
}

.switch__input:checked {
  background: var(--color-electric);
  box-shadow: none;
}

.switch__input:checked::before { transform: translateX(1rem); }

.switch__text { font-size: 1rem; line-height: 1.4; }

/* =========================================================
   Status chips: connected · pending · error · trust
   Neutral chip; only the marker carries colour, and each state
   has a distinct marker shape so meaning survives without colour.
   ========================================================= */

.status {
  --status-marker: var(--color-ink-300);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 1.625rem;
  padding: 0 var(--space-3) 0 var(--space-2);
  border: var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--frost-fill-strong);
  box-shadow: var(--frost-highlight);
  color: var(--text-secondary);
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: var(--type-meta-size);
  line-height: 1;
  white-space: nowrap;
}

.status::before {
  content: "";
  flex: none;
  width: 0.4375rem;
  height: 0.4375rem;
  margin-left: 2px;
  border-radius: 50%;
  background: var(--status-marker);
}

/* Connected: solid dot */
.status[data-state="connected"] { --status-marker: var(--state-connected); }

/* Pending: open ring, slowly rotating */
.status[data-state="pending"] { --status-marker: transparent; }

.status[data-state="pending"]::before {
  width: 0.5rem;
  height: 0.5rem;
  border: 1.5px solid var(--color-ink-500);
  border-right-color: transparent;
  animation: ha-spin 1.2s linear infinite;
}

/* Error: small diamond */
.status[data-state="error"] { --status-marker: var(--state-error); }

.status[data-state="error"]::before {
  border-radius: 1px;
  transform: rotate(45deg);
}

/* Trust: check in ink */
.status[data-state="trust"] { --status-marker: var(--state-trust); }

.status[data-state="trust"]::before {
  width: 0.5625rem;
  height: 0.4375rem;
  border-radius: 0;
  clip-path: polygon(14% 52%, 0 66%, 38% 100%, 100% 22%, 86% 9%, 37% 72%);
}

@media (prefers-reduced-motion: reduce) {
  .status[data-state="pending"]::before {
    animation: none;
    border-style: dotted;
    border-right-color: var(--color-ink-500);
  }
}

/* =========================================================
   Information hierarchy
   Every card orders its content in the same six levels, and
   skips the ones it does not need:

   1 Context   .card__header   what kind of thing, when, state   mono 12
   2 Identity  .entity         who or what it is about            sans 14–15 / 500
   3 Message   .card__title    the one thing to understand        sans 17 or 20 / 500
   4 Detail    .card__text     at most two sentences              sans 14 / Ink 700
   5 Evidence  .facts, .meta-row, .disclosure  identifiers        mono 12
   6 Action    .card__footer   at most one primary action

   Limits per card: one title, one status, three text sizes,
   one primary action. Identifiers never appear in titles.
   ========================================================= */

/* =========================================================
   Entity: media + name + meta + optional trailing slot
   ========================================================= */

.entity {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.entity__media {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 10px;
  background: var(--color-white);
  box-shadow: inset 0 0 0 1px var(--color-line), 0 1px 2px rgb(27 29 34 / 0.05);
}

.entity__media > img {
  width: 1.25rem;
  height: 1.25rem;
}

.entity__text {
  display: grid;
  flex: 1;
  gap: 2px;
  min-width: 0;
}

.entity__name {
  overflow: hidden;
  font-size: 1rem;
  font-weight: var(--weight-strong);
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entity__meta {
  overflow: hidden;
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: var(--type-meta-size);
  line-height: var(--type-meta-line);
  color: var(--text-meta);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entity__trailing {
  flex: none;
  margin-left: auto;
}

/* A vertical list of entities, separated by hairlines. */
.entity-list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.entity-list > li { padding: var(--space-3) 0; }
.entity-list > li:first-child { padding-top: 0; }
.entity-list > li:last-child { padding-bottom: 0; }
.entity-list > li + li { border-top: var(--border-hairline); }

/* Small: inline attribution in footers and sentences. */
.entity--sm { gap: var(--space-2); }

.entity--sm .entity__media {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 6px;
}

.entity--sm .entity__media > img {
  width: 0.8125rem;
  height: 0.8125rem;
}

.entity--sm .entity__name {
  font-size: var(--type-small-size);
}

/* Overlapping media for a group of entities. */
.entity-stack {
  display: flex;
  flex: none;
}

.entity-stack > .entity__media {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 7px;
  box-shadow: 0 0 0 2px var(--color-paper-0), inset 0 0 0 1px var(--color-line);
}

.entity-stack > .entity__media + .entity__media { margin-left: -0.375rem; }

.entity-stack > .entity__media > img {
  width: 0.875rem;
  height: 0.875rem;
}

.entity-stack__more {
  display: grid;
  place-items: center;
  min-width: 1.75rem;
  height: 1.75rem;
  margin-left: -0.375rem;
  padding: 0 0.3125rem;
  border-radius: 7px;
  background: var(--color-paper-1);
  box-shadow: 0 0 0 2px var(--color-paper-0), inset 0 0 0 1px var(--color-line);
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: 0.6875rem;
  color: var(--text-secondary);
}

/* =========================================================
   Option list: a single choice between entities, inside a card.
   Native radios; rows are separated by space, not borders.
   ========================================================= */

.option-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.option {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 3.25rem;
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}

.option:hover { background: rgb(27 29 34 / 0.035); }

.option__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.option > .entity { flex: 1; }

.option__indicator {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--color-line-strong);
  transition: box-shadow var(--duration-fast) var(--ease-out);
}

.option:has(.option__input:checked) {
  background: var(--color-white);
  box-shadow: inset 0 0 0 1px var(--color-line), 0 1px 2px rgb(27 29 34 / 0.05);
}

.option:has(.option__input:checked) .option__indicator {
  box-shadow: inset 0 0 0 5px var(--color-ink-900);
}

.option:has(.option__input:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

.option__placeholder {
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: 0.75rem;
  color: var(--text-meta);
}

/* =========================================================
   Card: fixed slots, one frosted surface
   ========================================================= */

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  min-width: 0;
  padding: var(--space-5);
}

.card__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  min-height: 1.625rem;
}

.card__main {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

.card__title {
  font-family: var(--font-sans);
  font-size: var(--type-title-card-size);
  font-weight: 500;
  line-height: var(--type-title-line);
  letter-spacing: var(--type-title-track);
  text-wrap: balance;
}

.card--dialog .card__title { font-size: var(--type-title-dialog-size); }

.card__text {
  font-size: var(--type-ui-size);
  line-height: var(--type-ui-line);
  color: var(--text-secondary);
  text-wrap: pretty;
}

.card__text--clamp {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

.card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 2.25rem;
  margin-top: auto; /* footers align across cards of different length */
  padding-top: var(--space-4);
  border-top: var(--border-hairline);
}

.card__footer > .entity { flex: 0 1 auto; }
.card__footer > :not(.entity) { flex: none; }
.card__footer > .card__note { flex: 1 1 auto; }

.card__note {
  display: flex;
  gap: var(--space-3);
  font-size: var(--type-small-size);
  line-height: var(--type-small-line);
  color: var(--text-secondary);
}

.card__note > .t-meta { flex: none; padding-top: 1px; }

/* =========================================================
   Evidence: meta row, facts, disclosure
   ========================================================= */

.meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: var(--type-meta-size);
  line-height: var(--type-meta-line);
  color: var(--text-meta);
}

.facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-2) var(--space-5);
  margin: 0;
}

.facts > dt {
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: var(--type-meta-size);
  line-height: 1.6;
  color: var(--text-meta);
}

.facts > dd {
  min-width: 0;
  font-size: var(--type-small-size);
  line-height: var(--type-small-line);
  overflow-wrap: anywhere;
}

.facts > dd code { font-size: var(--type-meta-size); }

.disclosure {
  border-top: var(--border-hairline);
}

.disclosure__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 2.5rem;
  padding-top: var(--space-2);
  font-size: var(--type-small-size);
  color: var(--text-meta);
  list-style: none;
  cursor: pointer;
}

.disclosure__summary::-webkit-details-marker { display: none; }

.disclosure__summary::after {
  content: "";
  width: 0.4375rem;
  height: 0.4375rem;
  margin-right: 2px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--duration-base) var(--ease-out);
}

.disclosure[open] > .disclosure__summary::after { transform: translateY(1px) rotate(225deg); }
.disclosure__summary:hover { color: var(--text-primary); }

.disclosure__body { padding: var(--space-2) 0 var(--space-1); }

/* =========================================================
   Permission list: what a grant allows, in plain language
   ========================================================= */

.permissions {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.permission {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  align-items: baseline;
  gap: var(--space-3);
  font-size: var(--type-ui-size);
  line-height: var(--type-ui-line);
}

.permission::before {
  content: "";
  width: 0.625rem;
  height: 0.5rem;
  transform: translateY(-1px);
  background: var(--color-ink-900);
  clip-path: polygon(14% 52%, 0 66%, 38% 100%, 100% 22%, 86% 9%, 37% 72%);
}

.permission[data-kind="deny"] { color: var(--text-meta); }

.permission[data-kind="deny"]::before {
  height: 1px;
  transform: translateY(-4px);
  background: var(--color-ink-300);
  clip-path: none;
}

/* =========================================================
   Notices: compact card
   ========================================================= */

.notice {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5) var(--space-5);
  border: var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--frost-fill-strong);
  box-shadow: var(--frost-highlight);
}

.notice__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.notice__title { font-size: 1rem; font-weight: var(--weight-strong); line-height: 1.4; }
.notice__body { font-size: var(--type-small-size); line-height: var(--type-small-line); color: var(--text-secondary); }
.notice__body code { font-size: 0.75rem; overflow-wrap: anywhere; }

/* =========================================================
   Provider / model identity tokens
   Third-party marks from style-guide/shared/assets/logos/,
   referenced as <img> so they also load from file://.
   Never used as Hey Aira branding.
   ========================================================= */

/*
 * Colour policy for marks from shared/assets/logos/:
 * - use the brand's colour file (*-color.svg) when the brand has one;
 * - brands whose mark is monochrome (OpenAI, xAI, Anthropic) use the
 *   monochrome file, softened so it never reads as heavy black;
 * - unavailable or disabled entities show every mark in greyscale.
 */
img[src*="/logos/"]:not([src$="-color.svg"]) { opacity: 0.78; }

.provider[aria-pressed="true"] img[src*="/logos/"],
.option:has(.option__input:checked) img[src*="/logos/"] { opacity: 1; }

.provider-mark {
  flex: none;
  display: block;
  width: var(--provider-mark-size, 1.25rem);
  height: var(--provider-mark-size, 1.25rem);
}

.provider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  min-height: 3.25rem;
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  border: var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--frost-fill);
  box-shadow: var(--frost-highlight);
  color: var(--text-primary);
  text-align: left;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.provider > .entity { flex: 1; }
.provider .entity__media { width: 2.25rem; height: 2.25rem; border-radius: 9px; }
.provider .entity__name { font-size: var(--type-ui-size); }

/* Chip form for inline use in sentences. */
.provider--chip {
  --provider-mark-size: 0.875rem;
  display: inline-flex;
  gap: var(--space-2);
  max-width: 100%;
  min-height: 1.75rem;
  padding: 0 var(--space-3) 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--frost-fill-strong);
  font-size: var(--type-small-size);
  font-weight: 500;
  white-space: nowrap;
  vertical-align: middle;
}

.provider--chip > span {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Selectable form. */
button.provider {
  width: 100%;
  font: inherit;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-out), background-color var(--duration-fast) var(--ease-out);
}

button.provider:hover {
  border-color: var(--color-line-strong);
  background: var(--frost-fill-strong);
}

.provider[aria-pressed="true"] {
  border-color: var(--color-ink-900);
  background: var(--color-white);
  box-shadow: inset 0 0 0 1px var(--color-ink-900);
}

.provider__check {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--color-line-strong);
}

.provider[aria-pressed="true"] .provider__check {
  background: var(--color-ink-900);
  box-shadow: none;
  -webkit-mask: radial-gradient(circle, transparent 0 2.5px, #000 3px);
  mask: radial-gradient(circle, transparent 0 2.5px, #000 3px);
}

button.provider:disabled {
  border-style: dashed;
  background: transparent;
  box-shadow: none;
  cursor: not-allowed;
}

button.provider:disabled .entity__name { color: var(--text-meta); }
button.provider:disabled .entity__media > img { opacity: 0.4; filter: grayscale(1); }

/* =========================================================
   Segmented control (native radios)
   ========================================================= */

.segmented {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  min-width: 0;
  margin: 0;
  padding: 3px;
  border: var(--border-hairline);
  border-radius: 10px;
  background: rgb(235 230 222 / 0.6);
}

.segmented__option { position: relative; }

.segmented__input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.segmented__label {
  display: grid;
  place-items: center;
  min-height: 2.25rem;
  padding: 0 var(--space-3);
  border-radius: 7px;
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: var(--type-meta-size);
  color: var(--text-meta);
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}

.segmented__input:hover + .segmented__label { color: var(--text-primary); }

.segmented__input:checked + .segmented__label {
  background: var(--color-white);
  color: var(--text-primary);
  box-shadow: 0 1px 2px rgb(27 29 34 / 0.1), inset 0 0 0 1px var(--color-line);
}

.segmented__input:focus-visible + .segmented__label {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

/* =========================================================
   OAuth / MCP authorization card
   A .card.card--dialog. Root data-state:
   request | authorizing | connected | error.
   Children with data-when="…" render only in the listed states.

   Order: context (Hey Aira, state) → client entity → one question
   → what it allows → technical details (collapsed) → two actions.
   ========================================================= */

.auth-card {
  width: 100%;
  max-width: 23.5rem;
  gap: var(--space-5);
  container-type: inline-size;
  container-name: auth-card;
}

.auth-card[data-state="request"] [data-when]:not([data-when~="request"]),
.auth-card[data-state="authorizing"] [data-when]:not([data-when~="authorizing"]),
.auth-card[data-state="connected"] [data-when]:not([data-when~="connected"]),
.auth-card[data-state="error"] [data-when]:not([data-when~="error"]) {
  display: none;
}

.auth-card__decision {
  display: grid;
  gap: var(--space-4);
}

.auth-card__body {
  display: grid;
  gap: var(--space-3);
}

/* Two equal actions at the end of a dialog card. */
.card__actions,
.auth-card__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}

.auth-card[data-state="authorizing"] .entity__media {
  animation: ha-breathe 1.6s var(--ease-out) infinite alternate;
}

@keyframes ha-breathe {
  to { box-shadow: inset 0 0 0 1px var(--color-line), 0 0 0 4px rgb(27 29 34 / 0.05); }
}

@media (prefers-reduced-motion: reduce) {
  .auth-card[data-state="authorizing"] .entity__media { animation: none; }
}

/* Narrow card: primary action first, full width. */
@container auth-card (max-width: 19rem) {
  .auth-card__actions { grid-template-columns: minmax(0, 1fr); }
  .auth-card__actions > .button--primary { order: -1; }
}

/* =========================================================
   Site footer
   A full section, not a line: one statement, three link groups,
   and a quiet base row with the Hey Aira name.
   ========================================================= */

.site-footer {
  margin-top: var(--space-8);
  border-top: var(--border-hairline);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-8);
  max-width: var(--layout-max);
  margin: 0 auto;
  padding: var(--space-8) var(--layout-gutter) var(--space-6);
}

.site-footer__lead {
  display: grid;
  justify-items: start;
  gap: var(--space-4);
}

.site-footer__statement {
  max-width: 18ch;
  font-family: var(--font-serif);
  font-size: var(--type-h2-size);
  font-weight: 400;
  line-height: var(--type-h2-line);
  letter-spacing: var(--type-h2-track);
  text-wrap: balance;
}

.site-footer__groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: var(--space-6) var(--space-7);
}

.site-footer__title {
  margin-bottom: var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--type-ui-size);
  font-weight: var(--weight-strong);
  line-height: 1.4;
  letter-spacing: var(--type-text-track);
}

.site-footer__links {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer__links a {
  display: inline-block;
  padding: 2px 0;
  color: var(--text-secondary);
  font-size: var(--type-ui-size);
  line-height: 1.45;
  text-decoration: none;
}

.site-footer__links a:hover {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  padding-top: var(--space-5);
  border-top: var(--border-hairline);
}

.site-footer__legal {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--text-meta);
}

@media (min-width: 60rem) {
  .site-footer { margin-top: var(--space-9); }

  .site-footer__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    column-gap: var(--space-8);
    padding-top: var(--space-9);
  }

  .site-footer__base { grid-column: 1 / -1; }
}

/* =========================================================
   Toast
   ========================================================= */

.toast {
  position: fixed;
  bottom: max(var(--space-5), env(safe-area-inset-bottom));
  left: 50%;
  z-index: 50;
  max-width: calc(100vw - 2rem);
  overflow: hidden;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-ink-900);
  color: var(--color-paper-0);
  box-shadow: 0 10px 30px -12px rgb(27 29 34 / 0.45);
  font-family: var(--font-mono);
  letter-spacing: normal;
  font-size: var(--type-meta-size);
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 0.75rem);
  transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
}

.toast[data-visible="true"] {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* =========================================================
   Page patterns
   Reusable sections for product pages. They use the type roles
   from base.css unchanged and add no cards around content.
   ========================================================= */

/* ---------- Section head: what the section is, then what it says ---------- */

.section-head {
  display: grid;
  gap: var(--space-3);
}

.section-head > * { margin: 0; }

.section-head__label {
  font-family: var(--font-mono);
  font-size: var(--type-meta-size);
  line-height: var(--type-meta-line);
  letter-spacing: normal;
  color: var(--text-meta);
}

.section-head__lead {
  max-width: var(--layout-measure);
  color: var(--text-secondary);
}

/* Centred: label, heading and lead on the page axis. */
.section-head--center { justify-items: center; text-align: center; }

/* ---------- Logo row: the tools a product works with ---------- */

.logo-row {
  display: grid;
  gap: var(--space-5);
}

.logo-row > * { margin: 0; }

.logo-row__title {
  font-family: var(--font-sans);
  font-size: var(--type-small-size);
  font-weight: var(--weight-regular);
  line-height: var(--type-small-line);
  letter-spacing: var(--type-text-track);
  color: var(--text-meta);
}

.logo-row__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
  gap: var(--space-5) var(--space-2);
  padding: 0;
  list-style: none;
}

/* Mark and name share the page's left edge. */
.logo-row__item {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
}

.logo-row__item img {
  width: 2.25rem;
  height: 2.25rem;
}

/* Monochrome brand marks are softened so they never read as heavy black. */
.logo-row__item img[data-mono] { opacity: 0.8; }

.logo-row__name {
  font-size: var(--type-small-size);
  line-height: 1.3;
  color: var(--text-secondary);
}

@media (max-width: 29.99rem) {
  .logo-row__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------- Lanes: two ways of working joined by one state ----------
   Two frosted lanes with a hub between them: the brand dot, large, with
   the name inside and a short label below. No connecting lines. Lanes sit
   side by side on wide screens and stack on small ones. */

.lanes {
  --lanes-gap: 9rem;
  --lanes-inset: var(--space-6);
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--lanes-gap) minmax(0, 1fr);
  align-items: stretch;
  text-align: left;
}

.lanes__lane {
  display: grid;
  grid-template-rows: auto auto 1fr;
  gap: var(--space-2);
  padding: var(--space-5) var(--lanes-inset);
}

.lanes__lane > * { margin: 0; }

.lanes__title {
  font-family: var(--font-sans);
  font-size: var(--type-h3-size);
  font-weight: var(--weight-medium);
  line-height: var(--type-h3-line);
  letter-spacing: var(--type-h3-track);
}

.lanes__text {
  font-size: var(--type-ui-size);
  line-height: var(--type-ui-line);
  color: var(--text-secondary);
}

.lanes__tools {
  display: flex;
  flex-wrap: wrap;
  align-self: end;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) 0 0;
  list-style: none;
}

.lanes__tools li {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--type-small-size);
  color: var(--text-secondary);
}

.lanes__tools img { width: 1.25rem; height: 1.25rem; }
.lanes__tools img[data-mono] { opacity: 0.8; }

/* Hub: a light source, not a disc. A solid core, fully inside the gap,
   carries the name; a soft glow spreads from it under the frosted lanes
   and fades out, so the centre reads as the source both lanes draw on. */
.lanes__hub {
  --lanes-dot: 7rem;
  --lanes-glow: 36rem;
  position: relative;
  z-index: 0;
  display: grid;
  place-items: center;
}

.lanes__hub::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(var(--lanes-glow), 100vw);
  height: calc(var(--lanes-glow) * 0.7);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgb(46 91 255 / 0.5),
    rgb(46 91 255 / 0.22) 40%,
    rgb(46 91 255 / 0.07) 70%,
    rgb(46 91 255 / 0) 100%);
  pointer-events: none;
}

.lanes__lane { position: relative; z-index: 1; }

.lanes__dot {
  position: relative;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 2px;
  width: var(--lanes-dot);
  height: var(--lanes-dot);
  border-radius: 50%;
  background: var(--brand-dot-color);
  color: var(--color-white);
  font-family: var(--font-mono);
  letter-spacing: normal;
  text-align: center;
}

.lanes__dot-name {
  font-size: var(--type-ui-size);
  line-height: 1.3;
}

.lanes__dot-label {
  max-width: 5rem;
  font-size: 0.6875rem;
  line-height: 1.25;
  opacity: 0.82;
}

/* Stacked: the core sits in the gap between the lanes; the glow runs
   under the lane above and the lane below. */
@media (max-width: 47.99rem) {
  .lanes { grid-template-columns: minmax(0, 1fr); }
  .lanes__lane { padding: var(--lanes-inset) var(--space-5); }
  .lanes__hub { height: var(--lanes-gap); }
}

/* Logo row, centred: for use directly under a centred hero. */
.logo-row--center { justify-items: center; text-align: center; }
.logo-row--center .logo-row__list { width: 100%; }
.logo-row--center .logo-row__item { justify-items: center; }

/* ---------- Point list: parallel points of equal weight ---------- */

/* Separated by space alone: equal points need no rules between them. */
.point-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: var(--space-7) var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}

.point-list__item {
  display: grid;
  align-content: start;
  gap: var(--space-2);
}

.point-list__item > * { margin: 0; }

.point-list__text {
  font-size: var(--type-ui-size);
  line-height: var(--type-ui-line);
  color: var(--text-secondary);
}

/* ---------- Flow: steps in order, joined by one line ---------- */

.flow {
  --flow-node: 0.75rem;
  --flow-gap: var(--space-6);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--flow-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.flow__step {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding-top: var(--space-6);
}

/* Node */
.flow__step::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: var(--flow-node);
  height: var(--flow-node);
  border-radius: 50%;
  background: var(--surface-canvas);
  box-shadow: inset 0 0 0 1.5px var(--color-ink-700);
}

/* The last step ends in the brand dot. */
.flow__step:last-child::before {
  background: var(--brand-dot-color);
  box-shadow: none;
}

/* Line to the next node */
.flow__step::after {
  content: "";
  position: absolute;
  top: calc(var(--flow-node) / 2);
  left: calc(var(--flow-node) + var(--space-2));
  right: calc(var(--flow-gap) * -1 + var(--space-2));
  height: 1px;
  background: var(--color-line-strong);
}

.flow__step:last-child::after { display: none; }

.flow__text {
  margin: 0;
  font-size: var(--type-ui-size);
  line-height: var(--type-ui-line);
  color: var(--text-secondary);
}

@media (max-width: 47.99rem) {
  .flow { grid-template-columns: minmax(0, 1fr); --flow-gap: var(--space-5); }
  .flow__step { padding: 0 0 0 var(--space-6); }
  .flow__step::before { top: 0.35rem; }
  .flow__step::after {
    top: calc(0.35rem + var(--flow-node) + var(--space-2));
    bottom: calc(var(--flow-gap) * -1 + var(--space-2));
    left: calc(var(--flow-node) / 2);
    right: auto;
    width: 1px;
    height: auto;
  }
}

/* Flow, travelling (desktop): one brand dot moves along the line as the
   flow scrolls into view and stops at each step, so HeyAira is shown at
   every step, not only the last. Every step is an open ring. Needs
   scroll-driven animations; elsewhere, on small screens and with reduced
   motion, the static flow above is shown unchanged. */
@supports (animation-timeline: view()) {
  @media (min-width: 48rem) and (prefers-reduced-motion: no-preference) {
    .flow--travel {
      --flow-step: calc((100% - 2 * var(--flow-gap)) / 3 + var(--flow-gap));
      position: relative;
      view-timeline: --flow-travel block;
    }

    .flow--travel .flow__step:last-child::before {
      background: var(--surface-canvas);
      box-shadow: inset 0 0 0 1.5px var(--color-ink-700);
    }

    .flow--travel::before {
      content: "";
      position: absolute;
      z-index: 1;
      top: 0;
      left: 0;
      width: var(--flow-node);
      height: var(--flow-node);
      border-radius: 50%;
      background: var(--brand-dot-color);
      animation: flow-dot linear both;
      animation-timeline: --flow-travel;
      animation-range: entry 100% cover 50%;
    }
  }
}

/* Hold at each step, travel between them. */
@keyframes flow-dot {
  0%, 12% { left: 0; }
  44%, 56% { left: var(--flow-step); }
  88%, 100% { left: calc(2 * var(--flow-step)); }
}

/* ---------- Layer stack: what lives where, top to bottom ---------- */

.layer-stack {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--border-strong);
}

.layer-stack__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--space-2) var(--space-5);
  padding: var(--space-5) 0;
  border-bottom: var(--border-hairline);
}

.layer-stack__what {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-h3-size);
  font-weight: var(--weight-medium);
  line-height: var(--type-h3-line);
  letter-spacing: var(--type-h3-track);
}

.layer-stack__where {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--type-small-size);
  color: var(--text-meta);
  white-space: nowrap;
}

.layer-stack__row--own .layer-stack__where { color: var(--text-primary); }

/* A sentence under the name: what the layer holds, in plain words. */
.layer-stack__desc {
  grid-column: 1;
  margin: 0;
  max-width: 34rem;
  font-size: var(--type-ui-size);
  line-height: var(--type-ui-line);
  color: var(--text-secondary);
}

/* The tools or place that hold the layer, as small marks with names. */
.layer-stack__tools {
  grid-column: 1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: var(--space-1) 0 0;
  padding: 0;
  list-style: none;
}

.layer-stack__tools li {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--type-small-size);
  color: var(--text-secondary);
}

.layer-stack__tools img { width: 1.25rem; height: 1.25rem; }
.layer-stack__tools img[data-mono] { opacity: 0.8; }

/* Open: rows with descriptions, separated by space instead of rules, in
   a reading-width column so the location stays close to its name. */
.layer-stack--open {
  display: grid;
  gap: var(--space-6);
  width: 100%;
  max-width: 44rem;
  margin-inline: auto;
  border-top: 0;
}

.layer-stack--open .layer-stack__row {
  padding: 0;
  border-bottom: 0;
}

/* Marks: the tool marks take the right column, level with the name, so
   the row reads name left, where right, as in the plain stack. */
.layer-stack--marks .layer-stack__tools {
  grid-column: 2;
  grid-row: 1;
  align-self: center;
  justify-content: flex-end;
  margin: 0;
}

/* The description runs under both columns, never beside the marks. */
.layer-stack--marks .layer-stack__desc { grid-row: 2; grid-column: 1 / -1; }

/* Below 40rem the marks drop under the text instead of crowding the name. */
@media (max-width: 39.99rem) {
  .layer-stack--marks .layer-stack__row { grid-template-columns: minmax(0, 1fr); }
  .layer-stack--marks .layer-stack__tools { grid-column: auto; grid-row: auto; justify-content: flex-start; }
  .layer-stack--marks .layer-stack__desc { grid-row: auto; grid-column: auto; }
}

.layer-stack--marks .layer-stack__row--own .layer-stack__tools li { color: var(--text-primary); }

@media (max-width: 29.99rem) {
  .layer-stack__row { grid-template-columns: minmax(0, 1fr); }
  .layer-stack__desc,
  .layer-stack__tools { grid-column: auto; }
}

/* ---------- Board: work by state, as a kanban ----------
   Each column is one state, named in its header with a count. Columns
   have no surface, so cards never sit inside another box. Place the
   board on a plain recessed band; cards are solid raised paper. */

/* All columns share one set of rows through subgrid, so every card has
   the same height: the height of the tallest card. Set --board-rows on
   .board to the number of cards in the longest column. */
.board {
  --board-rows: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: auto;
  grid-auto-rows: 1fr;
  gap: var(--space-3) var(--space-5);
}

.board__column {
  display: grid;
  grid-row: 1 / span calc(var(--board-rows) + 1);
  grid-template-rows: subgrid;
  min-width: 0;
}

/* The header text sits on the same inner edge as the card text. */
.board__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin: 0 0 var(--space-2);
  padding-inline: var(--space-4);
  font-family: var(--font-sans);
  font-size: var(--type-ui-size);
  font-weight: var(--weight-strong);
  line-height: var(--type-ui-line);
  letter-spacing: var(--type-text-track);
}

.board__count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--type-meta-size);
  font-weight: var(--weight-regular);
  letter-spacing: normal;
  color: var(--text-meta);
}

.board__cards {
  display: grid;
  grid-row: 2 / span var(--board-rows);
  grid-template-rows: subgrid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.board__card {
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding: var(--space-4);
  border: var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  box-shadow: 0 1px 2px rgb(27 29 34 / 0.04);
}

.board__card > * { margin: 0; }

.board__card .card__title { font-size: var(--type-ui-size); line-height: 1.4; }

/* One column on small screens: states stack, cards take their own height. */
@media (max-width: 47.99rem) {
  .board {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
    row-gap: var(--space-6);
  }
  .board__column,
  .board__cards {
    grid-row: auto;
    grid-template-rows: none;
    gap: var(--space-3);
  }
}

/* ---------- Consent: an optional choice, asked once ----------
   A frosted sheet fixed to the bottom of the viewport, on the page axis.
   It never covers the page with a scrim and never blocks reading. Both
   answers are equal buttons, so refusing is as easy as agreeing. The
   footer's "Cookie settings" reopens it. No inline styles: the page CSP
   allows none, so visibility is the hidden attribute alone. */

.consent {
  position: fixed;
  z-index: 40;
  right: var(--space-4);
  bottom: var(--space-4);
  left: var(--space-4);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4) var(--space-6);
  max-width: 56rem;
  max-height: calc(100dvh - 2 * var(--space-4));
  margin-inline: auto;
  padding: var(--space-5) var(--space-6);
  overflow: auto;
  /* Solid, not frost: it sits over live content, and a tint behind the
     text would cost legibility. The frost class still gives edge and shadow. */
  background: var(--surface-raised);
}

.consent[hidden],
.consent [hidden] { display: none; }

.consent__text {
  display: grid;
  gap: var(--space-2);
}

.consent__text > * { margin: 0; }

.consent__title {
  font-family: var(--font-sans);
  font-size: var(--type-ui-size);
  font-weight: var(--weight-strong);
  line-height: 1.4;
  letter-spacing: var(--type-text-track);
}

.consent__title:focus { outline: none; }

.consent__body {
  font-size: var(--type-small-size);
  line-height: var(--type-small-line);
  color: var(--text-secondary);
}

.consent__body a {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.consent__state {
  font-family: var(--font-mono);
  font-size: var(--type-meta-size);
  line-height: var(--type-meta-line);
  letter-spacing: normal;
  color: var(--text-meta);
}

.consent__actions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-2);
}

.consent__actions .button { white-space: nowrap; }

/* Keep current choice: only when the sheet was reopened from settings. */
.consent .consent__keep {
  grid-column: 1 / -1;
  justify-self: start;
  color: var(--text-secondary);
  font-size: var(--type-small-size);
  line-height: var(--type-small-line);
}

@media (max-width: 47.99rem) {
  .consent {
    grid-template-columns: minmax(0, 1fr);
    right: var(--space-2);
    bottom: var(--space-2);
    left: var(--space-2);
    padding: var(--space-5);
  }
}

/* A button that reads as a link, for settings in link lists. */
.link-button {
  padding: 2px 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.link-button:hover {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.link-button[hidden] { display: none; }

.site-footer__links .link-button {
  color: var(--text-secondary);
  font-size: var(--type-ui-size);
  line-height: 1.45;
  text-align: left;
}

/* ---------- Prose: long-form text such as legal notices ----------
   One reading column on the page axis. Headings inside are set at H3
   scale so a long notice keeps a calm rhythm under one serif title. */

.prose {
  display: grid;
  gap: var(--space-4);
  width: 100%;
  max-width: var(--layout-measure);
  margin-inline: auto;
}

.prose > * { margin: 0; }

.prose h2 {
  margin-top: var(--space-5);
  font-family: var(--font-sans);
  font-size: var(--type-h3-size);
  font-weight: var(--weight-medium);
  line-height: var(--type-h3-line);
  letter-spacing: var(--type-h3-track);
}

.prose p,
.prose li {
  font-size: var(--type-body-size);
  line-height: var(--type-body-line);
  color: var(--text-secondary);
}

.prose a {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.prose .layer-stack__what { font-size: var(--type-ui-size); line-height: 1.45; }

/* A settings button inside a sentence reads as a link. */
.link-button--inline {
  padding: 0;
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
