/* Portals hosted auth pages.
   Personality: precise, quiet, engineered. Legibility over ornament.
   Every colour pair below was checked against WCAG 2.2 AA before landing;
   ratios are noted where they are close to the line. */

/* ---------------------------------------------------------------- tokens */

:root {
  color-scheme: light dark;

  /* Surfaces and ink. Neutrals carry ~0.01 chroma toward the accent hue so
     they read as one family rather than as grey pasted onto blue. */
  --bg:            oklch(0.970 0.004 250);
  --surface:       oklch(1     0     250);
  --surface-sunk:  oklch(0.975 0.005 250);
  --ink:           oklch(0.215 0.014 250);  /* 17.5:1 on surface */
  --ink-2:         oklch(0.445 0.014 250);  /*  7.6:1 on surface */

  /* Two border weights. --line is decoration and may be faint; --line-control
     bounds an interactive control and must clear 3:1 (WCAG 2.2 SC 1.4.11).
     Tuned against the darkest ground a control actually sits on, not only
     against --surface: a secondary button in a panel foot, a switch on a
     disabled row and an icon button in a code head all stand on
     --surface-sunk, and the page ground behind .c-main is --bg. At 0.665 it
     cleared 3:1 on --surface alone (3.05:1) and failed on both of the others
     (2.84:1 and 2.80:1). */
  --line:          oklch(0.900 0.007 250);
  --line-control:  oklch(0.640 0.012 250);  /*  3.36:1 on surface,
                                                3.13:1 on surface-sunk,
                                                3.08:1 on bg */

  /* Primary actions are ink, not colour. The logo is a magenta-to-green
     gradient; letting it be the only saturated thing on the page is the whole
     point of having a mark that loud, and it keeps green and red free to mean
     success and danger rather than "button". */
  --action:        oklch(0.215 0.014 250);  /* 17.5:1 with --action-ink */
  --action-hover:  oklch(0.300 0.014 250);  /* 13.6:1 */
  --action-active: oklch(0.360 0.014 250);
  --action-ink:    oklch(1     0     250);

  /* --accent is drawn from the logo's magenta stop, darkened until it clears
     AA as body-sized link text. It marks links, focus and selection only. */
  --accent:        oklch(0.520 0.240 350);  /*  5.9:1 on surface */
  --accent-hover:  oklch(0.450 0.240 350);  /*  7.4:1 */
  --accent-faint:  oklch(0.965 0.030 350);  /*  5.2:1 with --accent on top */

  --danger:        oklch(0.505 0.185 25);
  --danger-bg:     oklch(0.968 0.018 25);
  --danger-line:   oklch(0.880 0.055 25);
  --success:       oklch(0.470 0.110 155);
  --success-bg:    oklch(0.968 0.022 155);
  --success-line:  oklch(0.880 0.060 155);
  --warn:          oklch(0.470 0.120 75);

  /* Type: one family, fixed rem steps at a ~1.15-1.2 ratio. Product UI has
     many type elements; wide jumps read as noise, not hierarchy. */
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  --text-xs:   0.75rem;
  --text-sm:   0.8125rem;
  --text-base: 0.9375rem;
  --text-md:   1.0625rem;
  --text-lg:   1.25rem;
  --text-xl:   1.5rem;

  /* Spacing: 4px base, skipping steps so rhythm has variety. */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 2.75rem;

  --radius:    0.5rem;
  --radius-sm: 0.375rem;
  --radius-lg: 0.75rem;

  /* Shadows stay tight. Precision reads through edges, not blur. */
  --shadow: 0 1px 2px oklch(0.215 0.014 250 / 0.06),
            0 4px 12px oklch(0.215 0.014 250 / 0.04);

  --ease: cubic-bezier(0.22, 1, 0.36, 1); /* ease-out-quart */
  --dur:  160ms;

  --z-base: 0;
  --z-sticky: 10;
  --z-overlay: 20;
  --z-toast: 30;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:            oklch(0.175 0.009 250);
    --surface:       oklch(0.225 0.011 250);
    --surface-sunk:  oklch(0.200 0.010 250);
    --ink:           oklch(0.960 0.004 250);  /* 15.2:1 on surface */
    --ink-2:         oklch(0.745 0.012 250);  /*  7.6:1 on surface */

    --line:          oklch(0.330 0.014 250);
    /* Dark already clears 3:1 on all three grounds, so it keeps its value:
       a lighter line on a dark ground gains contrast as the ground sinks. */
    --line-control:  oklch(0.515 0.012 250);  /*  3.04:1 on surface,
                                                  3.22:1 on surface-sunk,
                                                  3.37:1 on bg */

    --action:        oklch(0.960 0.004 250);  /* 16.9:1 with --action-ink */
    --action-hover:  oklch(0.880 0.006 250);  /* 13.2:1 */
    --action-active: oklch(0.820 0.008 250);
    --action-ink:    oklch(0.175 0.009 250);

    --accent:        oklch(0.720 0.200 350);  /*  6.3:1 on surface */
    --accent-hover:  oklch(0.800 0.160 350);  /*  8.2:1 */
    --accent-faint:  oklch(0.300 0.060 350);  /*  5.1:1 with --accent on top */

    --danger:        oklch(0.740 0.150 25);
    --danger-bg:     oklch(0.270 0.045 25);
    --danger-line:   oklch(0.400 0.080 25);
    --success:       oklch(0.780 0.130 155);
    --success-bg:    oklch(0.265 0.040 155);
    --success-line:  oklch(0.390 0.070 155);
    --warn:          oklch(0.800 0.120 75);

    --shadow: 0 1px 2px oklch(0 0 0 / 0.4), 0 4px 12px oklch(0 0 0 / 0.3);
  }
}

