/* donate.css: the one time donation page (/donate/) and its checkout tab screen (go.php). Moved from
   /give/ and give.css on 2026-10-29. */

/* One time gifts through our fiscal sponsor, Fractured Atlas. This page picks the amount
   and the fee choice, then go.php hands the donor to Fractured Atlas's donor info step
   with the amount locked in. Green stays reserved for Support, so this lane uses pink. */

*,*::before,*::after{ box-sizing:border-box; }
*{ margin:0; }
html{ -webkit-text-size-adjust:100%; background:var(--bg); }
body{
  background:var(--bg); color:var(--fg);
  font-family:var(--font-body); font-size:var(--step-0); line-height:1.6;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  padding: clamp(var(--space-4),5vw,var(--space-7)) clamp(var(--space-3),5vw,var(--space-6));
  min-height:100vh; min-height:100dvh;
}
p{ text-wrap:pretty; }
h1,h2{ text-wrap:balance; }
a{ color:inherit; text-underline-offset:.18em; }
::selection{ background:var(--pink); color:var(--ink); }
:focus-visible{ outline:2px solid var(--focus); outline-offset:3px; border-radius:4px; }

.wrap{ max-width:var(--wrap, 74ch); margin-inline:auto; width:100%; }
.mono{ font-family:var(--font-mono); font-weight:500; text-transform:uppercase;
       letter-spacing:.14em; font-size:var(--step--1); color:var(--muted); }

.hero{ padding:var(--space-5) 0 var(--space-6); }
.hero h1{ font-family:var(--font-cond); font-weight:700;
          font-size:var(--step-6); line-height:.94; margin-top:var(--space-3); }
.hero .lead{ font-size:var(--step-1); color:var(--muted); max-width:var(--measure); margin-top:var(--space-4); }

/* copy slots: the owner's words go here (H, P, S). Remove the class once the line is in. */
.slot{ outline:1px dashed var(--line); outline-offset:6px; border-radius:2px; }

/* ── the gift form ── */
.give{ border-top:1px solid var(--line); padding-block:var(--space-6);
       display:flex; flex-direction:column; gap:var(--space-5); max-width:var(--measure); }
.give fieldset{ border:0; padding:0; min-width:0; }
.give legend{ padding:0; margin-bottom:var(--space-3); }
/* the form's own heading above Amount (the owner, 2026-10-29), held closer to its first field */
.give-h{ font-size:var(--step-3); line-height:1; }
.give-h + fieldset{ margin-top:calc(var(--space-3) - var(--space-5)); }

/* ── the stepped sections (the owner, 2026-10-29): a mono heading each, set like a label; a section
   opens once the ones before it are complete, and a closed one shows only its heading. Without
   JavaScript every section is open. V1, the single long form, is git tag give-v1. ── */
/* no lines between the sections, just space (the owner, 2026-10-29) */
.step{ padding-top:var(--space-4); }
.step + .step{ margin-top:calc(var(--space-3) - var(--space-5)); }
.give-h + .step{ padding-top:0; margin-top:calc(var(--space-3) - var(--space-5)); }
.step__h{ margin:0; }
/* the titles stay --fg in every state, open or closed, with no hover, tap or open color (the owner,
   2026-10-29). Until then a closed section's title was --muted, which read as locked though a tap opens it. */
.step__btn{ display:block; width:100%; margin:0; padding:0; border:0; background:none; text-align:left; cursor:pointer;
            font-family:var(--font-mono); font-weight:500; text-transform:uppercase; letter-spacing:.14em;
            font-size:var(--step-0); line-height:1.3; color:var(--fg); -webkit-tap-highlight-color:transparent; }
.step__panel{ display:grid; grid-template-rows:1fr; transition:grid-template-rows .4s var(--ease); }
html.js .step:not(.is-open) .step__panel{ grid-template-rows:0fr; }
/* the inline padding and matching negative margin leave room for focus rings inside the clip */
.step__inner{ min-height:0; overflow:hidden; display:flex; flex-direction:column; gap:var(--space-5);
              padding:var(--space-4) 6px 6px; margin-inline:-6px; transition:opacity .3s var(--ease); }
