/*
 * The whole stylesheet. No build step, nothing to purge, nothing to override.
 *
 * Every measured component library ships default button heights of 32-40px,
 * which fails both Apple's 44pt and Material's 48dp guidance. Children aged
 * 11-17 miss a 9mm target one time in six. The correct values here are *above*
 * every default, so a library would be overridden at every call site.
 *
 * The palette starts from the feedback study's own "Option C" look —
 * `experiments/feedback-study/src/styles.css` — rather than GOV.UK's, so
 * pressing Start no longer changes the page underneath the module. Every pair
 * below is checked against WCAG 1.4.3/1.4.11 by `scripts/check-contrast.test.ts`,
 * which reads this file's tokens straight off disk.
 */

:root {
  --target-min: 56px;     /* above Apple's 44pt and Material's 48dp, deliberately */
  --text-base: 1.25rem;   /* large by default, not a "large" variant */
  --space: 1.25rem;       /* vertical rhythm unit, used ×1, ×1.5, ×2, ×3 */
  --page: #fdf3c9;        /* = .fs-root background, so the module's edge vanishes at Start */
  --ink: #a33a63;         /* 5.64:1 on --page */
  --ink-muted: #a83f68;   /* 5.27:1 on --page */
  --ink-faint: #aa4569;   /* 5.00:1 on --page; hints, fact labels, footer links */
  --action: #b04a72;      /* the student's primary; --control text on it is 5.16:1; as a border on --page, 4.63:1 */
  --action-hover: #96395e; /* --control text on it is 6.90:1 */
  --control: #ffffff;     /* field fill and button text */
  --border: #b04a72;      /* field + secondary-button edge, ≥3:1 on --page (WCAG 1.4.11) */
  --hairline: #f2dce4;    /* decorative only: panel edges, dividers (1.17:1 on --page) */
  --accent-line: #e29bb4; /* decorative only: beakers, bubbles (1.97:1 on --page) */
  --panel: rgb(255 255 255 / 72%);        /* translucent fill for grouped content on --page */
  --panel-strong: rgb(255 255 255 / 90%); /* a stronger fill for receipt bands and the draft message */
  --track: #e4ded4;       /* progress track (Phase 2); = module's --fs-track */
  --ink-pending: #756c63; /* 4.62:1 on --page; a delivery step not yet reached */
  --light-off: rgb(117 108 99 / 18%);      /* decorative only: an unlit delivery light */
  --light-off-edge: rgb(117 108 99 / 40%); /* decorative only: its rim */
  --error: #b3261e;       /* 5.86:1 on --page. The old #d4351c is 4.36:1 on cream */
  --focus: #a33a63;       /* = module's focus outline colour, 5.64:1 on --page */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-card: 14px;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}

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

html {
  /* Never below 100%: a fixed px root size overrides the participant's own
     browser text-size setting, which is the one accessibility control the
     people who need it most have already found. */
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
  font-size: var(--text-base);
  line-height: 1.5;
}

/*
 * One column, never wider than a comfortable measure, with enough bottom room
 * that the primary action is never under a phone's home indicator.
 */
.screen {
  max-width: 40rem;
  margin: 0 auto;
  padding: var(--space) var(--space) calc(var(--space) * 3);
}

.question {
  font-size: 2rem;
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space);
  /* "Continue as <address>?" carries an address, which has no spaces to break
     at; it wraps inside the column rather than pushing the page sideways. */
  overflow-wrap: break-word;
}

.body {
  margin: 0 0 var(--space);
  max-width: 34rem;
}

/*
 * The landing hero: a decorative science scene and three fact cards below the
 * <h1>. Both are CSS-only — no image bytes, no JS — and the scene is
 * `aria-hidden` in the markup, so none of it is announced to a screen reader.
 */
.hero {
  position: relative;
  height: 7.5rem;
  margin: 0 0 var(--space);
  overflow: hidden;
  background: var(--panel);
  border-radius: var(--radius-card);
}

/*
 * A bench with an Erlenmeyer flask, a round-bottom flask and a graduated
 * beaker (the SVG in entry.tsx). The glass is outlined in ink at low opacity,
 * so it reads as glass rather than as solid shapes, and the liquid uses the
 * prototype's pink (`Feedback Study.dc.html:38-45`).
 */