/* ------------------------------------------------------------------ base */

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

body {
  margin: 0;
  min-height: 100dvh;
  display: grid;
  /* Vertical centring only. `justify-content: center` (which place-content
     would also set) sizes the single implicit column to its content, so the
     card's `width: min(100%, …)` would resolve against itself and shrink to
     fit: the card would change width from page to page. Leaving justify-content
     alone keeps the track full-width; justify-items centres the card in it.
     `safe` so content taller than the viewport scrolls instead of clipping. */
  align-content: safe center;
  justify-items: center;
  padding: var(--sp-5) var(--sp-4);
  background: var(--bg);
  color: var(--ink);
  font: var(--text-base)/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  text-size-adjust: 100%;
}

/* ------------------------------------------------------------------ card */

.card {
  width: min(100%, 25rem);
  background: var(--surface);
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

/* The account cabinet holds tables and lists; the auth width would choke it. */
.card--wide { width: min(100%, 44rem); }

@media (max-width: 30rem) {
  body { padding: 0; align-content: start; justify-items: stretch; }
  .card {
    width: 100%;
    min-height: 100dvh;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: var(--sp-6) var(--sp-4);
  }
}

/* ----------------------------------------------------------------- brand */

.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: -0.011em;
  color: var(--ink);
}

/* The logo is the page's only saturated element, so it needs no help. Sized by
   height with width:auto to keep its 169:51 ratio at any zoom level. */
.brand-mark {
  display: block;
  height: 1.75rem;
  width: auto;
  flex: none;
}

.brand .brand-sub {
  color: var(--ink-2);
  font-weight: 450;
}
.brand .brand-sub::before {
  content: "";
  display: inline-block;
  width: 1px;
  height: 0.85em;
  margin: 0 var(--sp-2) -0.08em 0;
  background: var(--line-control);
}

/* ------------------------------------------------------------ typography */

h1 {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: 620;
  letter-spacing: -0.021em;
  line-height: 1.2;
  text-wrap: balance;
}

h2 {
  margin: var(--sp-6) 0 var(--sp-3);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: -0.014em;
}

h3 {
  margin: var(--sp-5) 0 var(--sp-2);
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: -0.008em;
}

p { margin: var(--sp-3) 0 0; text-wrap: pretty; }

a {
  color: var(--accent);
  text-underline-offset: 0.2em;
  text-decoration-thickness: from-font;
  border-radius: var(--radius-sm);
}
a:hover { color: var(--accent-hover); }