html.js .step:not(.is-open) .step__inner{ opacity:0; }
@media (prefers-reduced-motion:reduce){ .step__panel, .step__inner{ transition:none; } }

/* amount tiles: the support tier pill, on the page's own tokens */
.tiers{ display:flex; flex-wrap:wrap; gap:.625rem; }
.tier{ position:relative; }
.tier input{ position:absolute; opacity:0; width:1px; height:1px; pointer-events:none; }
.tier span{ display:inline-flex; align-items:center; justify-content:center; min-width:5.5rem; min-height:44px;
            padding:.7em 1.15em; cursor:pointer; border-radius:999px;
            font-family:var(--font-mono); font-weight:500; font-size:var(--step-0);
            font-variant-numeric:tabular-nums; letter-spacing:.04em;
            color:var(--fg); background:transparent; border:2px solid var(--line);
            transition:background .15s var(--ease), color .15s var(--ease),
                       border-color .15s var(--ease), transform .15s var(--ease); }
.tier span:hover{ border-color:var(--fg); transform:translateY(-1px); }
.tier input:checked + span{ background:var(--fg); color:var(--bg); border-color:var(--fg); }
.tier input:focus-visible + span{ outline:2px solid var(--focus); outline-offset:3px; }

/* without JS the Other amount is a plain field; with JS the keypad replaces it */
.other-field{ margin-top:var(--space-3); display:flex; align-items:center; gap:.5em;
              font-family:var(--font-mono); font-size:var(--step-1); }
.other-field input{ font:inherit; color:var(--fg); background:transparent; width:9ch;
                    border:0; border-bottom:2px solid var(--line); padding:.2em 0; }
.other-field input:focus{ outline:0; border-color:var(--fg); }
html.js .other-field{ display:none; }

/* fee choice: a real checkbox drawn as a switch */
.fee{ display:flex; align-items:center; gap:var(--space-3); cursor:pointer; }
/* the running joke sits beside the label in a softer grey, and wraps under it on a narrow screen
   (the owner, 2026-10-29); the fifth flip leaves the switch off and greyed out */
.fee-row{ display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-1) var(--space-3); }
.fee__note{ color:var(--muted); font-size:var(--step--1); }
/* each new line fades and rises in (the owner, 2026-10-29); under reduced motion it just appears */
.fee__note.is-new{ animation:fee-note-in .5s var(--ease) both; }
@keyframes fee-note-in{ from{ opacity:0; transform:translateY(.4em); } to{ opacity:1; transform:none; } }
@media (prefers-reduced-motion:reduce){ .fee__note.is-new{ animation:none; } }
.fee input:disabled, .fee input:disabled + span{ opacity:.45; cursor:default; }
.fee:has(input:disabled){ cursor:default; }
.fee input{ appearance:none; -webkit-appearance:none; flex:none; margin:0; cursor:pointer;
            width:2.75rem; height:1.6rem; border-radius:999px; position:relative;
            background:rgba(128,128,128,.28);                       /* Safari before 16.2 */
            background:color-mix(in srgb, var(--fg) 14%, transparent);
            transition:background .2s var(--ease); }
.fee input::after{ content:""; position:absolute; top:.2rem; left:.2rem; width:1.2rem; height:1.2rem;
                   border-radius:50%; background:var(--fg); transition:transform .2s var(--ease); }
.fee input:checked{ background:var(--pink); }
.fee input:checked::after{ transform:translateX(1.15rem); background:var(--ink); }

/* the running total + the handoff */
.total{ display:flex; align-items:baseline; justify-content:space-between; gap:var(--space-3);
        border-top:1px solid var(--line); padding-top:var(--space-4); }
.total .num{ font-family:var(--font-mono); font-weight:500; font-variant-numeric:tabular-nums;
             font-size:var(--step-3); line-height:1; }