.hero-scene {
  display: block;
  width: 100%;
  height: 100%;
}

.hero-glass,
.hero-ticks,
.hero-bench {
  fill: none;
  stroke: var(--ink);
  stroke-opacity: 0.5;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.hero-ticks { stroke-width: 1.5; }
.hero-bench { stroke: var(--hairline); stroke-opacity: 1; }

.hero-liquid {
  fill: var(--accent-line);
  fill-opacity: 0.7;
}

/*
 * Bubbles start inside each vessel's liquid and rise straight up through its
 * mouth, fading out above it — every bubble sits under its own vessel's neck
 * so none crosses the glass. The static positions are all inside the liquid,
 * so the frame reduced motion shows is liquid with bubbles in it, not bubbles
 * floating over an empty bench. The `@keyframes` are declared only under
 * `no-preference`, and the `reduce` block below stops every animation anyway,
 * so this motion is opt-in on both ends. Negative delays start each loop part
 * way through, so the flasks are already bubbling when the page appears.
 * Transform lengths on SVG content are in viewBox units.
 */
.hero-bubble {
  fill: var(--control);
  stroke: var(--accent-line);
  stroke-width: 1;
  transform-box: fill-box;
  transform-origin: center;
}

@media (prefers-reduced-motion: no-preference) {
  .hero-bubble {
    animation: hero-rise 4.2s ease-in infinite;
  }

  .hero-bubble:nth-of-type(2) { animation-duration: 5s; animation-delay: -1.6s; }
  .hero-bubble:nth-of-type(3) { animation-duration: 3.6s; animation-delay: -2.9s; }
  .hero-bubble:nth-of-type(4) { animation-duration: 4.6s; animation-delay: -0.8s; }
  .hero-bubble:nth-of-type(5) { animation-duration: 3.9s; animation-delay: -2.2s; }
  .hero-bubble:nth-of-type(6) { animation-duration: 4.4s; animation-delay: -3.1s; }
  .hero-bubble:nth-of-type(7) { animation-duration: 5.4s; animation-delay: -1.2s; }

  @keyframes hero-rise {
    0% { transform: translateY(0) scale(0.7); opacity: 0; }
    12% { opacity: 1; }
    80% { opacity: 0.9; }
    100% { transform: translateY(-88px) scale(1.25); opacity: 0; }
  }
}

/*
 * Length / Format / Collected — the facts a "should I do this" decision
 * actually asks for, ahead of the longer explanation in `.body` and the full
 * consent form. Labels are mono, the same "machine voice" treatment as
 * `.reference` and `.band-count`.
 */
.facts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  margin: 0 0 var(--space);
}

.fact {
  padding: 0.625rem 0.5rem;
  background: var(--panel-strong);
  border-radius: var(--radius);
  text-align: center;
}