/* --ink, not --ink-2: the provenance line is the anti-phishing anchor and
   has to outrank the attribution note under it; at ink-2 the two read as one
   grey block. The host stays ink-2 via .muted, so name and host separate. */
.context { margin-top: var(--sp-2); color: var(--ink); }
.muted   { color: var(--ink-2); font-weight: 400; }

/* ----------------------------------------------------------- destination */
/* A multi-tenant IdP's one job on arrival is telling you where you are
   headed. That deserves a designed slot, not a grey sentence. */

.destination {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3) var(--sp-3);
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: var(--text-sm);
  color: var(--ink-2);
}
.destination strong {
  color: var(--ink);
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* ----------------------------------------------------------------- forms */

form { margin: 0; }

label {
  display: block;
  margin: var(--sp-4) 0 var(--sp-2);
  font-size: var(--text-sm);
  font-weight: 550;
  letter-spacing: -0.003em;
}
label .muted { font-weight: 400; }

/* Checkbox excluded: every other non-hidden input is full width, which the
   consent screen's Share checkbox must not inherit. */
input:not([type=hidden]):not([type=checkbox]) {
  width: 100%;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line-control);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  transition: border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
input::placeholder { color: var(--ink-2); opacity: 1; } /* same 4.5:1 as body */
input:hover:not(:focus) { border-color: var(--ink-2); }

/* One focus treatment for every control: 2px accent ring, offset halo. */
input:focus-visible,
button:focus-visible,
a:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
input:focus { border-color: var(--accent); }
input:focus-visible { outline-offset: 1px; }

input[aria-invalid="true"] { border-color: var(--danger); }
input[aria-invalid="true"]:focus-visible { outline-color: var(--danger); }

/* Codes are read character by character; monospace here is meaning, not style. */
input[autocomplete="one-time-code"] {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  letter-spacing: 0.14em;
}

.field-hint {
  margin: var(--sp-2) 0 0;
  font-size: var(--text-sm);
  color: var(--ink-2);
}

/* --------------------------------------------------------------- buttons */

button, .btn {
  width: 100%;
  margin-top: var(--sp-5);
  padding: 0.55rem var(--sp-4);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--action);
  color: var(--action-ink);
  font: inherit;
  font-weight: 570;
  letter-spacing: -0.006em;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
/* .btn lets a link carry a button's affordance (a download is a navigation,
   not a form submit). Scoped so button.link stays inline in the nav. */
.btn {
  display: inline-block;
  text-align: center;
  text-decoration: none;
}
button:hover, .btn:hover { background: var(--action-hover); }
button:active, .btn:active { background: var(--action-active); transform: translateY(1px); }

button.secondary, .btn.secondary {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--line-control);
  margin-top: var(--sp-3);
}
button.secondary:hover, .btn.secondary:hover { background: var(--surface-sunk); border-color: var(--ink-2); }
button.secondary:active, .btn.secondary:active { background: var(--surface-sunk); }

button.danger, .btn.danger {
  width: auto;
  padding: 0.35rem var(--sp-3);
  font-size: var(--text-sm);
  background: var(--surface);
  color: var(--danger);
  border-color: var(--line-control);
}
button.danger:hover, .btn.danger:hover {
  background: var(--danger-bg);
  border-color: var(--danger);
  color: var(--danger);           /* .btn inherits the link colour otherwise */
}

/* Inside a row the control is a flex item sitting beside its label, so it
   drops the standalone submit-button margin and shrinks to its content.
   Scoped to .row rather than set on the variants themselves: "Disable 2FA" is
   an ordinary form submit elsewhere and needs the same spacing below its input
   as every other submit on the page. */
.row button, .row .btn {
  width: auto;
  margin-top: 0;
  padding: 0.35rem var(--sp-3);
  font-size: var(--text-sm);
  white-space: nowrap;
}

/* After the variants on purpose: disabled is a state and must outrank the
   variant it decorates. Declared above them, equal specificity resolved in
   the variant's favour and a disabled .secondary button still looked live. */