.go{ display:inline-flex; align-items:center; justify-content:center; width:100%;
     font-family:var(--font-mono); font-weight:500; text-transform:uppercase;
     letter-spacing:.14em; font-size:var(--step--1); line-height:1;
     padding:1.1em 1.5em; min-height:52px; border-radius:999px; cursor:pointer;
     background:var(--pink); color:var(--ink); border:2px solid var(--pink);
     transition:transform .15s var(--ease), opacity .15s var(--ease); }
.go:hover{ transform:translateY(-1px); }
.go:disabled{ opacity:.45; cursor:default; transform:none; }
/* busy after Continue: a bare spinner, no words (their two steps can take a few seconds) */
.go[aria-busy="true"]{ position:relative; color:transparent; }
.go[aria-busy="true"]::after{ content:""; position:absolute; inset:0; margin:auto; width:1.1em; height:1.1em;
                              border-radius:50%; border:2px solid var(--ink); border-right-color:transparent;
                              animation:give-spin .8s linear infinite; }
@keyframes give-spin{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){ .go[aria-busy="true"]::after{ animation:none; } }
.err{ min-height:1.2em; color:var(--fg); font-size:var(--step--1); }
.sponsor{ color:var(--muted); font-size:var(--step--1); max-width:var(--measure); }

@media (prefers-reduced-motion:reduce){
  .tier span, .fee input, .fee input::after, .go{ transition:none; }
}

/* ── donor details: underline fields in the mono label voice ── */
.group{ border:0; padding:0; margin:0; min-width:0; display:flex; flex-direction:column; gap:var(--space-4); }
.group legend{ padding:0; margin-bottom:var(--space-3); }
.row{ display:grid; gap:var(--space-4); grid-template-columns:repeat(auto-fit, minmax(min(100%,12rem),1fr)); }
.field{ display:flex; flex-direction:column; gap:.35em; min-width:0; }
.field input, .field select, .field textarea{
  font:inherit; color:var(--fg); background:transparent; width:100%; min-height:44px;
  border:0; border-bottom:2px solid var(--line); border-radius:0; padding:.45em 0;
  transition:border-color .2s var(--ease); }
.field textarea{ min-height:5.5em; resize:vertical; }
.field input:focus, .field select:focus, .field textarea:focus{ outline:0; border-color:var(--fg); }
.field select{ appearance:none; -webkit-appearance:none; padding-right:1.6em; cursor:pointer; }
.field select option{ color:var(--fg); background:var(--bg); }
/* a missed field (the owner, 2026-10-29): its underline and its label turn pink until it holds a
   valid answer, then go straight back */
.field.is-missed input, .field.is-missed select, .field.is-missed textarea{ border-bottom-color:var(--pink); }
.field.is-missed > .mono{ color:var(--pink); }
/* browser autofill (the owner, 2026-10-29): our own faint tint instead of Safari's yellow or Chrome's
   blue, a touch lighter than black in dark mode and a light grey in light mode. Browsers lock the
   autofill background, so an inset shadow paints over it (the plain page color first, for browsers
   without color-mix). Two rules, since a browser that misses one pseudo class drops its whole rule. */
.field input:-webkit-autofill, .field select:-webkit-autofill, .field textarea:-webkit-autofill{
  -webkit-text-fill-color:var(--fg); caret-color:var(--fg);
  box-shadow:0 0 0 1000px var(--bg) inset;
  box-shadow:0 0 0 1000px color-mix(in srgb, var(--fg) 10%, var(--bg)) inset;
  transition:border-color .2s var(--ease), background-color 9999s ease-out 0s; }
.field input:autofill, .field select:autofill, .field textarea:autofill{
  -webkit-text-fill-color:var(--fg); caret-color:var(--fg);
  box-shadow:0 0 0 1000px var(--bg) inset;
  box-shadow:0 0 0 1000px color-mix(in srgb, var(--fg) 10%, var(--bg)) inset;
  transition:border-color .2s var(--ease), background-color 9999s ease-out 0s; }