.fact dt {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.fact dd {
  margin: 0.25rem 0 0;
  font-size: 0.9375rem;
  line-height: 1.3;
}

.hint {
  color: var(--ink-faint);
  font-size: 1rem;
  margin: 0 0 0.5rem;
}

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

/*
 * A secondary choice, deliberately not a second button. "Change my age" and
 * "yes, I'm 41" are not equivalent actions and must not look equivalent — but
 * the row is still a full-height target, because the person who needs it is the
 * person who already got something wrong.
 */
.alt-action {
  display: flex;
  align-items: center;
  gap: 0.3em; /* "Not you? Start again": flex would otherwise eat the space */
  min-height: var(--target-min);
  margin-top: var(--space);
}

.label {
  display: block;
  font-weight: 700;
  margin-bottom: 0.5rem;
}

/* A second label in the same form, such as the age typed again. */
.label--follow {
  margin-top: var(--space);
}

/*
 * A 2px border rather than 1px: at arm's length on a phone in daylight, a
 * hairline border reads as decoration and the field stops looking tappable.
 */
.field {
  display: block;
  width: 100%;
  min-height: var(--target-min);
  padding: 0.5rem 0.75rem;
  font-size: 1.5rem;
  font-family: inherit;
  color: var(--ink);
  background: var(--control);
  border: 2px solid var(--border);
  border-radius: var(--radius);
}

.field--narrow {
  max-width: 6ch;
}

/*
 * The module's own treatment: a single outline rather than a double ring, so a
 * keyboard or switch user sees the same focus indicator on both sides of
 * Start. `:focus-visible` rather than `:focus` keeps the ring off a tap.
 */
.field:focus-visible,
.btn:focus-visible,
a:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.btn {
  display: block;
  width: 100%;
  min-height: var(--target-min);
  margin-top: calc(var(--space) * 1.5);
  padding: 0.75rem 1rem;
  font-size: var(--text-base);
  font-family: inherit;
  font-weight: 700;
  color: var(--control);
  background: var(--action);
  border: 2px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
}

.btn:hover {
  background: var(--action-hover);
}

.error {
  color: var(--error);
  font-weight: 700;
  margin: 0 0 var(--space);
  padding-left: 0.75rem;
  border-left: 4px solid var(--error);
}

/*
 * A supplementary fact that is neither the question nor an error — boxed so it
 * reads as an aside a skimming reader can still take in, rather than one more
 * paragraph of body text that gets skipped along with the ones before it. The
 * mockup uses amber for this; the palette here stays inside the two colours
 * everything else uses; a full border reads as distinct without adding a third
 * hue nothing else on the page carries.
 */
.notice {
  margin: 0 0 var(--space);
  padding: 0.75rem 1rem;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  font-size: 1rem;
  color: var(--ink-muted);
}

.field--error {
  border-color: var(--error);
}

/*
 * The consent summary: the four facts a decision is actually made from. A
 * definition list rather than headings, because these are pairs and a screen
 * reader should say so.
 */
.summary {
  margin: 0 0 var(--space);
  padding: 1rem 1.25rem;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
}

.summary-heading {
  font-weight: 700;
  margin-top: 0.875rem;
}

/*
 * A step down from --text-base, and the only place in the app that goes below
 * it. All four facts have to be on screen at once — a summary that scrolls is
 * one people decide from the top half of.
 */
.summary-detail {
  margin: 0.125rem 0 0;
  margin-inline-start: 0;
  font-size: 1.125rem;
  line-height: 1.35;
}

/*
 * The longer consent document of `consent-v0`/`v1`, one tap away for a run
 * pinned to either (v2 is the summary alone). `<details>` is native, so this
 * works with no JavaScript — which is what keeps the funnel free of a bundle on
 * the one screen where a failed script would block a signature.
 */
.expander {
  margin: 0 0 var(--space);
  padding: 0.5rem 1rem;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}

.expander-summary {
  display: flex;
  align-items: center;
  min-height: var(--target-min);
  font-weight: 700;
  color: var(--action);
  cursor: pointer;
}

.expander[open] .expander-summary {
  margin-bottom: 0.5rem;
}

/*
 * The checkbox is sized to the same 56px rule as everything else — a 13px
 * default control is not a target, it is a dare.
 */
.checkbox-row {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin: var(--space) 0;
}

.checkbox {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  margin: 0;
  accent-color: var(--action);
}

.checkbox-label {
  /* The whole label is part of the target, so a near miss still ticks it. */
  min-height: var(--target-min);
  display: flex;
  align-items: center;
  font-weight: 700;
  cursor: pointer;
}

code {
  font-size: 0.9em;
  word-break: break-all;
}

/*
 * "No thanks" is a real button, the same size and weight as the other one.
 *
 * The only difference is the fill. A child's refusal that reads as a link under
 * the real button is a refusal the screen is discouraging, and the whole point
 * of this choice is that it is genuinely theirs.
 */
.btn--secondary {
  color: var(--ink);
  background: var(--panel);
  border-color: var(--border);
  margin-top: 0.75rem;
}

/*
 * The landing form: an age, then two boxes that say who is taking part, then
 * every way to sign in. Every rule below is previewed by CSS and enforced by
 * the server (`parseEntry`), so losing the preview never loses the rule:
 *
 * - The minors box reads "Also allow minor(s) to participate" beside a ticked
 *   "I want to participate", and "Allow minor(s) to participate only" without
 *   it. Only the "only" wording depends on `:has()`, so a browser without it
 *   keeps "Also allow…" — still true of what the box does.
 * - With neither box ticked there is nobody to sign in, so the sign-in block is
 *   hidden and a hint takes its place. A browser without `:has()` loses that
 *   preview too.
 * - The inline script in `entry.tsx` sets `age-ok` and `age-adult` on the form
 *   once the age field holds a 1-120 value, and 18 or over. Those two classes
 *   gate the minors row and the sign-in block the same way: hidden until
 *   `age-ok`, blank space until `age-adult`. Without the script neither class
 *   is ever set, so these rules never match and the page falls back to the
 *   `:has()` preview above — same as it behaves without any age gate at all.
 */
.intent .checkbox-row {
  margin: 0.5rem 0 0;
}

.minors-label--only,
.intent-none,
.age-needed {
  display: none;
}

.intent:not(:has(#self:checked)) .minors-label--only {
  display: inline;
}

.intent:not(:has(#self:checked)) .minors-label--also {
  display: none;
}

.intent:not(:has(#self:checked, #minors:checked)) .intent-none {
  display: block;
}

.intent:not(:has(#self:checked, #minors:checked)) .signin {
  display: none;
}

.intent.age-script:not(.age-ok) .age-needed {
  display: block;
}

.intent.age-script:not(.age-ok) .signin,
.intent.age-script:not(.age-ok) .intent-none {
  display: none;
}

/* Space held rather than collapsed, so ticking or dropping below 18 does not
   shift anything below the minors row. */
.intent.age-script:not(.age-adult) .minors-row {
  visibility: hidden;
}

.checkbox:disabled,
.checkbox:disabled + .checkbox-label {
  opacity: 0.45;
  cursor: not-allowed;
}

/*
 * "Sign in with Google" and "Sign in with Apple", in each provider's own style
 * rather than ours: Google's white button with the four-colour G and a grey
 * edge, Apple's black one with a white logo. Both are static — no provider
 * script, no iframe, nothing requested from either company until someone
 * presses — and the same size as each other.
 *
 * They are submit buttons of the landing form, so the browser's own button
 * styling (appearance, margins) is reset here rather than inherited.
 */
.btn-provider {
  -webkit-appearance: none;
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  width: 100%;
  min-height: var(--target-min);
  margin: 0.75rem 0 0;
  padding: 0.5rem 1rem;
  font-size: 1.0625rem;
  line-height: 1.2;
  text-decoration: none;
  border-radius: 4px;
  cursor: pointer;
}

.btn-google {
  color: #1f1f1f;
  background: #ffffff;
  border: 1px solid #747775;
  font-family: Roboto, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
  font-weight: 500;
}

.btn-apple {
  color: #ffffff;
  background: #000000;
  border: 1px solid #000000;
  font-family: -apple-system, system-ui, 'Segoe UI', Arial, sans-serif;
  font-weight: 600;
}

.btn-provider:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.provider-mark {
  flex: none;
  width: 20px;
  height: 20px;
}

.disclaimer {
  margin: var(--space) 0 0;
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--ink-faint);
}

/*
 * "Use email address instead": a native `<details>` whose summary reads as a
 * link, centred under the provider buttons. Opened, the email field and its
 * button appear in place — no navigation, and nothing typed is lost.
 */
.email-alt {
  margin-top: 0.5rem;
}

.email-alt-summary {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--action);
  text-decoration: underline;
  cursor: pointer;
  list-style: none;
}

.email-alt-summary::-webkit-details-marker {
  display: none;
}

.email-alt[open] .email-alt-summary {
  margin-bottom: 0.5rem;
}

/*
 * The check-email page: the address that was typed, then where its one
 * message has got to. An address can be long and has no spaces to break at,
 * so it wraps anywhere rather than pushing the column wider than the phone.
 */
.entry-contact {
  overflow-wrap: anywhere;
}

/*
 * Where a message has got to, drawn as a column of start lights: a round
 * light per step with its label beside it. A step still to come is a grey,
 * see-through light with a grey label; the step under way blinks slowly; a
 * finished step is held solid in full ink with a tick. The inline polls only
 * swap `data-state`, the steps' classes and `hidden`, so everything visual
 * lives here.
 *
 * The pending label is grey rather than see-through: a faded label would drop
 * under 4.5:1, and the step still has to be readable before it is reached.
 */
.delivery-steps {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: var(--space) 0 0.75rem;
  padding: 0;
  list-style: none;
}

.delivery-steps li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--ink-pending);
  font-size: 0.9375rem;
  line-height: 1.3;
}

.delivery-steps li::before {
  content: '';
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 2px solid var(--light-off-edge);
  border-radius: 50%;
  background: var(--light-off);
  color: var(--control);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
}

.delivery-steps li.done,
.delivery-steps li.current {
  color: var(--ink);
  font-weight: 700;
}

.delivery-steps li.current::before {
  border-color: var(--action);
  background: var(--action);
}

.delivery-steps li.done::before {
  content: '✓';
  border-color: var(--ink);
  background: var(--ink);
}

/* Held steady, at full strength, for anyone who has asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .delivery-steps li.current::before {
    animation: light-blink 1.8s ease-in-out infinite;
  }

  @keyframes light-blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
  }
}

/* A held, bounced or failed message has no place on the list, so it is not
   drawn. The class sets `display`, which would otherwise beat `hidden`. */
.delivery-steps[hidden] {
  display: none;
}

.reentry {
  margin-top: var(--space);
}

/*
 * The short request code a child reads out to a parent. Monospace and spaced,
 * because it is read aloud and "K7M2" has to survive being said over a noisy
 * kitchen.
 */
.reference {
  font-family: var(--mono);
  font-size: 1.1em;
  letter-spacing: 0.08em;
}

/*
 * One row per child. A label, what is still needed, and the one action that
 * moves them on — nothing that needs horizontal space on a phone, so it stacks.
 */
.child-list {
  list-style: none;
  margin: 0 0 var(--space);
  padding: 0;
}

.child-row {
  padding: var(--space) 0;
  border-bottom: 1px solid var(--hairline);
}

.child-label {
  display: block;
  font-weight: 700;
}

/* One group per approved document, with a visible edge between them. */
.request-group {
  margin-bottom: calc(var(--space) * 2);
  padding-bottom: var(--space);
  border-bottom: 1px solid var(--hairline);
}

.request-group:last-of-type {
  border-bottom: 0;
}

/* Available to a screen reader, invisible to everyone else. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }

  /* A number counting down is not motion, and the page really does move on
     when it reaches zero — so it keeps counting for everyone. */
  .countdown-number {
    animation: countdown 10s !important;
  }
}