button:disabled, button[aria-disabled="true"],
.btn[aria-disabled="true"] {
  background: var(--line);
  color: var(--ink-2);
  border-color: transparent;
  cursor: not-allowed;
  transform: none;
}
button:disabled:hover, button[aria-disabled="true"]:hover {
  background: var(--line);
  border-color: transparent;
}

button.link {
  width: auto;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  color: var(--accent);
  font: inherit;
  font-weight: inherit;
  cursor: pointer;
}
button.link:hover { color: var(--accent-hover); text-decoration: underline; }

/* --------------------------------------------------------------- signals */

.error, .notice {
  display: flex;
  gap: var(--sp-2);
  align-items: flex-start;
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3);
  border: 1px solid;
  border-radius: var(--radius);
  font-size: var(--text-sm);
  animation: signal-in var(--dur) var(--ease);
}
/* Never colour alone: each signal carries a glyph as a second channel. */
.error::before, .notice::before {
  font-weight: 700;
  line-height: 1.5;
  flex: none;
}
.error {
  background: var(--danger-bg);
  border-color: var(--danger-line);
  color: var(--danger);
}
.error::before { content: "!"; }
.notice {
  background: var(--success-bg);
  border-color: var(--success-line);
  color: var(--success);
}
.notice::before { content: "\2713"; }

@keyframes signal-in {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: 1; transform: none; }
}

/* -------------------------------------------------------- social sign-in */

.divider {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: var(--sp-5) 0 var(--sp-4);
  color: var(--ink-2);
  font-size: var(--text-sm);
}
.divider::before, .divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}

.provider {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
  padding: 0.5rem var(--sp-4);
  border: 1px solid var(--line-control);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.provider:hover {
  background: var(--surface-sunk);
  border-color: var(--ink-2);
  color: var(--ink);
}

.alt {
  margin: var(--sp-4) 0 0;
  font-size: var(--text-sm);
  color: var(--ink-2);
}

/* ------------------------------------------------------- account cabinet */

.tabs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-5);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--text-sm);
}
.tabs a {
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 500;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.tabs a:hover { background: var(--surface-sunk); color: var(--ink); }
.tabs a[aria-current="page"] { background: var(--accent-faint); color: var(--accent); }
.tabs .inline { margin-left: auto; }
.tabs .link { font-size: var(--text-sm); color: var(--ink-2); padding: var(--sp-1) var(--sp-2); }

.kv { width: 100%; border-collapse: collapse; margin-top: var(--sp-4); }
.kv th, .kv td { padding: var(--sp-3) var(--sp-3) var(--sp-3) 0; vertical-align: top; border-top: 1px solid var(--line); }
.kv tr:first-child th, .kv tr:first-child td { border-top: 0; }
/* th, not td, so the label is announced with its value. Reset to the browser
   default's opposite: a row header here reads as a label, not a heading. */
.kv th { width: 11rem; text-align: left; font-weight: 400; color: var(--ink-2); font-size: var(--text-sm); }

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-top: 1px solid var(--line);
}
.row > div:first-child { min-width: 0; }
.row .muted { display: block; margin-top: var(--sp-1); font-size: var(--text-sm); }

@media (max-width: 30rem) {
  .row { flex-direction: column; align-items: stretch; }
  .row form { align-self: flex-start; }
}

.pill {
  display: inline-block;
  padding: 0.05rem var(--sp-2);
  border: 1px solid var(--line-control);
  border-radius: 999px;
  background: var(--surface-sunk);
  color: var(--ink-2);
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: none;
}

.ok { color: var(--success); font-weight: 550; }

/* Status words sit beside a value (email, 2FA state); give them badge weight
   and breathing room so they read as status, not as part of the value. */
.kv .ok, .kv .muted {
  display: inline-block;
  margin-left: var(--sp-2);
  padding: 0.05rem var(--sp-2);
  border: 1px solid;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 550;
  vertical-align: 0.08em;
}
.kv .ok    { background: var(--success-bg); border-color: var(--success-line); }
.kv .muted { background: var(--surface-sunk); border-color: var(--line-control); }
/* The "Not set" placeholder is a value, not a status: keep it plain. */
/* An absent value ("Not set") is not a status, so it drops the badge
   treatment. Opt-in via .unset rather than positional: keying this off
   :only-child meant a status word lost its badge whenever a sibling control
   was moved out of the cell. */