.select{ position:relative; display:block; }
.select svg{ position:absolute; right:0; top:50%; width:1.2em; height:1.2em; transform:translateY(-50%);
             fill:currentColor; color:var(--muted); pointer-events:none; }

/* how the gift is listed: round pickers that fill solid pink when chosen, no dot inside (the owner,
   2026-10-29; they were native radios in accent pink, which draw a dot) */
.choices{ display:flex; flex-direction:column; gap:var(--space-2); }
.choice{ display:flex; align-items:flex-start; gap:var(--space-2); cursor:pointer; color:var(--fg); }
.choice input{ appearance:none; -webkit-appearance:none; width:1.1rem; height:1.1rem; margin:.3em 0 0; flex:none;
               border-radius:50%; border:2px solid var(--muted); background:transparent; cursor:pointer;
               transition:background-color .15s var(--ease), border-color .15s var(--ease); }
.choice input:checked{ background:var(--pink); border-color:var(--pink); }
@media (prefers-reduced-motion:reduce){ .choice input{ transition:none; } }
/* high contrast modes repaint custom colors, so the chosen one keeps a system fill */
@media (forced-colors:active){ .choice input{ forced-color-adjust:none; border-color:CanvasText; }
                               .choice input:checked{ background:Highlight; border-color:Highlight; } }
html.js .field[data-reason][hidden]{ display:none; }

.consent{ color:var(--muted); font-size:var(--step--1); }
.consent a{ color:var(--fg); text-decoration:underline; text-decoration-color:color-mix(in srgb, var(--fg) 30%, transparent); }
/* the fine print sits together right under the button (the owner, 2026-10-29) */
.go + .consent{ margin-top:calc(var(--space-4) - var(--space-5)); }
.consent + .sponsor{ margin-top:calc(var(--space-3) - var(--space-5)); }

/* ── the handoff screen (go.php): the total and one clear button ── */
.handoff{ padding-block:var(--space-7); display:flex; flex-direction:column; gap:var(--space-4); max-width:var(--measure); }
.handoff__total{ font-family:var(--font-mono); font-weight:500; font-variant-numeric:tabular-nums;
                 font-size:var(--step-5); line-height:1; }
a.go{ text-decoration:none; }
.go[aria-disabled="true"]{ opacity:.45; pointer-events:none; }

/* ── after Continue, with JavaScript: the thank you card takes the form's place (the owner, 2026-10-29) ── */
.give[hidden], .sent[hidden]{ display:none; }
.sent{ border-top:1px solid var(--line); padding-block:var(--space-6);
       display:flex; flex-direction:column; gap:var(--space-4); max-width:var(--measure); }
.sent:focus{ outline:0; }
.sent__total{ font-family:var(--font-mono); font-weight:500; font-variant-numeric:tabular-nums;
              font-size:var(--step-4); line-height:1; }
.sent__note{ font-size:var(--step-1); color:var(--muted); }
.sent__retry{ font-size:var(--step--1); color:var(--muted); margin-top:var(--space-4); }
/* Finalize (solid pink) and Edit (outlined) side by side, sharing the width; they stack on a screen
   too narrow for both labels (the owner, 2026-10-29) */
.sent__actions{ display:grid; gap:var(--space-3);
                grid-template-columns:repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }
.sent__retry + .sent__actions{ margin-top:calc(var(--space-2) - var(--space-4)); }
.go.ghost{ background:transparent; color:var(--fg); border-color:var(--line); }

/* the checkout tab's wait (go.php) before Stripe: a bare spinner, no words */
.opening{ width:2rem; height:2rem; margin:var(--space-7) auto; border-radius:50%;
          border:2px solid var(--fg); border-right-color:transparent; animation:give-spin .8s linear infinite; }
@media (prefers-reduced-motion:reduce){ .opening{ animation:none; } }
html:not(.js) .opening{ display:none; }   /* without JavaScript the checkout tab shows the button instead */