/*
 * The "start again" page's countdown, with no script: `--countdown` is a
 * registered integer, animated down one step per second and printed through a
 * CSS counter. `<meta http-equiv="refresh">` does the actual navigating when it
 * runs out (`src/screens/start-again.tsx`, whose START_AGAIN_SECONDS this must
 * match).
 *
 * Every second is its own keyframe, held with `steps(1, end)`, so a browser
 * that cannot interpolate the property still steps through 10, 9, 8… instead of
 * flipping once halfway. The resting value is the starting number, so a page
 * whose animation never runs, or has finished, reads "10" rather than "0".
 */
@property --countdown {
  syntax: '<integer>';
  inherits: false;
  initial-value: 10;
}

.countdown-number {
  --countdown: 10;
  counter-reset: countdown var(--countdown);
  animation: countdown 10s;
  font-variant-numeric: tabular-nums;
}

.countdown-number::after {
  content: counter(countdown);
}

@keyframes countdown {
  0% { --countdown: 10; animation-timing-function: steps(1, end); }
  10% { --countdown: 9; animation-timing-function: steps(1, end); }
  20% { --countdown: 8; animation-timing-function: steps(1, end); }
  30% { --countdown: 7; animation-timing-function: steps(1, end); }
  40% { --countdown: 6; animation-timing-function: steps(1, end); }
  50% { --countdown: 5; animation-timing-function: steps(1, end); }
  60% { --countdown: 4; animation-timing-function: steps(1, end); }
  70% { --countdown: 3; animation-timing-function: steps(1, end); }
  80% { --countdown: 2; animation-timing-function: steps(1, end); }
  90% { --countdown: 1; animation-timing-function: steps(1, end); }
  100% { --countdown: 0; }
}