.kv .unset {
  margin-left: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: inherit;
  font-weight: 400;
}

/* Secrets and recovery codes: monospace, selectable, unambiguous. */
.key, .codes code, code {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.key {
  margin-top: var(--sp-4);
  padding: var(--sp-3);
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-align: center;
  letter-spacing: 0.08em;
  overflow-wrap: anywhere;
  user-select: all;
}
.codes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
  padding: 0;
  list-style: none;
}
.codes li {
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  text-align: center;
  user-select: all;
}

.scopes { margin: var(--sp-4) 0 0; padding-left: 1.15rem; }
.scopes li { margin: var(--sp-2) 0; }

.qr {
  display: block;
  margin: var(--sp-4) auto 0;
  padding: var(--sp-3);
  background: #fff;             /* QR contrast must not follow the theme */
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.inline { display: inline; }

/* ------------------------------------------------------------ legal links */

.legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--text-sm);
}
/* padding-block: without it these links are 20px tall and miss the 24px
   target of WCAG SC 2.5.8. */
.legal a { color: var(--ink-2); text-decoration: none; padding-block: var(--sp-1); }
.legal a:hover { color: var(--ink); text-decoration: underline; }

/* A relative timestamp is an approximation; the exact value is on the title
   attribute, so mark it as explainable rather than as a broken link. */
time[title] { cursor: help; text-decoration: underline dotted from-font; text-underline-offset: 0.2em; }

/* ----------------------------------------------------------------- motion */

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

/* Forced-colours (Windows high contrast): keep focus and bounds visible. */
@media (forced-colors: active) {
  .card, input, button, .provider, .pill { border: 1px solid CanvasText; }
  input:focus-visible, button:focus-visible, a:focus-visible { outline: 2px solid Highlight; }
}

/* ------------------------------------------------ per-field consent */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

.select-wrap { position: relative; margin-top: var(--sp-2); }
select {
  appearance: none; width: 100%; padding: 0.5rem 2.25rem 0.5rem 0.65rem;
  border: 1px solid var(--line-control); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit; line-height: 1.55; cursor: pointer;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
  transition: border-color var(--dur) var(--ease);
}
select:hover:not(:focus) { border-color: var(--ink-2); }
select:focus { border-color: var(--accent); }
select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
select[aria-invalid="true"] { border-color: var(--danger); }
.select-wrap::after {
  content: ""; position: absolute; right: 0.9rem; top: 50%; width: 0.42rem; height: 0.42rem; margin-top: -0.32rem;
  border-right: 1.5px solid var(--ink-2); border-bottom: 1.5px solid var(--ink-2); transform: rotate(45deg); pointer-events: none;
}

.group { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.group > h2 { margin: 0; font-size: var(--text-base); font-weight: 650; letter-spacing: -0.008em; color: var(--ink); }
.group-note { margin: var(--sp-1) 0 0; font-size: var(--text-sm); color: var(--ink-2); }

.field { margin-top: var(--sp-5); }
.field-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2) var(--sp-3); flex-wrap: wrap; min-height: 1.4rem; }
.field-name, .field label { display: block; margin: 0; font-size: var(--text-sm); font-weight: 550; letter-spacing: -0.003em; color: var(--ink); }
.field input:not([type=checkbox]) { margin-top: var(--sp-2); }
.value { margin: var(--sp-1) 0 0; font-size: var(--text-base); color: var(--ink); overflow-wrap: anywhere; }

/* The app's words: named speaker, quotation marks, hairline rule. Nothing
   Portals says ever appears inside this channel. */
.purpose { margin: var(--sp-2) 0 0; padding: 0 0 0 var(--sp-3); border-left: 2px solid var(--line-control); font-size: var(--text-sm); color: var(--ink-2); }
.purpose-who { font-weight: 600; color: var(--ink-2); }
.purpose q { quotes: "\201C" "\201D" "\2018" "\2019"; }
.attribution { margin-top: var(--sp-3); }