/*
 * The footer: one centred row of small links under a hairline, the same on
 * every screen. "Withdraw from the study" (when the screen offers it) and
 * "Privacy and study contact" sit side by side.
 *
 * Quiet is the honest weight for both: withdrawing is always available and is
 * never the thing the screen is asking for, and the privacy text is reference
 * material. A participant looking for either knows what they are looking for;
 * one who is not should not be nudged towards it. The text is small, but each
 * link keeps a 44px tap target (Apple's minimum), so small never means fiddly.
 *
 * The privacy summary is a native `<details>` styled as a link. Opened, it
 * takes the whole row width so its paragraphs read at a normal measure.
 */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  column-gap: 1rem;
  margin-top: calc(var(--space) * 2);
  padding-top: 0.5rem;
  border-top: 1px solid var(--hairline);
  font-size: 0.875rem;
}

.footer-link,
.link-summary {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink-faint);
  text-decoration: underline;
}

.link-summary {
  cursor: pointer;
  list-style: none;
}

.link-summary::-webkit-details-marker {
  display: none;
}

.study-help {
  text-align: center;
}

.study-help[open] {
  flex-basis: 100%;
}

.study-help .body {
  margin: 0.5rem auto;
  font-size: 1rem;
  text-align: left;
}

/*
 * The finish screen, below the receipt: the do-not-share line, one closed
 * **Share**, and for an adult the family question. The whole receipt is meant
 * to fit on about one phone screen, so everything past the warning stays
 * folded until someone asks for it.
 */