label.share {
  display: inline-flex; align-items: center; gap: var(--sp-2); margin: 0; padding: var(--sp-2) 0; min-height: 2.75rem;
  font-size: var(--text-sm); font-weight: 500; color: var(--ink); cursor: pointer; user-select: none;
}
label.share input[type=checkbox] { width: 1.25rem; height: 1.25rem; margin: 0; flex: none; accent-color: var(--action); cursor: pointer; }
input[type=checkbox]:focus-visible, summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.change { margin-top: var(--sp-1); }
.change > summary {
  display: inline-flex; align-items: center; gap: var(--sp-1); width: fit-content; min-height: 2rem; padding: var(--sp-1) 0;
  list-style: none; cursor: pointer; font-size: var(--text-sm); font-weight: 500; color: var(--accent); border-radius: var(--radius-sm);
}
.change > summary::-webkit-details-marker { display: none; }
.change > summary::after { content: ""; width: 0.38rem; height: 0.38rem; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-0.12em) rotate(45deg); transition: transform var(--dur) var(--ease); }
.change[open] > summary::after { transform: translateY(0.06em) rotate(-135deg); }
.change > summary:hover { color: var(--accent-hover); text-decoration: underline; }
.field:has(.change[open]) > .value { display: none; }

.subfields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); margin-top: var(--sp-3); }
.subfield { min-width: 0; }
.subfield.span2 { grid-column: 1 / -1; }
.subfield label { margin: 0 0 var(--sp-1); font-weight: 500; color: var(--ink-2); }
.subfield input, .subfield .select-wrap { margin-top: 0; }
@media (max-width: 24rem) { .subfields { grid-template-columns: 1fr; } }

.field-error { margin: var(--sp-2) 0 0; font-size: var(--text-sm); font-weight: 550; color: var(--danger); }
/* The alternative text is empty on purpose: the mark is decoration, and
   punctuation-only generated content is announced inconsistently — some
   screen readers say "exclamation mark", some say nothing. The message
   itself carries the meaning. */
.field-error::before { content: "!" / ""; font-weight: 700; margin-right: 0.45em; }

.sharing { margin: var(--sp-5) 0 0; padding-top: var(--sp-4); border-top: 1px solid var(--line); font-size: var(--text-sm); color: var(--ink-2); }
.sharing p { margin: 0; }
.sharing p + p { margin-top: var(--sp-2); }
.sharing b { color: var(--ink); font-weight: 600; }
.standing { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.standing .scopes { margin-top: 0; }
.decide { margin-top: var(--sp-5); }

@media (forced-colors: active) {
  select { border: 1px solid CanvasText; }
  .select-wrap::after, .change > summary::after { border-color: CanvasText; }
}

/* -------------------------------------------------- account profile */
/* One row of the Profile tab: the value reads first, the actions sit at the
   end of the line, and both wrap onto their own lines on a narrow screen
   rather than squeezing a long address into a column two words wide. */
.cell { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-2) var(--sp-4); flex-wrap: wrap; }
.cell > .val { min-width: 0; overflow-wrap: anywhere; }
.acts { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: baseline; font-size: var(--text-sm); margin-left: auto; }
.acts a, .acts button.link { font-weight: 500; text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: from-font; padding-block: var(--sp-1); min-height: 1.75rem; }
.acts form { display: contents; }
button.link.destructive { color: var(--danger); }
button.link.destructive:hover { color: var(--danger); }
.shares { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--sp-1) var(--sp-2); margin: var(--sp-2) 0 0; font-size: var(--text-sm); }
.shares dt { color: var(--ink); font-weight: 600; }
.shares dd { margin: 0; color: var(--ink-2); }
@media (max-width: 24rem) { .shares { grid-template-columns: 1fr; gap: 0; } .shares dd { margin-bottom: var(--sp-2); } }
@media (max-width: 30rem) { .cell { flex-direction: column; align-items: stretch; } .acts { margin-left: 0; } }
.measure { max-width: 24rem; }
.measure-wide { max-width: 34rem; }
.back { margin: 0 0 var(--sp-4); font-size: var(--text-sm); }