.divider {
  margin: calc(var(--space) * 1.5) 0 var(--space);
  border: 0;
  border-top: 1px solid var(--hairline);
}

.section-heading {
  margin: var(--space) 0 0.5rem;
  font-size: 1.5rem;
  line-height: 1.2;
}

/* The receipt's two facts, a label and its value on one row each. */
.summary--inline {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.25rem 0.5rem;
  align-items: baseline;
}

.summary--inline .summary-heading {
  margin-top: 0;
}

.summary--inline .summary-detail {
  margin: 0;
}

/*
 * "DO NOT share ANY details of the experiment with anyone else!" — the one
 * request that protects the results, so it is the loudest line on the page.
 * Plain --ink on --page, the pair `scripts/check-contrast.test.ts` already
 * holds at 5.64:1; its size is what makes it loud, not a new colour.
 */
.warn {
  margin: var(--space) 0 0.5rem;
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.25;
  color: var(--ink);
  max-width: 34rem;
}

/* A native `<details>` whose summary is drawn as the primary button. */
.share-summary {
  margin-top: var(--space);
  text-align: center;
  list-style: none;
}

.share-summary::-webkit-details-marker {
  display: none;
}

.share-summary:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* The draft message, shown before anything is sent. It reads as a quotation of
   what would go out rather than as body copy of this page. */
.draft {
  margin: var(--space) 0;
  padding: 0.75rem 1rem;
  background: var(--panel-strong);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
}

.draft-label {
  margin: 0 0 0.25rem;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-family: var(--mono);
  color: var(--ink-muted);
}

.draft-text {
  margin: 0;
  font-size: 1.0625rem;
  line-height: 1.5;
}

/* Long, and it must not push the page sideways on a narrow phone. */
.share-url {
  word-break: break-all;
  font-weight: 700;
}

/*
 * The withdraw confirmation opened in place once begin has committed the
 * attempt (`WithdrawConfirmDialog`, `src/client/host.ts`). Content is the same
 * `WithdrawConfirmBody` the standalone `/r/:token/withdraw` page renders, so
 * only the frame around it needs its own rules here.
 */
.withdraw-dialog {
  max-width: 28rem;
  width: calc(100% - var(--space) * 2);
  margin: auto;
  padding: var(--space);
  color: var(--ink);
  background: var(--panel-strong);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
}

.withdraw-dialog::backdrop {
  background: rgb(0 0 0 / 45%);
}

.withdraw-dialog-title {
  font-size: 1.5rem;
  line-height: 1.2;
  font-weight: 700;
  margin: 0 0 var(--space);
}
