/* =====================================================================
   EPQX — TOKENS + RESET + CHROME + ELEMENT "LOOK"
   ---------------------------------------------------------------------
   This is the ONLY stylesheet for the new EPQ engine ("EPQX").

   Design philosophy that keeps layouts from ever breaking:
     1. Everything is scoped under .epqx-root, so it can never collide
        with the host theme or page builder (Breakdance, etc.).
     2. The ENGINE writes every instance-specific value (a screen's size,
        a container's grid, an element's spacing/colour) as an INLINE
        style. Inline styles always beat class rules, so we NEVER need a
        single `!important`. That is the whole reason the old EPQ became a
        war of overrides — here it simply cannot happen.
     3. This file only defines (a) tokens you can re-skin globally and
        (b) the consistent "look" of each element type. Layout lives in
        the schema, not here.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. TOKENS  — change these to re-skin the entire questionnaire at once.
   --------------------------------------------------------------------- */
.epqx-root {
  --epqx-font: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif;

  --epqx-ink:   #1a1f2b;   /* primary text                       */
  --epqx-muted: #6b7280;   /* secondary text / labels            */
  --epqx-line:  #d0d5dd;   /* input + card borders               */
  --epqx-gold:  #d8ae66;   /* brand accent (progress, primary)   */
  --epqx-dark:  #101828;   /* dark "Continue" button             */
  --epqx-yes:   #14a84a;   /* affirmative glyph colour           */
  --epqx-no:    #e02424;   /* negative glyph colour              */

  --epqx-page:  #f7f7f9;   /* area outside the white card        */
  --epqx-card:  #ffffff;   /* the white screen card              */
  --epqx-stage: transparent; /* the inner "stage" (editor can tint this) */

  --epqx-radius:    4px;  /* inputs / small elements            */
  --epqx-radius-lg: 26px;  /* the screen card                    */

  /* Spacing scale — engine maps numeric style values to px, but these
     are handy reference values for authors building schemas.          */
  --epqx-gap: 20px;

  /* -------------------------------------------------------------------
     1b. EXPERIENCE FOUNDATION TOKENS (v1.0.103)
     -------------------------------------------------------------------
     Every value below is the value ALREADY in use somewhere in this
     stylesheet — these tokens name the existing look rather than
     restyling it, so later phases have one place to reach for instead
     of re-typing literals. The seven original tokens above are left
     exactly as they were (the editor and older rules reference them).
     Two exceptions are called out inline: --epqx-warning and the focus
     ring, which had no prior value to inherit.
     ------------------------------------------------------------------- */

  /* Surfaces */
  --epqx-surface:        #ffffff;   /* same as --epqx-card                     */
  --epqx-surface-raised: #fbfcfe;   /* elevated panel (recommendation asset)   */
  --epqx-surface-sunken: #f6f6f8;   /* inset rows (mobile asset cards)         */

  /* Text */
  --epqx-text:           #1a1f2b;   /* same as --epqx-ink                      */
  --epqx-text-secondary: #4a5567;   /* body copy on review cards               */
  --epqx-text-muted:     #6b7280;   /* same as --epqx-muted                    */

  /* Brand */
  --epqx-blue:      #1f4e79;        /* GBF steel navy (review headings)        */
  --epqx-blue-dark: #1c4468;        /* pressed/hover companion to the navy     */
  --epqx-gold-dark: #c89b4b;        /* gold gradient companion, already in use */

  /* Status. --epqx-yes / --epqx-no above stay as the glyph colours.           */
  --epqx-success:        #1ba94c;   /* affirmative action (review button)      */
  --epqx-success-strong: #169042;
  --epqx-warning:        #9a6b16;   /* NEW: dark amber from the gold family    */
  --epqx-error:          #cf4231;   /* validation popup                        */
  --epqx-error-border:   #e02424;   /* invalid field border                    */
  --epqx-error-text:     #c0392b;   /* inline field-error copy                 */

  /* Borders */
  --epqx-line-soft:   #eaecf0;      /* the screen card's own hairline          */
  --epqx-line-strong: #cfd2d8;      /* money inputs                           */
  --epqx-line-cool:   #e6ecf3;      /* review-page cards                       */

  /* Focus. NEW: navy is used (not gold) so keyboard focus is never confused
     with the gold "selected" state, and it clears 4.5:1 on white.             */
  --epqx-focus:          #1f4e79;
  --epqx-focus-ring:     0 0 0 3px rgba(31, 78, 121, 0.38);
  --epqx-focus-ring-inset: inset 0 0 0 2px rgba(31, 78, 121, 0.55);
  --epqx-ring-gold:      0 0 0 4px rgba(216, 174, 102, 0.16);  /* field focus  */
  --epqx-ring-selected:  0 0 0 4px rgba(216, 174, 102, 0.20);  /* chosen card  */

  /* Shadows */
  --epqx-shadow-sm:    0 10px 24px rgba(17, 24, 39, 0.08);
  --epqx-shadow-md:    0px 0px 20px rgba(0, 0, 0, 0.10);
  --epqx-shadow-lg:    0px 0px 30px rgba(0, 0, 0, 0.30);
  --epqx-shadow-modal: 0 24px 60px rgba(17, 24, 39, 0.32);

  /* Radii */
  --epqx-radius-input: 4px;    /* same as --epqx-radius                       */
  --epqx-radius-card:  18px;   /* selectable choice cards                     */
  --epqx-radius-modal: 22px;
  --epqx-radius-pill:  999px;

  /* Widths */
  --epqx-width-max:  1500px;   /* widest content column (review page)         */
  --epqx-width-form: 760px;    /* form column (deeds panel, modals)          */
  --epqx-width-read: 640px;    /* comfortable reading measure                 */

  /* Minimum touch target (reference value for later phases; nothing is
     resized in this phase).                                                  */
  --epqx-touch: 44px;

  /* Spacing */
  --epqx-space-xs:      6px;
  --epqx-space-sm:      10px;
  --epqx-space-md:      20px;  /* same as --epqx-gap                          */
  --epqx-space-lg:      26px;
  --epqx-space-xl:      32px;
  --epqx-space-2xl:     44px;
  --epqx-space-section: 40px;  /* gap between major sections                  */

  /* -------------------------------------------------------------------
     1d. VERTICAL RHYTHM (v1.0.104)
     -------------------------------------------------------------------
     One place to tune how much air the questionnaire breathes. Used by
     the chrome and by the shared element rules below — screens do not
     carry their own margins for this.
     ------------------------------------------------------------------- */
  --epqx-space-field:    22px;  /* a field row to the next row's label        */
  --epqx-space-label:    8px;   /* a label to the control it names             */
  --epqx-rhythm-kicker:  20px;  /* section label to the screen heading        */
  --epqx-rhythm-heading: 44px;  /* screen heading to the first question       */
  --epqx-rhythm-stack:   10px;  /* extra air between stacked field rows       */
  --epqx-rhythm-nav:     30px;  /* last question to the navigation row        */
  --epqx-card-pad-y:     32px;  /* the white surface's vertical padding       */
  --epqx-card-pad-x:     28px;  /* unchanged, so no screen's width shifts     */

  /* -------------------------------------------------------------------
     1e. TYPE SCALE (v1.0.104)
     -------------------------------------------------------------------
     Seven deliberate levels. Sizes a screen sets for itself in the
     schema still win (they are inline), so this is the baseline every
     screen falls back to — not a cap on the design.
     ------------------------------------------------------------------- */
  --epqx-fs-kicker:   13px;                        /* section / kicker        */
  --epqx-fs-heading:  clamp(28px, 3.4vw, 48px);    /* main screen heading     */
  --epqx-fs-lead:     clamp(15px, 1.4vw, 19px);    /* supporting text         */
  --epqx-fs-question: clamp(17px, 1.6vw, 20px);    /* question heading        */
  --epqx-fs-label:    14px;                        /* field label             */
  --epqx-fs-help:     13.5px;                      /* help text               */
  --epqx-fs-error:    13px;                        /* validation text         */

  --epqx-lh-heading: 1.15;   /* was 1.12 — kinder to two- and three-line heads */
  --epqx-lh-question: 1.4;
  --epqx-lh-body:    1.62;   /* was 1.5 — the main reading-comfort change      */
  --epqx-lh-label:   1.35;
  --epqx-lh-tight:   1.3;

  /* -------------------------------------------------------------------
     1c. MOTION TOKENS (v1.0.103)
     -------------------------------------------------------------------
     Durations are chosen to MATCH the timings already in the file, so
     retrofitting them changes nothing visually. Anything new in a later
     phase should reach for these names rather than typing a duration.
     ------------------------------------------------------------------- */
  --epqx-dur-instant:  120ms;  /* pressed / released                          */
  --epqx-dur-fast:     150ms;  /* button + pill feedback                      */
  --epqx-dur-standard: 180ms;  /* card selection, hover settle                */
  --epqx-dur-reveal:   200ms;  /* conditional field appearing                 */
  --epqx-dur-screen:   240ms;  /* screen exit                                 */
  --epqx-dur-section:  440ms;  /* screen/section entrance                     */
  --epqx-dur-chain:    550ms;  /* card-chain slide (existing value)           */
  /* Screen to screen is a cross-fade (v1.0.114). 110 out + 190 in = 300ms,
     the top of the 220-300ms screen-transition band: long enough to read as
     a dissolve rather than a cut, short enough that nothing waits on it. */
  --epqx-dur-nav-exit:  110ms; /* screen leaving  (v1.0.106, retimed .114)    */
  --epqx-dur-nav-enter: 190ms; /* screen arriving (v1.0.106, retimed .114)    */
  --epqx-nav-shift:     18px;  /* directional shift — retained, see §NAV       */
  --epqx-dur-row-in:    200ms; /* a repeatable row appearing  (v1.0.107)      */
  --epqx-dur-row-out:   160ms; /* a repeatable row collapsing (v1.0.107)      */
  --epqx-dur-select:    180ms; /* choice-card selection (140-200ms band)      */
  --epqx-dur-progress:  240ms; /* progress rail (200-300ms band, v1.0.108)    */
  /* ILLUSTRATION SIZE (v1.0.113). One box for every screen illustration, so
     the questionnaire reads as one set rather than a dozen different crops.
     The default is the size the Guardianship screen was already using, which
     is the one the client picked. Overridable globally and per screen from
     EPQX -> Settings; the engine writes those as inline custom properties. */
  --epqx-illus-w: 260px;
  --epqx-illus-h: 460px;

  --epqx-dur-break-in:  320ms; /* section card arriving (300-450ms, v1.0.111) */
  --epqx-dur-break-out: 180ms; /* section card lifting away    (v1.0.111)     */

  --epqx-ease:       cubic-bezier(0.22, 1, 0.36, 1);   /* standard            */
  --epqx-ease-exit:  cubic-bezier(0.4, 0, 1, 1);       /* leaving             */
  --epqx-ease-chain: cubic-bezier(0.4, 0, 0.2, 1);     /* existing chain      */
  --epqx-ease-slide: cubic-bezier(0.22, 0.61, 0.36, 1);/* existing slide-up   */

  font-family: var(--epqx-font);
  color: var(--epqx-ink);
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------------
   2. RESET  — predictable box model for everything we render.
   --------------------------------------------------------------------- */
.epqx-root,
.epqx-root *,
.epqx-root *::before,
.epqx-root *::after { box-sizing: border-box; }

.epqx-root img { max-width: 100%; height: auto; display: block; }

/* ---------------------------------------------------------------------
   3. CHROME  — the fixed frame every screen sits inside: header,
   progress bar, white card, stage, and the navigation row.
   (Matches the blank-canvas mockup.)
   --------------------------------------------------------------------- */
/* The calm outer frame. Its padding is deliberately unchanged, so no
   screen's usable content width moves; only the shadow is softened (the
   old 30px/30% cast a heavy dark halo around the whole questionnaire). */
.epqx-shell { position: relative; background: var(--epqx-page); padding: 22px; border-radius: 28px; transition: max-width 0.3s ease; box-shadow: 0 18px 44px rgba(16, 24, 40, 0.10), 0 2px 6px rgba(16, 24, 40, 0.04); }

.epqx-header {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  margin-bottom: 12px;
}
.epqx-home { font-size: 30px; line-height: 1; color: #2f2a26; }
.epqx-brand {
  font-size: 13px; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--epqx-muted);
}
.epqx-step {
  justify-self: end;
  font-size: 13px; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--epqx-muted);
}

.epqx-progress {
  height: 10px; background: #e5e7eb; border-radius: 999px;
  overflow: hidden; margin-bottom: 22px;
}
.epqx-progress-fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, #d8ae66, #c89b4b);
  border-radius: inherit;
  transition: width 0.25s ease;
}

/* The white card. The engine sets its max-width per breakpoint inline. */
/* THE primary questionnaire surface. The hairline border was doing the
   same job as the shadow (the card sits on the tinted shell either way),
   so it is gone and a softer, more directional shadow defines the edge.
   Vertical padding grew; HORIZONTAL padding is unchanged on purpose, so
   every screen keeps exactly the content width it was designed at. */
.epqx-card {
  background: var(--epqx-card);
  border: 0;
  border-radius: var(--epqx-radius-lg);
  padding: var(--epqx-card-pad-y, 32px) var(--epqx-card-pad-x, 28px);
  margin: 0 auto;            /* centred; max-width comes from the schema */
  transition: max-width 0.35s ease;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 12px 30px rgba(16, 24, 40, 0.07);
}

/* The stage = the design surface (the light-blue area in the mockup).
   Its min-height comes from the schema per breakpoint. The engine turns
   it into a flex or grid container per the screen's `layout`.           */
/* TOP-ALIGNED, not centred (v1.0.116).
   The stage used to centre its content vertically. At rest that is invisible —
   exactly one screen in the questionnaire is shorter than this 300px minimum —
   but during a screen change the box is deliberately held at the OUTGOING
   height while it eases to the new one, so it is always taller than its
   content mid-animation. Centring then dragged every line of text down or up
   by half the height difference, which is the sliding, stuttering movement the
   transition was reported for. Top-aligned, the card grows and shrinks around
   the text instead of pulling it along. */
.epqx-stage { background: var(--epqx-stage); width: 100%; min-height: 300px; display: flex; flex-direction: column; justify-content: flex-start; }
.epqx-stage h2 { margin-bottom: var(--epqx-rhythm-heading, 44px); }
.epqx-kicker { font-size: var(--epqx-fs-kicker, 13px); font-weight: 800; letter-spacing: 0.08em; line-height: 1.4; text-transform: uppercase; color: var(--epqx-muted); margin-bottom: var(--epqx-rhythm-kicker, 20px); }

/* Navigation row */
.epqx-nav {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 12px; margin-top: var(--epqx-rhythm-nav, 30px);
}
.epqx-nav .epqx-btn-primary { margin-left: auto; }
.epqx-btn-snapshot { background: var(--epqx-gold, #d8ae66); color: #fff; }
.epqx-btn-snapshot:hover { opacity: 0.92; }
.epqx-btn {
  appearance: none; border: 0; border-radius: 4px;
  padding: 14px 26px; font: inherit; font-weight: 700; cursor: pointer;
  transition: transform var(--epqx-dur-fast, 150ms) ease,
              box-shadow var(--epqx-dur-fast, 150ms) ease,
              opacity var(--epqx-dur-fast, 150ms) ease;
}
.epqx-btn:hover { transform: translateY(-1px); }
.epqx-btn-primary { background: var(--epqx-dark); color: #fff; }
.epqx-btn-secondary { background: #fff; border: 1px solid var(--epqx-line); color: var(--epqx-ink); }
.epqx-btn-ghost { background: transparent; color: var(--epqx-muted); padding: 8px 10px; }
/* Plain underlined text link (e.g. "Edit Alternate Representatives
   Information", re-opens a screen's modal on demand) instead of a pill. */
.epqx-btn-link { background: transparent; color: #2563eb; padding: 2px 4px; text-decoration: underline; font-size: 14px; font-weight: 600; align-self: center; }
.epqx-btn-link:hover { color: #1d4ed8; transform: none; }
.epqx-btn[disabled] { opacity: 0.35; cursor: default; transform: none; }

/* ---------------------------------------------------------------------
   4. ELEMENT LOOK  — the consistent styling of each element TYPE.
   Layout/spacing/colour overrides come from the schema as inline styles
   and will transparently win over anything here (no !important needed).
   --------------------------------------------------------------------- */

/* Heading + text */
.epqx-heading { margin: 0; font-weight: 800; line-height: var(--epqx-lh-heading, 1.15); letter-spacing: -0.03em; color: var(--epqx-ink); font-size: var(--epqx-fs-heading, clamp(28px, 3.4vw, 48px)); overflow-wrap: break-word; }
/* Supporting text / instructions. Capped to a comfortable reading
   measure so a paragraph never runs the full width of a wide screen.
   A screen that sets its own maxWidth still wins (that is inline), and
   centred paragraphs stay centred via .epqx-text-center, which the
   engine adds after layout. */
.epqx-text    { margin: 0; line-height: var(--epqx-lh-body, 1.62); color: var(--epqx-muted); font-size: var(--epqx-fs-lead, clamp(15px, 1.4vw, 19px)); max-width: var(--epqx-width-read, 640px); overflow-wrap: break-word; }
.epqx-text-center { margin-inline: auto; }

/* A labelled form field (input or select) */
.epqx-field { display: flex; flex-direction: column; gap: var(--epqx-space-label, 8px); }
/* Breathing room between a field row and the next row's label. Field-grouping
   containers only; the deeds override below is more specific and still wins. */
.epqx-container { margin-bottom: var(--epqx-space-field, 22px); }
.epqx-label { font-size: var(--epqx-fs-label, 14px); font-weight: 600; line-height: var(--epqx-lh-label, 1.35); color: var(--epqx-ink); overflow-wrap: break-word; }
.epqx-input,
.epqx-select {
  width: 100%; height: 48px; padding: 0 16px;
  border: 1px solid var(--epqx-line); border-radius: var(--epqx-radius);
  font: inherit; color: var(--epqx-ink); background: #fff;
}
.epqx-input:focus,
.epqx-select:focus {
  outline: none; border-color: var(--epqx-gold);
  box-shadow: 0 0 0 4px rgba(216, 174, 102, 0.16);
}

/* Multi-line text box */
.epqx-textarea { height: auto; min-height: 120px; padding: 14px 16px; line-height: var(--epqx-lh-body, 1.62); resize: vertical; }

/* Single checkbox + label */
.epqx-check { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 15px; color: var(--epqx-ink); }
.epqx-check input { width: 18px; height: 18px; accent-color: var(--epqx-gold); }

/* Selectable cards (Yes/No, image-choice, etc.) */
.epqx-card-opt {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 18px;
  border: 1px solid var(--epqx-line); border-radius: 18px; background: #fff;
  cursor: pointer; text-align: center;
  transition: border-color var(--epqx-dur-standard, 180ms) ease,
              box-shadow var(--epqx-dur-standard, 180ms) ease,
              transform var(--epqx-dur-standard, 180ms) ease;
}
.epqx-card-opt:hover { border-color: var(--epqx-gold); transform: translateY(-2px); }
.epqx-card-opt.is-selected { border-color: var(--epqx-gold); box-shadow: var(--epqx-ring-selected, 0 0 0 4px rgba(216, 174, 102, 0.2)); }
.epqx-card-opt input { position: absolute; opacity: 0; pointer-events: none; }   /* a11y radio, visually hidden */
.epqx-card-glyph { font-weight: 900; line-height: 1; font-size: clamp(64px, 9vw, 120px); }
.epqx-card-glyph.is-yes { color: var(--epqx-yes); }
.epqx-card-glyph.is-no  { color: var(--epqx-no); }
.epqx-card-img { width: 170px; height: 170px; object-fit: contain; display: block; }
.epqx-card-separator { font-size: 38px; font-weight: 800; color: var(--epqx-ink, #1a1f2b); align-self: center; }
.epqx-richline { margin: 0; font-size: clamp(20px, 2.6vw, 30px); line-height: 1.7; font-weight: 600; color: var(--epqx-ink, #1a1f2b); }
.epqx-richline-inline { display: flex; align-items: center; flex-wrap: wrap; }
.epqx-add-right { align-self: flex-end; }
.epqx-underline-input .epqx-input { border: none; border-bottom: 2px solid var(--epqx-gold, #c79a52); border-radius: 0; background: transparent; text-align: center; padding: 8px 2px; width: 100%; }
.epqx-underline-input .epqx-input:focus { outline: none; box-shadow: none; border-bottom-color: #14181f; }
.epqx-inline-input { display: inline-block; width: 70px; border: 0; border-bottom: 2px solid var(--epqx-gold, #c79a52); background: transparent; text-align: center; font: inherit; font-weight: 700; color: var(--epqx-ink, #1a1f2b); margin: 0 4px; }
.epqx-inline-input:focus { outline: none; border-bottom-color: var(--epqx-ink, #1a1f2b); }
.epqx-rest-card { border: 1px solid var(--epqx-line, #e4e7ec); border-radius: 16px; padding: 18px 20px; background: #fff; }
.epqx-rest-badge { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; background: var(--epqx-gold, #c79a52); color: #fff; font-weight: 800; }

/* Asset Inventory table (Section 5) */
.epqx-asset-table { display: flex; flex-direction: column; width: 100%; }
.epqx-asset-row { display: grid; grid-template-columns: 1.7fr 1.4fr 1.4fr 1.8fr; align-items: center; gap: 16px; padding: 10px 0; border-bottom: 1px solid #ececef; }
.epqx-asset-head { border-bottom: 1px solid #d7d7dc; padding-bottom: 12px; }
.epqx-asset-head .epqx-asset-item, .epqx-asset-head .epqx-asset-cell, .epqx-asset-head .epqx-asset-owner { font-size: 13px; font-weight: 700; letter-spacing: 0.04em; color: #6b7280; text-transform: uppercase; }
/* v1.0.114 — the Asset Inventory list reads left-to-right from one edge.
   Every column (item, value, debt, owner) starts at its own left edge and the
   header sits directly above the control it names, instead of each column
   being centred in its share of the row. Mobile already worked this way. */
.epqx-asset-head .epqx-asset-cell, .epqx-asset-head .epqx-asset-owner { text-align: left; display: block; }
.epqx-asset-item { font-size: 16px; color: var(--epqx-ink, #1a1f2b); }
.epqx-asset-cell { display: flex; justify-content: flex-start; }
.epqx-money { display: flex; align-items: center; gap: 6px; min-height: 48px; border: 1px solid var(--epqx-line-strong, #cfd2d8); border-radius: var(--epqx-radius-input, 4px); padding: 0 12px; width: 100%; max-width: 240px; background: #fff; }
.epqx-money:focus-within { border-color: var(--epqx-gold, #c79a52); }
.epqx-money-sign { color: #9aa0aa; }
.epqx-money-input { border: none; outline: none; align-self: stretch; padding: 12px 0; width: 100%; font-size: 16px; background: transparent; }
.epqx-asset-owner { display: flex; align-items: center; justify-content: flex-start; gap: 18px; }
.epqx-owner-radios { display: flex; gap: 18px; }
.epqx-owner-opt { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.epqx-owner-opt input { appearance: radio; -webkit-appearance: radio; width: 18px; height: 18px; accent-color: var(--epqx-gold, #c79a52); }
.epqx-owner-select { display: none; width: 100%; max-width: 220px; padding: 12px; border: 1px solid #cfd2d8; border-radius: 4px; background: #fff; font-size: 15px; }
.epqx-asset-totals { display: flex; flex-wrap: wrap; gap: 28px; justify-content: flex-end; padding: 18px 0 4px; font-size: 16px; }
.epqx-asset-total-item { color: #4b5563; font-weight: 600; }
.epqx-asset-total-net { color: var(--epqx-ink, #1a1f2b); font-weight: 800; }
.epqx-asset-table.is-mobile .epqx-asset-head { display: none; }
.epqx-asset-table.is-mobile .epqx-asset-row { grid-template-columns: 1fr 1fr; grid-template-areas: "item item" "value debt" "owner owner"; gap: 10px; background: #f6f6f8; border: 1px solid #ececef; border-radius: 12px; padding: 14px; margin-bottom: 12px; }
.epqx-asset-table.is-mobile .epqx-asset-item { grid-area: item; font-weight: 700; }
.epqx-asset-table.is-mobile .epqx-asset-cell:nth-of-type(2) { grid-area: value; }
.epqx-asset-table.is-mobile .epqx-asset-cell:nth-of-type(3) { grid-area: debt; }
.epqx-asset-table.is-mobile .epqx-asset-cell { justify-content: stretch; }
.epqx-asset-table.is-mobile .epqx-money { max-width: none; }
.epqx-asset-table.is-mobile .epqx-asset-owner { grid-area: owner; justify-content: stretch; }
.epqx-asset-table.is-mobile .epqx-owner-radios { display: none; }
.epqx-asset-table.is-mobile .epqx-owner-select { display: block; }
.epqx-asset-table.is-mobile .epqx-asset-totals { justify-content: flex-start; }

/* Validation warning popup (red) */
.epqx-warn-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(20,24,31,0.45); border-radius: 28px; z-index: 90; box-sizing: border-box; }
.epqx-warn { width: min(640px, 96%); background: #cf4231; border-radius: 22px; padding: 36px 40px; box-shadow: 0 24px 60px rgba(0,0,0,0.35); }
.epqx-warn-msg { color: #fff; font-size: clamp(24px, 3vw, 34px); font-weight: 800; line-height: 1.2; margin-bottom: 28px; }
.epqx-warn-actions { display: flex; gap: 16px; justify-content: flex-end; flex-wrap: wrap; }
.epqx-warn-confirm, .epqx-warn-edit { cursor: pointer; border-radius: 4px; padding: 14px 28px; font-weight: 800; font-size: 16px; }
.epqx-warn-confirm { background: transparent; color: #fff; border: 2px solid #fff; }
.epqx-warn-confirm:hover { background: rgba(255,255,255,0.12); }
.epqx-warn-edit { background: #fff; color: #cf4231; border: 2px solid #fff; }
.epqx-warn-edit:hover { background: #f3f3f3; }
.epqx-card-opt.is-disabled { cursor: default; pointer-events: none; opacity: 0.5; }
.epqx-card-opt.epqx-card-bare { border: 0; background: transparent; padding: 0; box-shadow: none; }
.epqx-card-opt.epqx-card-bare:hover { border: 0; transform: none; }
.epqx-card-opt.epqx-card-bare.is-selected { border: 0; box-shadow: none; }

/* Per-screen modal (e.g. critical-decision alternates) */
.epqx-modal-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(247,247,249,0.72); border-radius: 28px; z-index: 60; box-sizing: border-box; }
.epqx-modal { width: min(760px, 94%); max-height: 88%; overflow-y: auto; background: #d8ae66; border-radius: 24px; box-shadow: 0 24px 60px rgba(17,24,39,0.32); padding: 34px 36px 30px; position: relative; box-sizing: border-box; }
/* "Name Your Alternate Representatives" (the 3 critical-decision screens):
   taller than the default modal so its two-tab form fits without scrolling. */
.epqx-modal.epqx-modal-alt-reps { width: min(860px, 96%); max-height: 96%; }
.epqx-modal-close { position: absolute; top: 14px; right: 16px; width: 34px; height: 34px; border: 0; background: transparent; color: #3a2f15; font-size: 26px; line-height: 1; cursor: pointer; border-radius: 4px; }
.epqx-modal-close:hover { background: rgba(0,0,0,0.12); }
.epqx-modal-title { font-size: 22px; font-weight: 800; color: #2c2410; margin-bottom: 6px; text-align: center; }
.epqx-modal-intro { text-align: center; font-style: italic; color: #2c2410; margin: 0 0 22px; }
.epqx-modal-tabs { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-bottom: 22px; }
.epqx-modal-tab { border: 0; cursor: pointer; padding: 10px 16px; border-radius: 4px; background: rgba(60,45,12,0.22); color: #3a2f15; font-weight: 700; font-size: 14px; }
.epqx-modal-tab:hover { background: rgba(37,37,37,0.45); color: #fff; }
.epqx-modal-tab.is-active { background: #252525; color: #fff; }
.epqx-modal-panel { display: none; }
.epqx-modal-panel.is-active { display: block; }
.epqx-modal-panel .epqx-field { margin-bottom: 14px; }
.epqx-modal-panel .epqx-label { color: #3a2f15; text-transform: uppercase; letter-spacing: 0.05em; font-size: 12px; font-weight: 700; }
.epqx-modal-panel .epqx-input { background: #ead9b6; border: 0; color: #2c2410; }
.epqx-modal-footer { display: flex; justify-content: flex-end; margin-top: 8px; }
.epqx-modal-continue { border: 0; cursor: pointer; background: #14181f; color: #fff; font-weight: 700; padding: 14px 34px; border-radius: 4px; }
.epqx-modal-continue:hover { background: #000; }

/* Inline radio group + action button (children screens) */
.epqx-radiogroup { flex-wrap: wrap; }
/* Question-level, not screen-level: at 30px this competed with the screen
   heading right above it and pushed its own Yes/No answers onto a second
   line. The question is unchanged; only its size is. */
.epqx-radiogroup-label { font-weight: 800; font-size: var(--epqx-fs-question, clamp(17px, 1.6vw, 20px)); color: var(--epqx-ink, #1a1f2b); margin-right: 8px; }
.epqx-radio { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; cursor: pointer; }
.epqx-radio input { width: 20px; height: 20px; accent-color: var(--epqx-gold, #c79a52); }
.epqx-action-btn { background: var(--epqx-gold, #c79a52); color: #fff; border: 0; border-radius: 4px; padding: 14px 30px; font-weight: 800; cursor: pointer; align-self: flex-start; }
.epqx-action-btn:hover { filter: brightness(0.96); }
.epqx-child-media { width: 100%; min-height: 360px; background: center bottom / contain no-repeat; }

/* Tooltip (info icon on a heading) */
.epqx-tip { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 7px; border-radius: 50%; background: var(--epqx-gold, #c79a52); border: 2px solid #14181f; color: #14181f; font-size: 14px; font-weight: 800; font-style: normal; line-height: 1; cursor: help; position: relative; vertical-align: middle; box-sizing: border-box; }
.epqx-tip-bubble { display: none; position: absolute; top: 130%; left: 50%; transform: translateX(-50%); width: 480px; max-width: 90vw; background: #14181f; color: #fff; font-size: 18px; font-weight: 400; font-style: normal; line-height: 1.5; letter-spacing: 0.2px; text-align: left; padding: 16px 18px; border-radius: 10px; z-index: 70; box-shadow: 0 10px 30px rgba(0,0,0,0.25); }
.epqx-tip:hover .epqx-tip-bubble { display: block; }
@media (max-width: 640px) { .epqx-tip-bubble { width: 260px; font-size: 15px; padding: 12px 14px; } }

/* Inline tabs (single critical-decision form) */
.epqx-tabs.epqx-gold-form { background: #d8ae66; border-radius: 22px; padding: 26px 28px; }
.epqx-tabbar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
.epqx-tab { border: 0; cursor: pointer; padding: 9px 18px; border-radius: 4px; background: rgba(60,45,12,0.22); color: #3a2f15; font-weight: 700; font-size: 14px; }
.epqx-tab.is-active { background: #14181f; color: #fff; }
.epqx-tabpanel { display: none; }
.epqx-tabpanel.is-active { display: block; }

/* Deeds (Section 6) — centered gold/gray pill tabs */
.epqx-deeds .epqx-tabbar { justify-content: center; gap: 14px; margin-bottom: 30px; }
.epqx-deeds .epqx-tab { background: #f1efe9; color: #b3ad9f; padding: 14px 38px; font-size: 16px; font-weight: 800; letter-spacing: 0.03em; }
.epqx-deeds .epqx-tab.is-active { background: var(--epqx-gold, #c79a52); color: #14181f; }
.epqx-deeds .epqx-tabpanel { max-width: 760px; margin: 0 auto; }
.epqx-deeds .epqx-tabpanel > .epqx-field, .epqx-deeds .epqx-tabpanel > .epqx-container { margin-bottom: 30px; }
.epqx-deeds .epqx-tabpanel > .epqx-field:last-child, .epqx-deeds .epqx-tabpanel > .epqx-container:last-child { margin-bottom: 0; }
.epqx-deeds .epqx-label { text-transform: uppercase; letter-spacing: 0.04em; font-size: 13px; color: #6b7280; font-weight: 700; }
.epqx-gold-form .epqx-label { color: #4a3c18; text-transform: uppercase; letter-spacing: 0.05em; font-size: 12px; font-weight: 800; }
.epqx-gold-form .epqx-input { background: #ead9b6; border: 0; color: #2c2410; }

/* File upload */
.epqx-fileupload-row { display: flex; align-items: center; gap: 10px; }
.epqx-field.epqx-fileupload { align-items: center; }
.epqx-fileupload-icon { font-size: 18px; }
.epqx-fileupload-status { display: block; margin-top: 6px; font-size: 13px; color: var(--epqx-muted, #6b7280); }

/* Table-of-contents dropdown in the kicker */
.epqx-kicker { display: flex; align-items: center; gap: 10px; position: relative; }
.epqx-toc-btn { border: 0; background: transparent; cursor: pointer; color: var(--epqx-muted, #6b7280); font-size: 15px; padding: 2px 4px; border-radius: 4px; }
.epqx-toc-btn:hover { color: var(--epqx-ink, #1a1f2b); background: rgba(0,0,0,0.05); }
.epqx-toc-menu { position: fixed; top: 0; left: 0; min-width: 320px; max-width: min(92vw, 420px); background: #fff; border: 1px solid #e4e7ec; border-radius: 12px; box-shadow: 0 18px 44px rgba(17,24,39,0.18); padding: 8px; z-index: 2147483000; overflow-y: auto; -webkit-overflow-scrolling: touch; font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif; }
.epqx-toc-item { display: block; width: 100%; text-align: left; border: 0; background: transparent; cursor: pointer; padding: 10px 12px; border-radius: 4px; font: inherit; font-weight: 600; color: var(--epqx-ink, #1a1f2b); text-transform: none; letter-spacing: 0; }
.epqx-toc-item:hover { background: var(--epqx-gold, #c79a52); color: #fff; }
.epqx-toc-sub { display: block; width: 100%; text-align: left; border: 0; background: transparent; cursor: pointer; padding: 7px 12px 7px 28px; border-radius: 4px; font: inherit; font-weight: 400; font-size: 14px; color: #5b6470; text-transform: none; letter-spacing: 0; }
.epqx-toc-sub:hover { background: #f3eee2; color: var(--epqx-ink, #1a1f2b); }
/* Accordion: section sub-links stay hidden until the section is opened (v1.0.80). */
.epqx-toc-item.has-children { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.epqx-toc-caret { flex: 0 0 auto; width: 7px; height: 7px; border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg); transition: transform .15s ease; opacity: 0.5; margin-right: 2px; }
.epqx-toc-group.is-open .epqx-toc-caret { transform: rotate(-135deg); }
.epqx-toc-children { display: none; }
.epqx-toc-group.is-open .epqx-toc-children { display: block; }
.epqx-card-label { font-size: 18px; font-weight: 700; color: var(--epqx-ink); }

/* Review / summary screen */
.epqx-summary { display: flex; flex-direction: column; gap: 26px; width: 100%; text-align: left; }
.epqx-summary-section { display: flex; flex-direction: column; }
.epqx-summary-title { font-size: 14px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--epqx-gold, #c79a52); padding-bottom: 10px; margin-bottom: 4px; border-bottom: 2px solid #ececf0; }
.epqx-summary-row { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; width: 100%; text-align: left; border: 0; background: transparent; cursor: pointer; padding: 12px; border-radius: 4px; font: inherit; border-bottom: 1px solid #f0f0f3; }
.epqx-summary-row:hover { background: #faf6ec; }
.epqx-summary-q { color: #6b7280; font-weight: 600; }
.epqx-summary-a { color: var(--epqx-ink, #1a1f2b); font-weight: 700; text-align: left; }
.epqx-summary-empty { color: #6b7280; text-align: center; padding: 20px; }
.epqx-btn-review { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 26px auto 4px; background: #1ba94c; color: #fff; border: 0; border-radius: 4px; padding: 18px 44px; font-size: 18px; font-weight: 800; cursor: pointer; box-shadow: 0 10px 22px rgba(27,169,76,0.28); }
.epqx-btn-review:hover { background: #169042; transform: translateY(-1px); }
.epqx-btn-review::before { content: "\2713"; font-weight: 900; font-size: 20px; }
.epqx-saverow { display: flex; justify-content: center; margin-top: 12px; }
.epqx-save-resume { background: transparent; border: 0; color: #2563eb; font-size: 14px; font-weight: 600; cursor: pointer; padding: 4px 8px; }
.epqx-save-resume:hover { text-decoration: underline; transform: none; }
.epqx-reset-q { background: transparent; border: 0; color: #2563eb; font-size: 14px; font-weight: 600; cursor: pointer; padding: 4px 8px; }
.epqx-reset-q:hover { text-decoration: underline; transform: none; }
.epqx-saverow-sep { color: #9aa3af; align-self: center; }
/* Plugin version line, shown under the Save/Reset row (options.version,
   localized from GBF_EPQX_VERSION). Hidden entirely when unset. */
.epqx-version-row { text-align: center; margin-top: 10px; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: #9aa3af; }

/* Generosity Discovery + Recommendations */
.epqx-pillgroup { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; width: 100%; }
.epqx-pill { border: 1.5px solid #2b2f36; background: #fff; color: #1a1f2b; border-radius: 4px; padding: 13px 28px; font-size: 17px; font-weight: 600; cursor: pointer; transition: background .15s ease, color .15s ease, border-color .15s ease, transform .12s ease; }
.epqx-pill:hover { border-color: var(--epqx-gold, #c79a52); transform: translateY(-1px); }
.epqx-pill.is-selected { background: var(--epqx-gold, #c79a52); border-color: var(--epqx-gold, #c79a52); color: #fff; }

.epqx-gen-hero { width: 200px; max-width: 60%; height: auto; display: block; margin: 4px auto 6px; }
.epqx-gen-q { font-size: 19px; font-weight: 700; color: var(--epqx-ink, #1a1f2b); text-align: center; }

/* "Your Legacy Starts Here" — designed to read like a polished planned-giving
   document: a centered, max-width column with generous whitespace, steel-navy
   headings under short gold rules, clean white cards, and gold accents used
   sparingly. (Palette from the GBF Planned Giving Guide.) */
.epqx-rec { display: flex; flex-direction: column; gap: 40px; width: 100%; max-width: 1500px; margin: 0 auto; text-align: left; }

/* Outer wrapper spanning all 5 review sections (financial summary, Ways You
   Could Give, Ministries That Align, the charitable-legacy question, and
   Your Next Steps) so every one of them shares the same width, centering,
   and generous spacing — whether it comes from the `recommendations`
   component or a plain schema element placed after it. */
.epqx-rec-outer { display: flex; flex-direction: column; gap: 40px; width: 100%; max-width: 1500px; margin: 0 auto; text-align: left; }
/* A clean divider + extra breathing room between each major section (but
   never above the first one), regardless of nesting depth. */
.epqx-rec-section + .epqx-rec-section { border-top: 1px solid #e6ecf3; padding-top: 36px; }

.epqx-rec-banner { text-align: center; padding: 4px 8px 8px; }
.epqx-rec-band { font-size: 13px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: #353535; }
.epqx-rec-estate { font-size: 52px; font-weight: 800; letter-spacing: -0.01em; line-height: 1.05; color: var(--epqx-gold, #c79a52); margin: 6px 0 12px; }
.epqx-rec-summary { font-size: 20px; font-weight: 700; color: #353535; margin: 0 auto; line-height: 1.4; max-width: 620px; }

.epqx-rec-h { font-size: 26px; font-weight: 800; letter-spacing: -0.01em; color: #1f4e79; text-align: center; margin: 0; }
.epqx-rec-h::before { content: ""; display: block; width: 56px; height: 3px; margin: 0 auto 24px; border-radius: 2px; background: var(--epqx-gold, #c79a52); }

.epqx-rec-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 26px; margin-top: 26px; }

.epqx-rec-card { display: flex; flex-direction: column; gap: 14px; border: 1px solid #e6ecf3; border-radius: 14px; padding: 26px 26px 24px; background: #fff; box-shadow: 0 12px 32px rgba(31,78,121,0.07); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.epqx-rec-card:hover { transform: translateY(-4px); border-color: var(--epqx-gold, #c79a52); box-shadow: 0 20px 46px rgba(31,78,121,0.18); }
.epqx-rec-name { font-size: 21px; font-weight: 800; letter-spacing: -0.01em; line-height: 1.2; color: #353535; }
.epqx-rec-blurb { font-size: 14px; line-height: 1.6; color: #566275; margin: 0; }

/* Gift-vehicle card: icon + title header over a gold rule, then WHAT?/WHY? */
.epqx-rec-gift-head { display: flex; align-items: center; gap: 14px; padding-bottom: 14px; border-bottom: 2px solid var(--epqx-gold, #c79a52); }
.epqx-rec-gift-icon { width: 52px; height: 52px; object-fit: contain; flex: 0 0 52px; }
.epqx-rec-ww { display: grid; grid-template-columns: 42px 1fr; align-items: stretch; overflow: hidden; border-radius: 8px; }
.epqx-rec-ww-tab { display: flex; align-items: center; justify-content: center; writing-mode: vertical-rl; transform: rotate(180deg); font-size: 13px; font-weight: 800; letter-spacing: 0.06em; color: #fff; padding: 12px 0; }
.epqx-rec-ww-body { padding: 13px 16px; font-size: 13.5px; line-height: 1.55; color: #4a5567; }
.epqx-rec-what .epqx-rec-ww-tab { background: var(--epqx-gold, #c79a52); }
.epqx-rec-what .epqx-rec-ww-body { background: #faf3e4; }
.epqx-rec-why2 .epqx-rec-ww-tab { background: #353535; }
.epqx-rec-why2 .epqx-rec-ww-body { background: #f1f1f1; }

/* Ministry card: "Matches your heart…" note with a gold spine + Give link. */
.epqx-rec-match { font-size: 13px; line-height: 1.55; color: #566275; background: #f7f9fc; border-left: 3px solid var(--epqx-gold, #c79a52); padding: 11px 15px; border-radius: 0 8px 8px 0; }

.epqx-rec-link { align-self: flex-start; margin-top: auto; padding-top: 6px; font-size: 14.5px; font-weight: 800; letter-spacing: 0.01em; color: #353535; text-decoration: none; }
.epqx-rec-link:hover { color: var(--epqx-gold, #c79a52); text-decoration: none; }

.epqx-rec-steps { margin: 22px auto 0; padding: 0 0 0 30px; display: flex; flex-direction: column; gap: 18px; max-width: 640px; }
.epqx-rec-steps li { font-size: 16px; line-height: 1.65; color: #2c3e50; padding-left: 6px; }
.epqx-rec-steps li::marker { color: var(--epqx-gold, #c79a52); font-weight: 800; }

/* Your Next Steps — first 3 steps only, one row of 3 icon+text columns.
   Styled as a distinct, elevated call-to-action panel (not just another
   plain section) so it reads as the obvious next move: its own tinted
   background, a gold border, extra padding, and a bigger heading. It stays
   visually connected to the sections above it by keeping the same content
   width, spacing rhythm, and color palette as the rest of the review page. */
.epqx-rec-steps-section {
  background: linear-gradient(180deg, #f9fbfe 0%, #eef4fb 100%);
  border: 1px solid #d7e3f2;
  border-radius: var(--epqx-radius-lg, 26px);
  padding: 44px 40px 40px;
  margin-top: 8px;
  box-shadow: 0 18px 44px rgba(31,78,121,0.1);
}
.epqx-rec-section + .epqx-rec-steps-section { border-top: 1px solid #d7e3f2; padding-top: 44px; }
.epqx-rec-steps-section .epqx-rec-h { font-size: 32px; }
.epqx-rec-steps-section .epqx-rec-h::before { width: 72px; height: 4px; margin-bottom: 16px; }
.epqx-rec-steps-lead { text-align: center; font-size: 16px; line-height: 1.6; color: #45536b; max-width: 560px; margin: 0 auto; font-weight: 600; }
.epqx-rec-steps-row { display: flex; gap: 32px; margin-top: 30px; }
.epqx-rec-step-col { flex: 1; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px; }
.epqx-rec-step-icon {
  width: 64px; height: 64px; padding: 13px; box-sizing: border-box;
  border-radius: 50%; background: #fff; border: 2px solid var(--epqx-gold, #c79a52);
  color: var(--epqx-gold, #c79a52); box-shadow: 0 10px 22px rgba(199,154,82,0.24);
}
.epqx-rec-step-icon svg { width: 100%; height: 100%; display: block; }
.epqx-rec-step-text { font-size: 16px; font-weight: 600; line-height: 1.55; color: #1f2f45; max-width: 240px; }

/* Relocated charitable-legacy question (moved here from its own screen). */
.epqx-charity-section { width: 100%; }
.epqx-charity-section .epqx-rec-h { margin-bottom: 22px; }
/* This one question is built as a `heading` element (an <h2>), unlike every
   other .epqx-rec-h on this screen (plain <div>s) — so it also picks up the
   theme's own h2 styling (large, black), which can outrank a single-class
   selector like .epqx-rec-h. Force it to match the section headers around
   it ("Ministries That Align with Your Heart", etc.) exactly. */
.epqx-root .epqx-charity-section .epqx-heading.epqx-rec-h {
  font-size: 26px !important;
  font-weight: 800 !important;
  letter-spacing: -0.01em !important;
  color: #1f4e79 !important;
  margin: 0 !important;
}

@media (max-width: 640px) {
  .epqx-rec, .epqx-rec-outer { gap: 32px; }
  .epqx-rec-grid { grid-template-columns: 1fr; }
  .epqx-rec-estate { font-size: 42px; }
  .epqx-rec-section + .epqx-rec-section { padding-top: 28px; }
  .epqx-rec-steps-row { flex-direction: column; gap: 24px; }
  .epqx-rec-step-text { max-width: 100%; }
  .epqx-rec-steps-section { padding: 32px 22px 28px; }
  .epqx-rec-steps-section .epqx-rec-h { font-size: 26px; }
  .epqx-rec-steps-lead { font-size: 14.5px; }
}

/* Your Details — vertical card chain */
.epqx-chain { position: relative; width: 100%; overflow: hidden; transition: height var(--epqx-dur-chain, 550ms) var(--epqx-ease-chain, cubic-bezier(.4,0,.2,1)); }
.epqx-chain-track { display: flex; flex-direction: column; gap: 0; transition: transform var(--epqx-dur-chain, 550ms) var(--epqx-ease-chain, cubic-bezier(.4,0,.2,1)); }
.epqx-chain-card { width: 100%; box-sizing: border-box; padding: 8px 2px; }
.epqx-chain-fade { position: absolute; left: 0; right: 0; height: 56px; pointer-events: none; z-index: 3; transition: opacity .3s ease; }
.epqx-chain-fade-top { top: 0; background: linear-gradient(to bottom, var(--epqx-card,#fff) 14%, rgba(255,255,255,0)); }
.epqx-chain-fade-bottom { bottom: 0; background: linear-gradient(to top, var(--epqx-card,#fff) 14%, rgba(255,255,255,0)); }
.epqx-couple-img { width: auto; max-width: 240px; max-height: 360px; display: block; margin: 0 auto; border: 1px solid transparent; border-radius: 12px; transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.epqx-couple-img:hover { transform: translateY(-4px); border-color: var(--epqx-gold, #c79a52); box-shadow: 0 20px 46px rgba(31,78,121,0.18); }
.epqx-assets-img { width: auto; max-width: 320px; max-height: 380px; display: block; margin: 0 auto; }

/* Repeat-item remove control (e.g. Rest & Residue beneficiaries) */
.epqx-repeat-remove { flex: 0 0 auto; align-self: flex-end; margin-bottom: 9px; width: 30px; height: 30px; border: 0; border-radius: 4px; background: #e23b3b; color: #fff; font-size: 20px; line-height: 1; font-weight: 700; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; transition: background .15s ease, transform .12s ease; }
.epqx-repeat-remove:hover { background: #c62f2f; transform: scale(1.06); }

/* =====================================================================
   ISOLATION LAYER — "EPQX is styled by EPQX only."
   ---------------------------------------------------------------------
   A host theme styles bare tags (h1-h6, p, a, button, input, img, li…).
   A bare-tag rule BEATS an inherited value, so the theme's heading font,
   link underline, image border, etc. leak in even though EPQX sets them
   on the container. The rest of this file deliberately avoids !important
   (layout is set inline by the engine), but defeating a hostile host
   theme is the one case that requires it. Everything below is scoped to
   .epqx-root and limited to typographic / decorative properties, so the
   engine's inline layout is never touched. FontAwesome <i> glyphs are
   re-asserted to their own font so icons keep rendering.
   ===================================================================== */

/* 1) Force the EPQX font on every text-bearing tag (icons excluded — §2). */
.epqx-root,
.epqx-root h1, .epqx-root h2, .epqx-root h3, .epqx-root h4, .epqx-root h5, .epqx-root h6,
.epqx-root p, .epqx-root a, .epqx-root span, .epqx-root div, .epqx-root li,
.epqx-root label, .epqx-root strong, .epqx-root b, .epqx-root em, .epqx-root small,
.epqx-root button, .epqx-root input, .epqx-root select, .epqx-root textarea,
.epqx-root optgroup, .epqx-root option {
  font-family: var(--epqx-font) !important;
}
/* High-specificity reinforcement on EPQX's own classes (beats theme
   selectors like `.theme-wrap h2 { font-family: <serif> }`). */
.epqx-root .epqx-heading, .epqx-root .epqx-text, .epqx-root .epqx-kicker,
.epqx-root .epqx-label, .epqx-root .epqx-card-label, .epqx-root .epqx-inline-input,
.epqx-root .epqx-input, .epqx-root .epqx-textarea, .epqx-root .epqx-btn,
.epqx-root .epqx-btn-review, .epqx-root .epqx-save-resume, .epqx-root .epqx-reset-q, .epqx-root .epqx-skip-now {
  font-family: var(--epqx-font) !important;
}

/* 2) FontAwesome glyphs keep their own font + upright posture, no matter
   what the theme does to <i>. (More specific than §1, so it wins.) */
.epqx-root i,
.epqx-root .fa, .epqx-root .fas, .epqx-root .far, .epqx-root .fal, .epqx-root .fab,
.epqx-root .fa-solid, .epqx-root .fa-regular, .epqx-root .fa-light, .epqx-root .fa-brands,
.epqx-root [class^="fa-"], .epqx-root [class*=" fa-"] {
  font-family: "Font Awesome 6 Free", "Font Awesome 6 Brands", "FontAwesome" !important;
  font-style: normal !important;
}

/* 3) Stop theme italics / forced casing / underlines on display + control
   text. Intentional uppercase lives on .epqx-kicker and the gold/deeds/
   modal label variants, which are intentionally omitted so they keep it. */
.epqx-root .epqx-heading, .epqx-root .epqx-text, .epqx-root .epqx-card-label,
.epqx-root .epqx-input, .epqx-root .epqx-textarea, .epqx-root .epqx-inline-input,
.epqx-root .epqx-btn, .epqx-root .epqx-btn-review, .epqx-root .epqx-save-resume, .epqx-root .epqx-reset-q, .epqx-root .epqx-skip-now {
  font-style: normal !important;
  text-transform: none !important;
  text-decoration: none !important;
}

/* 3b) Field labels are ALWAYS left-justified (v1.0.109).
   A host theme styling bare <label> / <span> text (or a centred wrapper it
   puts around the shortcode) can leak alignment in, which centres labels on
   the live site even though the questionnaire's own rules never do. This is
   the same class of problem — and the same remedy — as the font and casing
   forcing above: it belongs in the isolation layer, with !important, because
   nothing else can outrank a determined theme selector. Labels only; every
   heading keeps the alignment its screen gives it.

   v1.0.114 adds the asset table's column headers to the same guard. They used
   to be centred by design; the Asset Inventory list is now left-justified
   throughout (see the .epqx-asset-* rules), and the headers have to be pinned
   the same way as the labels or a centring theme puts them back. */
.epqx-root .epqx-label,
.epqx-root .epqx-field > .epqx-label,
.epqx-root .epqx-radiogroup-label,
.epqx-root .epqx-asset-head .epqx-asset-item,
.epqx-root .epqx-asset-head .epqx-asset-cell,
.epqx-root .epqx-asset-head .epqx-asset-owner { text-align: left !important; }
.epqx-root .epqx-heading { letter-spacing: -0.03em !important; line-height: var(--epqx-lh-heading, 1.15) !important; }

/* 4) Links/buttons: no inherited theme underline. */
.epqx-root a,
.epqx-root button { text-decoration: none; }

/* 5) Images: strip theme borders / shadows / filters. Sizing is left to the
   base `.epqx-root img` rule + per-image classes/inline styles (so we do NOT
   touch width/height here). */
.epqx-root img {
  border: 0 !important;
  box-shadow: none !important;
  filter: none !important;
  vertical-align: middle;
}

/* 6) Protect the numbered recommendation steps from theme list resets
   (e.g. a theme `li { list-style: none }`). */
.epqx-root ol.epqx-rec-steps { list-style: decimal !important; padding-left: 22px; }
.epqx-root .epqx-rec-steps li { display: list-item !important; list-style: decimal !important; }

/* Inline field validation (number/phone/email/percent rules) */
.epqx-field-error { color: var(--epqx-error-text, #c0392b); font-size: var(--epqx-fs-error, 13px); font-weight: 600; line-height: var(--epqx-lh-tight, 1.3); margin: 2px 0 6px; }
.epqx-input.epqx-input-invalid, .epqx-money-input.epqx-input-invalid { border-color: #e02424; box-shadow: 0 0 0 3px rgba(224,36,36,0.12); }

/* Date field — Month (name) / Day / Year dropdowns + a calendar picker (📅) */
.epqx-date { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; }
.epqx-date-part { flex: 1 1 0; min-width: 0; height: 48px; font-family: var(--epqx-font); font: inherit; padding: 0 12px; border: 1px solid var(--epqx-line, #d0d5dd); border-radius: var(--epqx-radius, 14px); background: #fff; color: var(--epqx-ink, #1a1f2b); cursor: pointer; }
.epqx-date-month { flex: 1.5 1 0; }
.epqx-date-day, .epqx-date-year { flex: 1 1 0; }
.epqx-date-part:focus { outline: none; border-color: var(--epqx-gold, #c79a52); box-shadow: 0 0 0 3px rgba(216,174,102,0.18); }
.epqx-date-calwrap { flex: 0 0 48px; position: relative; display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; border: 1px solid var(--epqx-line, #d0d5dd); border-radius: var(--epqx-radius, 14px); background: #fff; cursor: pointer; }
.epqx-date-calwrap:hover { border-color: var(--epqx-gold, #c79a52); }
.epqx-date-calicon { font-size: 20px; line-height: 1; pointer-events: none; }
.epqx-date-cal { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; border: 0; padding: 0; margin: 0; }

/* State selects and date pickers must match the themed fields around them. In
   the tan "gold" forms and the tan modal, plain .epqx-select / date parts kept
   a white background; bring them in line with the tan inputs. */
.epqx-gold-form .epqx-select,
.epqx-modal-panel .epqx-select,
.epqx-gold-form .epqx-date-part,
.epqx-modal-panel .epqx-date-part,
.epqx-gold-form .epqx-date-calwrap,
.epqx-modal-panel .epqx-date-calwrap { background: #ead9b6; border: 0; color: #2c2410; }

/* Completion delivery modal — "email my estate plan document to…" */
.epqx-delivery-overlay { position: fixed; inset: 0; z-index: 90; display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px; overflow-y: auto; background: rgba(20,24,31,0.55); }
.epqx-delivery { position: relative; width: 100%; max-width: 760px; background: #fff; border-radius: 22px; padding: 44px 48px 40px; box-shadow: 0 30px 80px rgba(0,0,0,0.35); }
.epqx-delivery-close { position: absolute; top: 22px; right: 24px; width: 34px; height: 34px; border: 0; background: transparent; font-size: 26px; line-height: 1; color: var(--epqx-ink, #1a1f2b); cursor: pointer; border-radius: 4px; }
.epqx-delivery-close:hover { background: #f0f1f4; }
.epqx-delivery-title { font-size: 34px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.15; color: var(--epqx-ink, #1a1f2b); margin: 0 40px 10px 0; }
.epqx-delivery-intro { font-size: 16px; color: #6b7280; margin: 0 0 22px; }
.epqx-delivery-error { background: #fdeceA; color: #c0392b; font-size: 14px; font-weight: 600; padding: 10px 14px; border-radius: 10px; margin-bottom: 16px; }
.epqx-delivery-group { margin-bottom: 18px; }
.epqx-delivery-label { font-size: 19px; font-weight: 800; color: var(--epqx-ink, #1a1f2b); margin-bottom: 8px; }
.epqx-delivery-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.epqx-delivery-footer { display: flex; justify-content: flex-end; margin-top: 26px; }
.epqx-delivery-submit { background: var(--epqx-ink, #14181f); color: #fff; border: 0; border-radius: 4px; padding: 14px 34px; font-size: 16px; font-weight: 700; cursor: pointer; }
.epqx-delivery-submit:hover { opacity: 0.92; }
.epqx-delivery-submit:disabled { opacity: 0.6; cursor: default; }

/* ---- Completion / thank-you screen ---- */
.epqx-thanks { text-align: center; padding: 6px 4px 2px; }
.epqx-thanks-title { font-size: 30px; font-weight: 800; letter-spacing: -0.01em; line-height: 1.15; color: #b23b2e; margin: 4px 24px 14px; }
.epqx-thanks-lead { font-size: 17px; line-height: 1.55; color: #37414f; max-width: 560px; margin: 0 auto 22px; }
.epqx-thanks-codebox { display: inline-block; min-width: 260px; background: #faf7f0; border: 1px solid #e7dcc4; border-radius: 16px; padding: 16px 28px; margin: 4px auto 22px; }
.epqx-thanks-codelabel { font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase; font-weight: 800; color: #8a7a52; }
.epqx-thanks-code { font-size: 44px; font-weight: 800; letter-spacing: 10px; color: var(--epqx-ink, #1a1f2b); margin-top: 4px; padding-left: 10px; }
.epqx-thanks-note { font-size: 15px; line-height: 1.55; color: #6b7280; max-width: 560px; margin: 0 auto 24px; }
.epqx-thanks-actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.epqx-thanks-confirm-slot { }
.epqx-thanks-confirm { margin: 22px auto 0; max-width: 420px; background: #fff; border: 1px solid #e5e7eb; border-radius: 14px; padding: 18px 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.08); }
.epqx-thanks-confirm-q { font-size: 17px; font-weight: 700; color: var(--epqx-ink, #1a1f2b); margin-bottom: 14px; }
.epqx-thanks-confirm-actions { display: flex; gap: 12px; justify-content: center; }
@media (max-width: 640px) {
  .epqx-thanks-title { font-size: 24px; }
  .epqx-thanks-code { font-size: 34px; letter-spacing: 6px; }
}
@media (max-width: 640px) {
  .epqx-delivery { padding: 32px 22px 28px; border-radius: 18px; }
  .epqx-delivery-title { font-size: 26px; margin-right: 28px; }
  .epqx-delivery-row { grid-template-columns: 1fr; gap: 10px; }
}

/* ============================================================
   v1.0.12 additions
   ============================================================ */

/* Hover lift on every text field */
.epqx-input:hover,
.epqx-inline-input:hover,
.epqx-money-input:hover,
.epqx-date-part:hover,
.epqx-root textarea:hover {
  border-color: #d8ae66 !important;
  transform: translateY(-1px) !important;
  box-shadow: 0 10px 24px rgba(17,24,39,0.08) !important;
}

/* Hover lift on form-choice cards & their images (title / marital / spouse /
   Yes-No / critical-decision / distribution choices — like the old EPQ). */
.epqx-card-opt:hover {
  border-color: #d8ae66 !important;
  transform: translateY(-1px) !important;
  box-shadow: 0 10px 24px rgba(17,24,39,0.08) !important;
}

/* Asset Inventory totals: value green, debt red, net blue / red by sign */
.epqx-asset-total-value { color: #1e8e3e !important; }
.epqx-asset-total-debt { color: #d93025 !important; }
.epqx-asset-total-net.is-positive { color: #1f4e79 !important; }
.epqx-asset-total-net.is-negative { color: #d93025 !important; }

/* TOC: highlight the section the user is currently in */
.epqx-toc-item.is-current,
.epqx-toc-sub.is-current { color: #1f4e79; background: #eef4fb; font-weight: 800; }

/* Completion: gold "Thank you" card over the email form */
.epqx-delivery-thanks {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(560px, 86%); background: var(--epqx-gold, #d8ae66); color: #fff;
  border-radius: 18px; padding: 40px 44px; text-align: center;
  box-shadow: 0 24px 60px rgba(0,0,0,0.28); z-index: 5;
}
.epqx-delivery-thanks-title { font-size: 40px; font-weight: 800; letter-spacing: -0.02em; color: #1a1f2b; margin-bottom: 14px; }
.epqx-delivery-thanks-body { font-size: 19px; font-weight: 700; line-height: 1.45; color: #ffffff; }
.epqx-delivery-thanks-note { margin-top: 14px; font-size: 16px; font-weight: 600; }
.epqx-delivery-thanks-actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 14px; margin-top: 24px; }
.epqx-delivery-thanks-actions .epqx-btn-secondary { background: #fff; border: 1px solid rgba(255,255,255,0.65); }

/* v1.0.15 — tooltip now renders as a body-level floating node (epxqMakeTip)
   so it can't be clipped by overflow/transform containers like the card chain.
   The in-DOM .epqx-tip-bubble is kept only as a hidden accessible/source copy. */
.epqx-root .epqx-tip-bubble { display: none !important; }
.epqx-tip-floating { font-family: inherit; }

/* v1.0.16 — Generosity Discovery question labels: responsive, ~20px on desktop */
.epqx-screen-generosity-discovery .epqx-label,
.epqx-screen-generosity-discovery .epqx-radiogroup-label {
  font-size: clamp(15px, 2.2vw, 20px) !important;
  line-height: 1.35;
}

/* v1.0.99 — Rest & Residue distribution-choice screen: the beneficiary
   First/MI/Last Name labels are enlarged to match the bigger "Give to
   Children Equally" text and smaller images on this screen (per Freeman's
   corrected mockups), without changing the label size anywhere else. */
.epqx-screen-section3-rest-residue-3 .epqx-label {
  font-size: 17px;
}

/* v1.0.17 — Generosity Discovery mockup: left-justify ministry question + pills;
   question text responsive ~20px on desktop (used in the 2-column rows too). */
.epqx-screen-generosity-discovery .epqx-gen-q {
  text-align: left !important;
  font-size: clamp(15px, 2.2vw, 20px) !important;
  line-height: 1.35;
}
.epqx-screen-generosity-discovery .epqx-pillgroup { justify-content: flex-start; }

/* =========================================================================
   KOIE Snapshot additions (v1.0.20) — persona line, asset opportunities,
   gift benefits, and the educational disclaimer. All scoped under .epqx-root.
   ========================================================================= */
.epqx-rec-persona {
  margin: 14px auto 0; max-width: 680px; text-align: center;
  font-size: 16px; line-height: 1.6; font-style: italic; color: #353535;
}
.epqx-rec-assets {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px; margin-top: 20px;
}
.epqx-rec-asset {
  display: flex; flex-direction: column; gap: 3px;
  border: 1px solid #e6ecf3; border-radius: 12px; padding: 14px 16px; background: #fbfcfe;
}
.epqx-rec-asset-type { font-size: 14.5px; font-weight: 800; color: #353535; }
.epqx-rec-asset-note { font-size: 13px; line-height: 1.5; color: #566275; }
.epqx-rec-benefits {
  font-size: 12.5px; line-height: 1.55; color: #8a94a3; margin: 2px 0 0;
  font-style: italic; text-align: left;
}
.epqx-rec-benefits strong { font-style: italic; color: #6b7280; text-decoration: underline; }
.epqx-rec-ministry .epqx-rec-benefits { text-align: left; }
.epqx-rec-disclaimer {
  margin: 34px auto 0; max-width: 760px; text-align: center;
  font-size: 12px; line-height: 1.6; color: #8a93a3;
  border-top: 1px solid #e6ecf3; padding-top: 18px;
}

/* =========================================================================
   Generosity Discovery — heart-signal controls (rankPills, spectrum,
   heartSummary reflect-back). Scoped to the questionnaire palette.
   ========================================================================= */
.epqx-rankpills { display: flex; flex-direction: column; gap: 10px; }
.epqx-rankpills-row { display: flex; flex-wrap: wrap; gap: 12px; }
.epqx-rankpill { display: inline-flex; align-items: center; gap: 8px; border: 2px solid var(--epqx-line, #e4e7ec); background: #fff; color: var(--epqx-ink, #1a1f2b); border-radius: 4px; padding: 10px 18px; font: inherit; font-weight: 700; cursor: pointer; transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease, background .15s ease; }
.epqx-rankpill:hover { transform: translateY(-1px); border-color: var(--epqx-gold, #c79a52); box-shadow: 0 10px 24px rgba(17,24,39,.08); }
.epqx-rankpill.is-ranked { background: #1f4e79; border-color: #1f4e79; color: #fff; }
.epqx-rankpill-badge { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: var(--epqx-gold, #c79a52); color: #14181f; font-size: 13px; font-weight: 800; }
.epqx-rankpills-hint, .epqx-rankpills-empty { font-size: 13px; color: var(--epqx-muted, #6b7280); }

.epqx-spectrum { display: flex; flex-direction: column; gap: 10px; }
.epqx-spectrum-q { font-size: 16px; font-weight: 700; color: var(--epqx-ink, #1a1f2b); }
.epqx-spectrum-row { display: grid; grid-template-columns: minmax(90px, 1fr) auto minmax(90px, 1fr); align-items: center; gap: 14px; }
.epqx-spectrum-pole { font-size: 14px; font-weight: 700; color: #4a5567; }
.epqx-spectrum-left { text-align: right; }
.epqx-spectrum-right { text-align: left; }
.epqx-spectrum-track { display: inline-flex; align-items: center; gap: 12px; }
.epqx-spectrum-dot { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--epqx-line, #d0d5dd); background: #fff; cursor: pointer; padding: 0; transition: transform .12s ease, border-color .12s ease, background .12s ease; }
.epqx-spectrum-dot.is-mid { width: 14px; height: 14px; }
.epqx-spectrum-dot:hover { border-color: var(--epqx-gold, #c79a52); transform: scale(1.1); }
.epqx-spectrum-dot.is-selected { background: var(--epqx-gold, #c79a52); border-color: var(--epqx-gold, #c79a52); }
@media (max-width: 640px) {
  .epqx-spectrum-row { grid-template-columns: 1fr; justify-items: center; gap: 8px; }
  .epqx-spectrum-left, .epqx-spectrum-right { text-align: center; }
}

.epqx-heartsummary { max-width: 640px; margin: 0; text-align: left; }
.epqx-heartsummary-title { font-size: 28px; font-weight: 800; letter-spacing: -0.01em; color: #1f4e79; margin: 0; }
.epqx-heartsummary-title::after { content: ""; display: block; width: 56px; height: 3px; margin: 16px 0 20px; border-radius: 2px; background: var(--epqx-gold, #c79a52); }
.epqx-heartsummary-line { font-size: 20px; line-height: 1.5; font-weight: 700; color: #1f4e79; margin: 0 0 12px; }
.epqx-heartsummary-foot { font-size: 20px; line-height: 1.6; color: #566275; margin: 18px 0 0; font-weight: 400; }

/* ---- Reflect-back popup ("Here's what we heard") ---- */
.epqx-popup-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(20,24,31,0.45); border-radius: 28px; z-index: 95; box-sizing: border-box; }
.epqx-popup-box { background: #fff; max-width: 620px; width: 100%; border-radius: 18px; padding: 32px 34px 26px; box-shadow: 0 30px 70px rgba(0,0,0,0.35); max-height: 86%; overflow: auto; box-sizing: border-box; }
.epqx-popup-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 22px; }
@media (max-width: 640px) { .epqx-popup-box { padding: 24px 22px 20px; } .epqx-popup-actions { flex-direction: column-reverse; } .epqx-popup-actions .epqx-btn { width: 100%; } }

/* ---- Screen slide transition (Generosity Discovery / Your Heart for Ministry) ---- */
@keyframes epqxSlideUpIn { from { opacity: 0; transform: translateY(46px); } to { opacity: 1; transform: none; } }
@keyframes epqxSlideUpOut { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-46px); } }
.epqx-content.epqx-anim-in { animation: epqxSlideUpIn var(--epqx-dur-section, 440ms) var(--epqx-ease-slide, cubic-bezier(.22,.61,.36,1)) both; }
.epqx-content.epqx-anim-out { animation: epqxSlideUpOut var(--epqx-dur-screen, 240ms) ease-in both; }
@media (prefers-reduced-motion: reduce) { .epqx-content.epqx-anim-in, .epqx-content.epqx-anim-out { animation: none; } }

/* =====================================================================
   Phones (<=600px): de-cramp. Full-bleed the app to the screen edges,
   collapse the nested frame paddings, cap headings, shrink illustrations,
   and let the date row wrap so nothing is clipped left/right.
   ===================================================================== */
@media (max-width: 600px) {
  .epqx-app-wrap {
    padding: 0 !important;
    margin-left: calc(50% - 50vw) !important;
    margin-right: calc(50% - 50vw) !important;
    width: 100vw !important;
    max-width: 100vw !important;
  }
  .epqx-app { padding: 0 !important; margin: 0 !important; }
  .epqx-shell {
    max-width: 100% !important;
    width: 100% !important;
    padding: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
  }
  .epqx-card {
    max-width: 100% !important;
    width: 100% !important;
    padding: 16px !important;
    border-radius: 0 !important;
  }
  /* Header / section label / nav keep a little breathing room from the edge. */
  .epqx-header, .epqx-kicker, .epqx-nav { padding-left: 12px !important; padding-right: 12px !important; }
  /* Headings no larger than ~36px on phones. */
  .epqx-heading { font-size: clamp(24px, 7vw, 36px) !important; }
  /* Smaller illustrations so form fields aren't pushed off-screen.
     The .epqx-couple-img rule that used to sit here was DEAD CODE and was
     removed in v1.0.120. It read max-width:150px !important, but the
     v1.0.113 shared-illustration block later in this file carries
     `.epqx-root .epqx-couple-img.epqx-illus` — specificity (0,3,0) against
     this rule's (0,1,0), also !important, and later — so it always won and
     the couple illustration rendered at 260x338 on a 390px phone. The size
     is now decided in ONE place, in that block, rather than by two rules
     arguing. See "PHONES: side illustrations" below. */
  .epqx-card-img { width: 118px !important; height: 118px !important; }
  /* v1.0.120: the two Your Details side illustrations are excluded here.
     This rule is !important (host-theme isolation), so it silently beat the
     smaller phone max-height in the shared-illustration block and the couple
     kept rendering 210px tall no matter what that block asked for. Excluding
     the two elements this phase is about leaves exactly one rule deciding
     their size, and leaves every other image's 210px cap untouched. */
  .epqx-img:not(.epqx-couple-img):not(.epqx-assets-img) {
    max-height: 210px !important; margin-left: auto !important; margin-right: auto !important;
  }
  .epqx-couple-img, .epqx-assets-img { margin-left: auto !important; margin-right: auto !important; }
  /* Date row (Month / Day / Year / calendar) wraps + shrinks to fit. */
  .epqx-date { flex-wrap: wrap !important; gap: 8px !important; }
  .epqx-date-part { flex: 1 1 30% !important; }
  .epqx-date-calwrap { flex: 0 0 44px !important; }
}

/* ---- Your Heart for Ministry: left-justified, 2-column spectrums ---- */
.epqx-screen-generosity-heart .epqx-gen-q { text-align: left; }
.epqx-spectrum-side { display: grid; grid-template-columns: minmax(170px, 0.8fr) 1.7fr; align-items: center; gap: 18px; }
.epqx-spectrum-side .epqx-spectrum-q-side { font-size: 17px; font-weight: 700; color: var(--epqx-ink, #1a1f2b); margin: 0; }
@media (max-width: 640px) { .epqx-spectrum-side { grid-template-columns: 1fr; gap: 6px; } }

/* ---- Skip for now (footer link) ---- */
.epqx-skip-now { background: transparent; border: 0; color: #2563eb; font-size: 14px; font-weight: 600; cursor: pointer; padding: 4px 8px; }
.epqx-skip-now:hover { text-decoration: underline; transform: none; }

/* "Copy this alternate's details" checkbox: 25% larger + stronger label. */
.epqx-app .epqx-check input[type="checkbox"][name$="_copy_all"] { transform: scale(1.25); transform-origin: left center; margin-right: 12px; accent-color: #c79a52; }
.epqx-app .epqx-check input[type="checkbox"][name$="_copy_all"] + span { font-weight: 700; color: #1a1f2b; }

/* Welcome cards: fade + slide in from the left, staggered ~1s apart. */
@keyframes epqxCardIn { from { opacity: 0; transform: translateX(-28px); } to { opacity: 1; transform: translateX(0); } }
.epqx-welcome-card { opacity: 0; animation: epqxCardIn 0.6s ease forwards; }
.epqx-welcome-card:nth-child(1) { animation-delay: 0s; }
.epqx-welcome-card:nth-child(2) { animation-delay: 0.5s; }
.epqx-welcome-card:nth-child(3) { animation-delay: 1s; }
.epqx-welcome-card:nth-child(4) { animation-delay: 1.5s; }
@media (prefers-reduced-motion: reduce) {
  .epqx-welcome-card { opacity: 1; animation: none; }
}

/* Animated hand-drawn red circle around a dynamic number (minor children). */
.epqx-circle-num { position: relative; display: inline-block; font-weight: 700; color: #1a1f2b; padding: 0 6px; white-space: nowrap; }
.epqx-circle-svg { position: absolute; left: -6px; top: -8px; width: calc(100% + 12px); height: calc(100% + 16px); overflow: visible; pointer-events: none; }
.epqx-circle-svg ellipse { fill: none; stroke: #e02424; stroke-width: 2.5; stroke-linecap: round; stroke-dasharray: 180; stroke-dashoffset: 180; transform: rotate(-8deg); transform-origin: center; animation: epqxCircleDraw 0.9s ease forwards 0.35s; }
@keyframes epqxCircleDraw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .epqx-circle-svg ellipse { animation: none; stroke-dashoffset: 0; }
}

/* Per-screen override — "Upon your passing, who will inherit the entirety of
   your estate?" (married + single variants). No box-shadow on hover and a
   larger lift, for these screens only. */
.epqx-screen-section3-entire-estate .epqx-card-opt:hover,
.epqx-screen-section3-entire-estate-single .epqx-card-opt:hover {
  transform: translateY(-15px) !important;
  box-shadow: none !important;
}

/* Light-gray form modal variant (e.g. the "Organization Details" popup).
   Overrides the gold alternates-modal look for a neutral data-entry dialog. */
.epqx-modal.epqx-modal-form { background: #f3f4f6; color: #1f2430; }
.epqx-modal-form .epqx-modal-close { color: #4b5563; }
.epqx-modal-form .epqx-modal-title { color: #1f2430; }
.epqx-modal-form .epqx-field { margin-bottom: 14px; }
.epqx-modal-form .epqx-label { color: #4b5563; text-transform: uppercase; letter-spacing: 0.05em; font-size: 12px; font-weight: 700; }
.epqx-modal-form .epqx-input,
.epqx-modal-form .epqx-select { background: #ffffff; border: 1px solid #d1d5db; color: #1f2430; }
.epqx-modal-form .epqx-input:focus,
.epqx-modal-form .epqx-select:focus { border-color: #d8ae66; outline: none; }
.epqx-modal-form .epqx-modal-footer { justify-content: flex-end; gap: 12px; margin-top: 18px; }
.epqx-modal-secondary { border: 1px solid #d1d5db; cursor: pointer; background: #fff; color: #374151; font-weight: 700; padding: 14px 24px; border-radius: 4px; }
.epqx-modal-secondary:hover { background: #e9ebef; }

/* ======================================================================
   Legacy / Generosity screens — "What Will Your Legacy Be?" mockup.
   Background image fills the card; hero + body sit on it as translucent
   cards. (v1.0.74)
   ====================================================================== */
/* Let the background image reach the card edges on these two screens. */
.epqx-card:has(.epqx-screen-generosity-discovery),
.epqx-card:has(.epqx-screen-generosity-heart) {
  padding: 0 !important;
  overflow: hidden;
  border: 0;
}
.epqx-screen-generosity-discovery,
.epqx-screen-generosity-heart {
  /* The JPG first, then the same rule again with image-set() so a browser
     that understands it takes the WebP (44KB -> 26KB). A browser that does
     not simply ignores the second declaration and keeps the JPG, so the
     background can never go missing. Layout, position and sizing are
     identical in both. (v1.0.117) */
  background: #c8ccd0 url("../images/Legacy-Screen-Background.jpg") top center / cover no-repeat;
  background: #c8ccd0 image-set(url("../images/Legacy-Screen-Background.webp") type("image/webp"),
                                url("../images/Legacy-Screen-Background.jpg") type("image/jpeg"))
                      top center / cover no-repeat;
  border-radius: var(--epqx-radius-lg);
  padding: 44px;
  display: flex;
  flex-direction: column;
  gap: 26px;
  box-sizing: border-box;
}
/* Hero: translucent light card, left-aligned; the image shows to its right. */
.epqx-legacy-hero {
  background: rgba(248,248,249,0.74);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  border-radius: 20px;
  padding: 34px 40px;
  max-width: 60%;
  align-self: flex-start;
}
.epqx-legacy-title {
  font-family: "Playfair Display", Georgia, "Times New Roman", serif !important;
  font-weight: 800 !important;
  /* 58px, not 66: the hero column is 60% of the card, so at 1040 the title has
     465px to work with. "What Will Your" measured 521px at 66px, which forced
     the heading onto three lines and stranded "Be?" alone on the last one.
     Binding cannot fix that — the first two words already fill the line. At
     58px the same three words measure 458px, so the heading lays out as
     "What Will Your" / "Legacy Be?" — two lines, two words minimum. v1.0.114 */
  font-size: clamp(38px, 5vw, 58px) !important;
  line-height: 1.03 !important;
  color: #1c2230 !important;
  text-align: left !important;
  margin: 0 0 18px !important;
}
.epqx-legacy-hero .epqx-text { color: #3b4150; font-size: 18px; line-height: 1.5; margin: 0 0 14px; max-width: 48ch; text-align: left; }
.epqx-legacy-hero .epqx-text:last-child { margin-bottom: 0; }
/* Body: translucent gray card holding the questions. */
.epqx-legacy-body {
  background: rgba(235,236,238,0.85);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  border-radius: 20px;
  padding: 34px 40px;
}
.epqx-legacy-body .epqx-gen-q,
.epqx-legacy-body .epqx-label { text-align: left !important; font-size: clamp(16px, 2vw, 20px) !important; font-weight: 600 !important; color: #1c2230 !important; text-transform: none !important; letter-spacing: 0 !important; }
.epqx-legacy-body .epqx-input,
.epqx-legacy-body .epqx-textarea,
.epqx-legacy-body .epqx-select { background: #fff; border: 1px solid #e2e4e8; border-radius: 4px; }
.epqx-legacy-body .epqx-pillgroup { justify-content: flex-start; }
@media (max-width: 720px) {
  .epqx-screen-generosity-discovery,
  .epqx-screen-generosity-heart { padding: 18px; border-radius: 0; }
  .epqx-legacy-hero { max-width: 100%; padding: 22px; }
  .epqx-legacy-body { padding: 22px; }
}

/* Inline, non-interactive copy of the tooltip "?" badge, for referencing the
   symbol inside body text (e.g. the Welcome screen). Smaller than .epqx-tip. */
.epqx-tip-inline { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 50%; background: var(--epqx-gold, #c79a52); border: 1px solid #14181f; color: #14181f; font-size: 9px; font-weight: 800; line-height: 1; vertical-align: middle; box-sizing: border-box; }
/* Contact links inside Welcome-screen body text. */
.epqx-screen-welcome .epqx-text a { color: #0071bc; text-decoration: underline; font-weight: 600; }
.epqx-screen-welcome .epqx-text a:hover { color: #005a94; }

/* =====================================================================
   PHASE 1 — EXPERIENCE FOUNDATION (v1.0.103)
   ---------------------------------------------------------------------
   Reusable interaction-state styling, guarded hover, a visible keyboard
   focus system, and a comprehensive reduced-motion mode. Everything in
   this section is either (a) additive — a class or state nothing yet
   applies, available for later phases — or (b) a focus indicator where
   there previously was none. No screen is restyled here, no spacing is
   changed, and no existing rule above is overridden except where a rule
   explicitly says so.

   Every var() below carries its literal fallback, because a few EPQX
   nodes (the table-of-contents menu, the floating tooltip) are appended
   to <body> and therefore sit outside .epqx-root where the tokens live.
   ===================================================================== */

/* ---------------------------------------------------------------------
   P1.1  KEYBOARD FOCUS — visible, consistent, and never colour-only.
   Focus is drawn in navy so it is never mistaken for the gold
   "selected" state, and it is always a RING (a shape change), not just
   a colour change.
   --------------------------------------------------------------------- */

/* Controls that previously fell back to the browser's default outline. */
.epqx-root .epqx-btn:focus-visible,
.epqx-root .epqx-btn-review:focus-visible,
.epqx-root .epqx-action-btn:focus-visible,
.epqx-root .epqx-pill:focus-visible,
.epqx-root .epqx-rankpill:focus-visible,
.epqx-root .epqx-tab:focus-visible,
.epqx-root .epqx-modal-tab:focus-visible,
.epqx-root .epqx-modal-close:focus-visible,
.epqx-root .epqx-modal-continue:focus-visible,
.epqx-root .epqx-modal-secondary:focus-visible,
.epqx-root .epqx-delivery-submit:focus-visible,
.epqx-root .epqx-delivery-close:focus-visible,
.epqx-root .epqx-repeat-remove:focus-visible,
.epqx-root .epqx-toc-btn:focus-visible,
.epqx-root .epqx-save-resume:focus-visible,
.epqx-root .epqx-reset-q:focus-visible,
.epqx-root .epqx-skip-now:focus-visible,
.epqx-root .epqx-btn-link:focus-visible,
.epqx-root .epqx-warn-confirm:focus-visible,
.epqx-root .epqx-warn-edit:focus-visible,
.epqx-root .epqx-spectrum-dot:focus-visible {
  outline: 2px solid var(--epqx-focus, #1f4e79);
  outline-offset: 2px;
}

/* Body-level nodes (appended outside .epqx-root) need their own rule. */
.epqx-toc-item:focus-visible,
.epqx-toc-sub:focus-visible {
  outline: 2px solid #1f4e79;
  outline-offset: -2px;
}

/* Selectable choice cards. The accessible radio inside them is
   deliberately transparent, so focusing it used to produce NO visible
   indicator at all for keyboard users. The ring is drawn on the card. */
.epqx-root .epqx-card-opt:focus-within {
  outline: 2px solid var(--epqx-focus, #1f4e79);
  outline-offset: 3px;
}
/* Bare (image-only) cards sit flush, so pull the ring in slightly. */
.epqx-root .epqx-card-opt.epqx-card-bare:focus-within { outline-offset: 1px; }

/* Underline / inline / money inputs suppress the ring the normal fields
   get, which left them with a colour-only focus cue. Give them a ring
   too, without changing their resting look. */
.epqx-root .epqx-underline-input .epqx-input:focus-visible,
.epqx-root .epqx-inline-input:focus-visible,
.epqx-root .epqx-money-input:focus-visible {
  outline: 2px solid var(--epqx-focus, #1f4e79);
  outline-offset: 2px;
}
.epqx-root .epqx-money:focus-within {
  box-shadow: var(--epqx-focus-ring, 0 0 0 3px rgba(31, 78, 121, 0.38));
}

/* Checkboxes / owner radios: native controls, so reinforce rather than
   replace the platform indicator. */
.epqx-root .epqx-check input:focus-visible,
.epqx-root .epqx-owner-opt input:focus-visible,
.epqx-root .epqx-radio input:focus-visible {
  outline: 2px solid var(--epqx-focus, #1f4e79);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   P1.2  HOVER — capability-guarded.
   New hover effects go inside the positive guard below. The decorative
   lift/shadow hovers that already shipped are left where they are (they
   are proven, and several carry !important); instead the INVERSE guard
   neutralises them on touch/coarse-pointer devices, where a hover state
   otherwise sticks after a tap. Same outcome, no rewrite of working
   rules.
   --------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  /* Slightly firmer border on a hovered field label row's control — a
     hook for later phases; nothing changes today because no element
     carries .epqx-hoverable yet. */
  .epqx-root .epqx-hoverable:hover { border-color: var(--epqx-gold, #d8ae66); }
}

@media (hover: none), (pointer: coarse) {
  /* No sticky lift or shadow after a tap. */
  .epqx-root .epqx-btn:hover,
  .epqx-root .epqx-btn-review:hover,
  .epqx-root .epqx-card-opt:hover,
  .epqx-root .epqx-rec-card:hover,
  .epqx-root .epqx-pill:hover,
  .epqx-root .epqx-rankpill:hover,
  .epqx-root .epqx-couple-img:hover,
  .epqx-root .epqx-repeat-remove:hover,
  .epqx-root .epqx-spectrum-dot:hover,
  .epqx-root .epqx-input:hover,
  .epqx-root .epqx-inline-input:hover,
  .epqx-root .epqx-money-input:hover,
  .epqx-root .epqx-date-part:hover,
  .epqx-root textarea:hover,
  .epqx-root .epqx-screen-section3-entire-estate .epqx-card-opt:hover,
  .epqx-root .epqx-screen-section3-entire-estate-single .epqx-card-opt:hover {
    transform: none !important;
    box-shadow: none !important;
  }
}

/* ---------------------------------------------------------------------
   P1.3  PRESSED — a brief, reversible acknowledgement of a real press.
   Applies to pointer AND keyboard activation (:active covers both).
   --------------------------------------------------------------------- */
.epqx-root .epqx-btn:active,
.epqx-root .epqx-btn-review:active,
.epqx-root .epqx-action-btn:active,
.epqx-root .epqx-pill:active,
.epqx-root .epqx-rankpill:active,
.epqx-root .epqx-modal-continue:active,
.epqx-root .epqx-delivery-submit:active {
  transform: translateY(0) scale(0.985);
  transition-duration: var(--epqx-dur-instant, 120ms);
}
.epqx-root .epqx-btn[disabled]:active,
.epqx-root .epqx-btn.is-busy:active { transform: none; }

/* ---------------------------------------------------------------------
   P1.4  SELECTED — one shared ring for every "this is your answer" state.
   .epqx-card-opt.is-selected above already uses --epqx-ring-selected;
   these give the pill-style controls the same vocabulary when a later
   phase opts them in.
   --------------------------------------------------------------------- */
.epqx-root .epqx-is-selected-ring,
.epqx-root .epqx-pill.is-selected.epqx-is-selected-ring,
.epqx-root .epqx-rankpill.is-ranked.epqx-is-selected-ring {
  box-shadow: var(--epqx-ring-selected, 0 0 0 4px rgba(216, 174, 102, 0.20));
}

/* ---------------------------------------------------------------------
   P1.5  DISABLED — matches the existing .epqx-btn[disabled] look and
   extends it to aria-disabled and to non-button controls, so a disabled
   thing always reads the same way.
   --------------------------------------------------------------------- */
.epqx-root [aria-disabled="true"],
.epqx-root .epqx-is-disabled,
.epqx-root .epqx-input[disabled],
.epqx-root .epqx-select[disabled],
.epqx-root .epqx-textarea[disabled] {
  opacity: 0.35;
  cursor: default;
  transform: none;
}
.epqx-root [aria-disabled="true"] { pointer-events: none; }

/* ---------------------------------------------------------------------
   P1.6  BUSY — a control that has been activated and is waiting on the
   server (save, submit, upload). Communicated by opacity + cursor +
   a calm spinner, and always paired with aria-busy in the engine, so it
   is never conveyed by motion or colour alone.
   --------------------------------------------------------------------- */
.epqx-root .is-busy,
.epqx-root [aria-busy="true"] {
  cursor: progress;
  opacity: 0.75;
  pointer-events: none;
}
.epqx-root .is-busy::after {
  content: "";
  display: inline-block;
  width: 0.9em;
  height: 0.9em;
  margin-left: 0.55em;
  vertical-align: -0.1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: epqxSpin 720ms linear infinite;
}
@keyframes epqxSpin { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------------
   P1.7  SUCCESS — an action that completed. Colour PLUS a check glyph,
   never colour alone.
   --------------------------------------------------------------------- */
.epqx-root .is-success {
  border-color: var(--epqx-success, #1ba94c);
  color: var(--epqx-success-strong, #169042);
}
.epqx-root .is-success::after {
  content: "\2713";
  display: inline-block;
  margin-left: 0.45em;
  font-weight: 900;
}
.epqx-root .epqx-status-success {
  color: var(--epqx-success-strong, #169042);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
}

/* ---------------------------------------------------------------------
   P1.8  VALIDATION ERROR — reuses the shipped .epqx-field-error /
   .epqx-input-invalid look and extends the same treatment to
   aria-invalid and to selects/textareas, so every invalid control is
   marked identically. The inline message stays the primary signal.
   --------------------------------------------------------------------- */
.epqx-root .epqx-input[aria-invalid="true"],
.epqx-root .epqx-select[aria-invalid="true"],
.epqx-root .epqx-textarea[aria-invalid="true"],
.epqx-root .epqx-select.epqx-input-invalid,
.epqx-root .epqx-textarea.epqx-input-invalid {
  border-color: var(--epqx-error-border, #e02424);
  box-shadow: 0 0 0 3px rgba(224, 36, 36, 0.12);
}
.epqx-root .epqx-has-error > .epqx-label { color: var(--epqx-error-text, #c0392b); }

/* ---------------------------------------------------------------------
   P1.9  NEWLY REVEALED CONDITIONAL CONTENT.
   The engine adds .epqx-revealed to an element that has just become
   visible because of an answer the donor gave on this screen — and only
   then. It is NOT added on the first paint of a screen, on a same-screen
   re-render, or inside the editor, so nothing replays. The content is
   interactive for the whole 200 ms; the motion never gates access to it.
   --------------------------------------------------------------------- */
@keyframes epqxReveal {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
.epqx-root .epqx-revealed {
  animation: epqxReveal var(--epqx-dur-reveal, 200ms) var(--epqx-ease, cubic-bezier(0.22, 1, 0.36, 1)) both;
}

/* ---------------------------------------------------------------------
   P1.10  REDUCED MOTION — comprehensive.
   Nonessential animation and transition are reduced to effectively zero
   (not removed outright, so any code that waits on a transition still
   settles), smooth scrolling is off, staggers are flattened, and every
   state above still communicates itself through colour, shape, glyph and
   ARIA. Nothing is hidden waiting for an animation: the two screen
   animations are switched OFF by name (see the earlier rule) rather than
   shortened, so their opacity:0 start frame can never linger.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .epqx-root,
  .epqx-root * {
    animation-duration: 1ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }

  /* Turn the entrance/exit animations off by NAME, so no start frame
     (opacity 0 / translated) is ever painted. */
  .epqx-root .epqx-content.epqx-anim-in,
  .epqx-root .epqx-content.epqx-anim-out,
  .epqx-root .epqx-revealed {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  /* Staggered welcome cards appear immediately, fully opaque. */
  .epqx-root .epqx-welcome-card {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  /* The hand-drawn circle is drawn already complete. */
  .epqx-root .epqx-circle-svg ellipse {
    animation: none !important;
    stroke-dashoffset: 0 !important;
  }

  /* The card chain settles instantly instead of sliding, and its
     during-slide fades never appear. */
  .epqx-root .epqx-chain,
  .epqx-root .epqx-chain-track { transition: none !important; }
  .epqx-root .epqx-chain-fade { transition: none !important; opacity: 0 !important; }

  /* No decorative lift or scale anywhere. */
  .epqx-root .epqx-btn:hover,
  .epqx-root .epqx-btn:active,
  .epqx-root .epqx-btn-review:hover,
  .epqx-root .epqx-btn-review:active,
  .epqx-root .epqx-card-opt:hover,
  .epqx-root .epqx-rec-card:hover,
  .epqx-root .epqx-pill:hover,
  .epqx-root .epqx-pill:active,
  .epqx-root .epqx-rankpill:hover,
  .epqx-root .epqx-rankpill:active,
  .epqx-root .epqx-couple-img:hover,
  .epqx-root .epqx-repeat-remove:hover,
  .epqx-root .epqx-spectrum-dot:hover,
  .epqx-root .epqx-input:hover,
  .epqx-root .epqx-inline-input:hover,
  .epqx-root .epqx-money-input:hover,
  .epqx-root .epqx-date-part:hover,
  .epqx-root textarea:hover,
  .epqx-root .epqx-screen-section3-entire-estate .epqx-card-opt:hover,
  .epqx-root .epqx-screen-section3-entire-estate-single .epqx-card-opt:hover {
    transform: none !important;
  }

  /* The busy spinner would be the one continuously moving thing left;
     replace the rotation with a static ring so "busy" is still legible. */
  .epqx-root .is-busy::after {
    animation: none !important;
    border-right-color: currentColor;
    opacity: 0.45;
  }
}

/* =====================================================================
   PHASE 2 — CALM LAYOUT, TYPOGRAPHY AND DENSITY (v1.0.104)
   ---------------------------------------------------------------------
   Spacing, type and touch targets only. No approved text is touched, no
   layout is restructured, and NO NEW MOTION is introduced anywhere in
   this section. Screen-specific values still come from the schema as
   inline styles and continue to win, so every screen keeps the width and
   the deliberate layout it was designed with.
   ===================================================================== */

/* ---------------------------------------------------------------------
   P2.1  VERTICAL RHYTHM
   Air is added between stacked rows rather than inside them, so nothing
   changes width and no screen needs its own margins.
   --------------------------------------------------------------------- */

/* Consecutive field rows get a little more room than the schema's own gap,
   which is what made long forms read as one dense block. Applied ONLY
   inside a single-column stack: the engine marks those containers with
   .epqx-stack, so a row of three names side by side keeps its alignment. */
/* Only rows that FOLLOW a bare field need this: a preceding container has
   already contributed its own bottom margin, so pairs starting with a
   container are left alone and never pay for the same gap twice. */
.epqx-root .epqx-stack > .epqx-field + .epqx-field,
.epqx-root .epqx-stack > .epqx-field + .epqx-container {
  margin-top: var(--epqx-rhythm-stack, 10px);
}

/* A container that directly follows a heading or a paragraph is the start
   of a new question group; give it a clear break. */
.epqx-root .epqx-content > .epqx-heading + .epqx-container,
.epqx-root .epqx-content > .epqx-text + .epqx-container {
  margin-top: var(--epqx-space-sm, 10px);
}

/* The last row in a group should not add margin on top of the nav gap. */
.epqx-root .epqx-content > .epqx-container:last-child,
.epqx-root .epqx-chain-card > .epqx-container:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------------
   P2.2  TYPE LEVELS
   Seven levels, all token-driven. Sizes set per screen in the schema are
   inline and still win; these are the shared defaults.
   --------------------------------------------------------------------- */

/* Question heading — the label that introduces a group of inputs. */
.epqx-root .epqx-gen-q,
.epqx-root .epqx-spectrum-q,
.epqx-root .epqx-card-label {
  line-height: var(--epqx-lh-question, 1.4);
  overflow-wrap: break-word;
}
.epqx-root .epqx-radiogroup-label { line-height: var(--epqx-lh-question, 1.4); }

/* Help text — a quiet explanatory line under a control. */
.epqx-root .epqx-help,
.epqx-root .epqx-fileupload-status {
  font-size: var(--epqx-fs-help, 13.5px);
  line-height: var(--epqx-lh-label, 1.35);
  color: var(--epqx-muted, #6b7280);
}

/* Long, unbroken strings (ministry names, addresses, legal text, review
   answers) must never push a screen sideways. */
.epqx-root .epqx-card-label,
.epqx-root .epqx-summary-q,
.epqx-root .epqx-summary-a,
.epqx-root .epqx-asset-item,
.epqx-root .epqx-rec-name,
.epqx-root .epqx-rec-blurb,
.epqx-root .epqx-richline,
.epqx-root .epqx-modal-title,
.epqx-root .epqx-thanks-lead {
  overflow-wrap: break-word;
}

/* ---------------------------------------------------------------------
   P2.3  SOFTER CONTAINERS
   Fewer competing outlines. Inputs keep their border (they must read as
   editable); the decorative boxes around them are what gets quieter.
   --------------------------------------------------------------------- */
.epqx-root .epqx-rest-card { border-color: var(--epqx-line-soft, #eaecf0); box-shadow: var(--epqx-shadow-sm, 0 10px 24px rgba(17,24,39,0.08)); }
.epqx-root .epqx-asset-row { border-bottom-color: #f0f1f4; }
.epqx-root .epqx-asset-head { border-bottom-color: var(--epqx-line, #d0d5dd); }
.epqx-root .epqx-thanks-confirm { border-color: var(--epqx-line-soft, #eaecf0); }

/* Grouped panels get their definition from the surface tint, not a rule.  */
.epqx-root .epqx-rec-asset { border-color: var(--epqx-line-cool, #e6ecf3); }

/* ---------------------------------------------------------------------
   P2.4  TOUCH TARGETS — at least 44px for anything the donor taps.
   Padding and min-height only; no font size or colour changes, so
   nothing reflows horizontally.
   --------------------------------------------------------------------- */
.epqx-root .epqx-check,
.epqx-root .epqx-radio,
.epqx-root .epqx-owner-opt {
  min-height: var(--epqx-touch, 44px);
}

.epqx-root .epqx-save-resume,
.epqx-root .epqx-reset-q,
.epqx-root .epqx-skip-now,
.epqx-root .epqx-btn-link,
.epqx-root .epqx-btn-ghost,
.epqx-root .epqx-rec-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--epqx-touch, 44px);
  padding-inline: 8px;
}
/* The footer row holds three items on one line; let it wrap as a row
   rather than breaking a single link's label across two lines. */
.epqx-root .epqx-saverow { flex-wrap: wrap; align-items: center; gap: 2px; }

/* The section (table-of-contents) button is the one piece of persistent
   navigation on every screen; it gets a full 44px square. */
.epqx-root .epqx-toc-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--epqx-touch, 44px);
  min-height: var(--epqx-touch, 44px);
  margin-left: -10px;   /* keeps the label optically where it already was */
}

.epqx-root .epqx-tab,
.epqx-root .epqx-modal-tab {
  min-height: var(--epqx-touch, 44px);
}

/* The spectrum dots are a deliberate 14–20px design element. Rather than
   resize them, each one gets an invisible ~32px hit area — as large as
   the 12px gutters allow without two neighbours overlapping. */
.epqx-root .epqx-spectrum-dot { position: relative; }
.epqx-root .epqx-spectrum-dot::before {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
}

/* Table-of-contents entries live at body level, so they need their own
   rule (the tokens are scoped to .epqx-root). */
.epqx-toc-item, .epqx-toc-sub { min-height: 44px; display: flex; align-items: center; }

/* ---------------------------------------------------------------------
   P2.5  RESPONSIVE
   768 and below simplifies; 600 and below is already full-bleed (see the
   phones block earlier) and is refined here; safe-area insets are
   honoured so nothing sits under a notch or a home indicator.
   --------------------------------------------------------------------- */

/* Tablet band only — deliberately not overlapping the phones block, so
   the two never fight over the heading size. */
@media (min-width: 601px) and (max-width: 768px) {
  .epqx-root .epqx-heading { font-size: clamp(26px, 4.6vw, 34px) !important; }
  .epqx-root .epqx-card { padding: 26px 22px 30px; }
  .epqx-root .epqx-stage h2 { margin-bottom: 32px; }
  .epqx-root .epqx-nav { margin-top: 24px; }
}

@media (max-width: 600px) {
  /* Headings that read comfortably on a phone instead of shouting. */
  .epqx-root .epqx-heading {
    font-size: clamp(23px, 6.2vw, 32px) !important;
    line-height: 1.22 !important;
  }
  .epqx-root .epqx-card { padding: 20px 16px 26px !important; }
  .epqx-root .epqx-stage h2 { margin-bottom: 28px; }
  .epqx-root .epqx-nav { margin-top: 24px; }
  .epqx-root .epqx-kicker { margin-bottom: 16px; }
  /* Slightly more air between rows, since a phone shows fewer of them. */
  .epqx-root .epqx-container { margin-bottom: 20px; }

  /* Safe-area insets: keep the header, section label and navigation clear
     of a notch, a rounded corner, or the home indicator. */
  .epqx-root .epqx-header,
  .epqx-root .epqx-kicker,
  .epqx-root .epqx-nav {
    padding-left: max(12px, env(safe-area-inset-left)) !important;
    padding-right: max(12px, env(safe-area-inset-right)) !important;
  }
  .epqx-root .epqx-nav { padding-bottom: env(safe-area-inset-bottom); }
  .epqx-root .epqx-saverow,
  .epqx-root .epqx-version-row {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }

  /* Full-width primary actions are easier to hit one-handed, and the row
     no longer has to squeeze two buttons plus a link onto one line. */
  .epqx-root .epqx-nav .epqx-btn-primary,
  .epqx-root .epqx-nav .epqx-btn-secondary { flex: 1 1 44%; }

  /* Keep each footer link's label on one line on a narrow screen. */
  .epqx-root .epqx-save-resume,
  .epqx-root .epqx-reset-q,
  .epqx-root .epqx-skip-now { padding-inline: 2px; white-space: nowrap; }
}

/* The Month / Day / Year row plus its calendar button now fits on a single
   line from 381px up, so the date stops taking two rows on a phone. Below
   381px it keeps the wrapping the earlier phones block established. */
@media (min-width: 381px) and (max-width: 600px) {
  .epqx-root .epqx-date { flex-wrap: nowrap !important; }
  .epqx-root .epqx-date-part { flex: 1 1 0 !important; min-width: 0; }
  .epqx-root .epqx-date-month { flex: 1.4 1 0 !important; }
  .epqx-root .epqx-date-calwrap { flex: 0 0 44px !important; }
}

/* Narrow phones: trim the frame, never the readability. */
@media (max-width: 380px) {
  .epqx-root .epqx-card { padding: 16px 12px 22px !important; }
  .epqx-root .epqx-kicker { font-size: 12px; }
  .epqx-root .epqx-money { max-width: none; }
}

/* Very large desktops: the questionnaire stays centred (the engine sets
   its max-width per screen) and the surrounding calm has a floor, so the
   card never looks glued to the top of the window. */
@media (min-width: 1600px) {
  .epqx-root .epqx-shell { padding: 26px; }
}

/* ---------------------------------------------------------------------
   Select-one radio list inside a grouped panel (v1.0.105).
   Used by the Rest & Residue predecease clause: a quiet caption above two
   stacked choices, each with its own explanatory badge. Sizing only —
   the panel, the wording and the tooltips come from the schema.
   --------------------------------------------------------------------- */
.epqx-root .epqx-radiolist .epqx-radiogroup-label {
  font-size: var(--epqx-fs-help, 13.5px);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--epqx-muted, #6b7280);
}
.epqx-root .epqx-radiolist .epqx-radio {
  gap: 12px;
  font-weight: 600;
  line-height: var(--epqx-lh-question, 1.4);
  align-items: center;
}
.epqx-root .epqx-radiolist .epqx-radio input { flex: 0 0 auto; }

/* =====================================================================
   §NAV — SCREEN TO SCREEN (v1.0.106, replaced by a cross-fade in v1.0.114)
   ---------------------------------------------------------------------
   These classes are applied by the engine's navigateTo() ONLY, and only
   for a genuine move between two different screens. Nothing here is
   attached to a screen, a state, or a redraw, so an in-place re-render
   cannot pick one up.

   v1.0.106 moved screens sideways: forward left, back right, a jump a
   short fade. v1.0.114 replaces all three with the same quiet cross-fade,
   because the sideways shift is what made moving between screens read as
   a series of small jolts rather than one continuous document. Opacity
   only — no transform at all — so there is nothing to jerk, nothing to
   clip, nothing that can widen the page, and the two halves meet at a
   single value the eye cannot see a seam in.

   THE THREE DIRECTIONS STILL EXIST. The engine still distinguishes
   forward, back and jump and still applies a different class for each;
   only the animation they resolve to is now the same. The directional
   keyframes below are kept, unused, precisely so the old behaviour is
   three lines away if it is ever wanted back — and so a reader of this
   file can see what changed rather than finding a gap.

   NOT AFFECTED: the slide-up entrance on the screens that declare
   transition:"slideUp" (Generosity Discovery, the child-detail screens).
   Those take a different path through navigateTo() entirely — see
   `legacySlide` in epqx-engine.js — and were deliberately left alone.
   ===================================================================== */

/* The cross-fade itself. Deliberately pure opacity: a fade that also
   moves is a slide, and this screen is not sliding. */
@keyframes epqxNavFadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes epqxNavFadeIn  { from { opacity: 0; } to { opacity: 1; } }

@keyframes epqxNavOutLeft {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translate3d(calc(-1 * var(--epqx-nav-shift, 18px)), 0, 0); }
}
@keyframes epqxNavInRight {
  from { opacity: 0; transform: translate3d(var(--epqx-nav-shift, 18px), 0, 0); }
  to   { opacity: 1; transform: none; }
}
@keyframes epqxNavOutRight {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translate3d(var(--epqx-nav-shift, 18px), 0, 0); }
}
@keyframes epqxNavInLeft {
  from { opacity: 0; transform: translate3d(calc(-1 * var(--epqx-nav-shift, 18px)), 0, 0); }
  to   { opacity: 1; transform: none; }
}
@keyframes epqxNavOutFade {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translate3d(0, -8px, 0); }
}
@keyframes epqxNavInFade {
  from { opacity: 0; transform: translate3d(0, 8px, 0); }
  to   { opacity: 1; transform: none; }
}

/* All three directions resolve to the same cross-fade (v1.0.114).
   `linear` on the way out and the standard ease on the way in: a fade-out
   that accelerates reads as a snatch, and a fade-in that decelerates is
   what makes the arriving screen feel like it settles rather than blinks. */
.epqx-root .epqx-content.epqx-nav-out-fwd,
.epqx-root .epqx-content.epqx-nav-out-back,
.epqx-root .epqx-content.epqx-nav-out-jump {
  animation: epqxNavFadeOut var(--epqx-dur-nav-exit, 110ms) linear both;
}
.epqx-root .epqx-content.epqx-nav-in-fwd,
.epqx-root .epqx-content.epqx-nav-in-back,
.epqx-root .epqx-content.epqx-nav-in-jump {
  animation: epqxNavFadeIn var(--epqx-dur-nav-enter, 190ms) var(--epqx-ease, ease-out) both;
}

/* NOTE on overflow: nothing is clipped here, on purpose — and since
   v1.0.114 there is nothing to clip either, because the screen transition
   no longer moves anything sideways. The note is kept because the reason
   still holds for the retained directional keyframes above: the shift was
   18px on desktop and 12px on phones, in both cases no larger than the
   card's own horizontal padding (28px / 16px / 12px), so a moving screen
   stayed inside its surface and could never widen the document. Measured
   mid-transition at 320px and 390px. An overflow property here would have
   been the safer-looking choice but it establishes a new formatting
   context on the stage, which shifts sub-pixel layout on every screen.
*/

/* The programmatic focus target at the start of a new screen must not
   draw a focus ring for a mouse user; keyboard focus is unaffected
   because :focus-visible still applies. */
.epqx-root .epqx-content[tabindex="-1"]:focus,
.epqx-root .epqx-heading[tabindex="-1"]:focus { outline: none; }

/* Phones: a smaller shift, since the card runs edge to edge. */
@media (max-width: 600px) {
  .epqx-root { --epqx-nav-shift: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  /* Directional movement is replaced by an immediate swap. The engine
     already skips the animation entirely under reduced motion; these
     rules guarantee that nothing is ever left translated or invisible
     even if the setting changes mid-transition. */
  .epqx-root .epqx-content.epqx-nav-out-fwd,
  .epqx-root .epqx-content.epqx-nav-out-back,
  .epqx-root .epqx-content.epqx-nav-out-jump,
  .epqx-root .epqx-content.epqx-nav-in-fwd,
  .epqx-root .epqx-content.epqx-nav-in-back,
  .epqx-root .epqx-content.epqx-nav-in-jump {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .epqx-root .epqx-stage { transition: none !important; }
}

/* =====================================================================
   PHASE 4 — PREMIUM CONTROLS AND MICRO-FEEDBACK (v1.0.107)
   ---------------------------------------------------------------------
   Every control acknowledges the donor: a clear resting state, hover on
   devices that can hover, an obvious keyboard focus, a small pressed
   response, and honest disabled / busy states. Nothing bounces, nothing
   is playful, and every animation has a still equivalent under reduced
   motion (P4.8).

   No value, label or navigation rule is touched by anything here.
   ===================================================================== */

/* ---------------------------------------------------------------------
   P4.1  BUTTONS — one shared vocabulary for every kind.
   The families: .epqx-btn-primary (Continue / Add child),
   .epqx-btn-secondary (Previous), .epqx-action-btn (Add …),
   .epqx-repeat-remove (×), .epqx-btn-review, .epqx-modal-continue,
   .epqx-delivery-submit, and the text links (Save, Reset, Skip).
   --------------------------------------------------------------------- */

/* Resting state: a hairline of definition so a button never looks like
   flat text, without adding weight. */
.epqx-root .epqx-btn-primary,
.epqx-root .epqx-modal-continue,
.epqx-root .epqx-delivery-submit {
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.10);
}
.epqx-root .epqx-action-btn { box-shadow: 0 1px 2px rgba(16, 24, 40, 0.08); }
.epqx-root .epqx-btn-secondary { box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05); }

/* Hover — only where hovering is a real thing. Colour AND elevation, so
   it does not depend on colour alone. */
@media (hover: hover) and (pointer: fine) {
  .epqx-root .epqx-btn-primary:hover,
  .epqx-root .epqx-modal-continue:hover,
  .epqx-root .epqx-delivery-submit:hover {
    box-shadow: 0 4px 10px rgba(16, 24, 40, 0.18);
  }
  .epqx-root .epqx-btn-secondary:hover {
    border-color: var(--epqx-line-strong, #cfd2d8);
    background: #fcfcfd;
    box-shadow: 0 4px 10px rgba(16, 24, 40, 0.10);
  }
  .epqx-root .epqx-action-btn:hover { box-shadow: 0 4px 10px rgba(199, 154, 82, 0.28); }
  .epqx-root .epqx-repeat-remove:hover { box-shadow: 0 4px 10px rgba(226, 59, 59, 0.28); }
  .epqx-root .epqx-save-resume:hover,
  .epqx-root .epqx-reset-q:hover,
  .epqx-root .epqx-skip-now:hover { background: rgba(37, 99, 235, 0.07); border-radius: var(--epqx-radius-input, 4px); }
}

/* Pressed — a very small settle, never a bounce. Fires for pointer AND
   keyboard activation, and is the ~100ms acknowledgement required of
   every control even when the real work takes longer (P4.6). */
.epqx-root .epqx-btn:active,
.epqx-root .epqx-btn-review:active,
.epqx-root .epqx-action-btn:active,
.epqx-root .epqx-repeat-remove:active,
.epqx-root .epqx-modal-continue:active,
.epqx-root .epqx-modal-secondary:active,
.epqx-root .epqx-delivery-submit:active,
.epqx-root .epqx-warn-confirm:active,
.epqx-root .epqx-warn-edit:active,
.epqx-root .epqx-tab:active,
.epqx-root .epqx-modal-tab:active {
  transform: translateY(1px) scale(0.99);
  box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  transition-duration: var(--epqx-dur-instant, 120ms);
}
/* Nothing that cannot be pressed should look pressable. */
.epqx-root .epqx-btn[disabled]:active,
.epqx-root .epqx-btn.is-busy:active,
.epqx-root [aria-disabled="true"]:active,
.epqx-root .epqx-delivery-submit:disabled:active { transform: none; }

/* Disabled — dimmed, no pointer, and never showing a hover or press. */
.epqx-root .epqx-btn[disabled],
.epqx-root .epqx-delivery-submit:disabled,
.epqx-root .epqx-repeat-remove[disabled],
.epqx-root .epqx-action-btn[disabled] {
  box-shadow: none;
  cursor: not-allowed;
}

/* Busy — the spinner comes from P1.6; this keeps the label steady while
   it spins so the button does not resize under the reader. */
.epqx-root .epqx-btn.is-busy,
.epqx-root .epqx-delivery-submit.is-busy { box-shadow: none; }

/* ---------------------------------------------------------------------
   P4.2  CHOICE CARDS — selection must be unmistakable.
   Four signals at once, none of them colour alone: a heavier ring, a
   tinted surface, a small lift, and a checkmark badge.
   --------------------------------------------------------------------- */
.epqx-root .epqx-card-opt {
  transition: border-color var(--epqx-dur-select, 180ms) var(--epqx-ease, ease),
              box-shadow var(--epqx-dur-select, 180ms) var(--epqx-ease, ease),
              transform var(--epqx-dur-select, 180ms) var(--epqx-ease, ease),
              background-color var(--epqx-dur-select, 180ms) var(--epqx-ease, ease);
}
.epqx-root .epqx-card-opt.is-selected {
  background: #fffdf7;
  /* Inset ring reads as a 2px border without changing the box, so
     nothing reflows when a card becomes selected. */
  box-shadow: inset 0 0 0 2px var(--epqx-gold, #d8ae66),
              var(--epqx-ring-selected, 0 0 0 4px rgba(216, 174, 102, 0.20)),
              0 6px 16px rgba(199, 154, 82, 0.18);
  transform: translateY(-1px);
}
/* The badge. Absolutely positioned, so it is not a flex item and cannot
   move the card's own content. */
.epqx-root .epqx-card-opt.is-selected::after {
  content: "\2713";
  position: absolute;
  top: 8px;
  right: 8px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--epqx-gold, #d8ae66);
  color: #ffffff;
  font-size: 12px;
  font-weight: 900;
  line-height: 22px;
  text-align: center;
}
/* The badge only ANIMATES when the donor actually chooses — the engine adds
   .epqx-just-selected on click and drops it when the animation ends. A screen
   redraw rebuilds the card already selected, so the badge is simply there,
   with no replay (the same rule the screen entrance follows). */
.epqx-root .epqx-card-opt.epqx-just-selected::after {
  animation: epqxSelectMark var(--epqx-dur-select, 180ms) var(--epqx-ease, ease) both;
}
@keyframes epqxSelectMark {
  from { opacity: 0; transform: scale(0.6); }
  to   { opacity: 1; transform: scale(1); }
}
/* Bare (image-only) cards keep their frameless look, so the ring is
   drawn tight and the badge tucks in. */
.epqx-root .epqx-card-opt.epqx-card-bare.is-selected {
  background: transparent;
  box-shadow: var(--epqx-ring-selected, 0 0 0 4px rgba(216, 174, 102, 0.20));
}
.epqx-root .epqx-card-opt.epqx-card-bare.is-selected::after { top: 0; right: 0; }
/* A disabled option must not look selectable. */
.epqx-root .epqx-card-opt.is-disabled { box-shadow: none; transform: none; }

/* Pills and rank chips share the vocabulary when chosen. */
.epqx-root .epqx-pill.is-selected,
.epqx-root .epqx-rankpill.is-ranked { box-shadow: 0 4px 12px rgba(199, 154, 82, 0.28); }
.epqx-root .epqx-pill:active,
.epqx-root .epqx-rankpill:active,
.epqx-root .epqx-spectrum-dot:active { transform: translateY(1px) scale(0.99); }

/* ---------------------------------------------------------------------
   P4.3  NATIVE CHECKBOXES AND RADIOS
   Kept native (real inputs, real semantics, real keyboard behaviour) —
   only the surroundings are dressed. Touch targets came in P2.4.
   --------------------------------------------------------------------- */
.epqx-root .epqx-check input,
.epqx-root .epqx-radio input,
.epqx-root .epqx-owner-opt input { cursor: pointer; }

/* SELECTED is carried by the native control's own mark — a shape, not a
   colour — which is exactly why these stay native. Nothing is added here
   for the checked state on purpose: bolding or tinting the label would
   reflow the text every time a donor ticks a box, and the platform
   already communicates it correctly to assistive technology.

   Disabled: dimmed and clearly not clickable. */
.epqx-root .epqx-check:has(input:disabled),
.epqx-root .epqx-radio:has(input:disabled),
.epqx-root .epqx-owner-opt:has(input:disabled) { opacity: 0.45; cursor: default; }
.epqx-root .epqx-check input:disabled,
.epqx-root .epqx-radio input:disabled,
.epqx-root .epqx-owner-opt input:disabled { cursor: default; }

/* Error on a choice group: a red rule to its left plus the message text
   the engine renders — shape and words, not just colour. */
.epqx-root .epqx-radiogroup.epqx-has-error,
.epqx-root .epqx-check.epqx-has-error {
  border-left: 3px solid var(--epqx-error-border, #e02424);
  padding-left: 10px;
}

@media (hover: hover) and (pointer: fine) {
  /* A hovered choice reads as reachable without moving anything. */
  .epqx-root .epqx-check:hover input,
  .epqx-root .epqx-radio:hover input,
  .epqx-root .epqx-owner-opt:hover input { outline: 2px solid rgba(216, 174, 102, 0.45); outline-offset: 2px; }
}

/* ---------------------------------------------------------------------
   P4.4  FIELDS
   Focus came in P1.1. Added here: a quiet "this one checks out" tick, a
   clearer error, and a real disabled / read-only look. An untouched
   field is never marked either way — the engine only judges a field the
   donor has left, and only where there is something to validate.
   --------------------------------------------------------------------- */
.epqx-root .epqx-input.epqx-input-valid {
  border-color: #9ccfae;
  /* A small check drawn into the field: no extra node, so no layout shift. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%231ba94c' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 10.5 8 14.5 16 6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 15px 15px;
  padding-right: 36px;
  transition: border-color var(--epqx-dur-standard, 180ms) var(--epqx-ease, ease);
}
.epqx-root .epqx-input.epqx-input-invalid { padding-right: 14px; background-image: none; }

/* Disabled / read-only: unmistakably not editable. */
.epqx-root .epqx-input[disabled],
.epqx-root .epqx-select[disabled],
.epqx-root .epqx-textarea[disabled],
.epqx-root .epqx-input[readonly],
.epqx-root .epqx-textarea[readonly] {
  background: #f4f5f7;
  color: #6b7280;
  cursor: default;
  box-shadow: none;
}
.epqx-root .epqx-input[readonly] { border-style: dashed; }

/* ---------------------------------------------------------------------
   P4.5  REPEATABLE ROWS
   A new row settles in; a removed one closes its own gap before the list
   redraws (the height itself is animated inline by the engine, which is
   the only reliable way to collapse a flex row).
   --------------------------------------------------------------------- */
@keyframes epqxRowIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.epqx-root .epqx-repeat-item.epqx-row-in {
  animation: epqxRowIn var(--epqx-dur-row-in, 200ms) var(--epqx-ease, ease) both;
}
.epqx-root .epqx-repeat-item.epqx-row-out { pointer-events: none; }

/* ---------------------------------------------------------------------
   P4.8  REDUCED MOTION — a still equivalent for every one of the above.
   The engine already skips the row animations and the collapse outright;
   these rules make the CSS side safe on its own too.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .epqx-root .epqx-card-opt.is-selected::after,
  .epqx-root .epqx-card-opt.epqx-just-selected::after,
  .epqx-root .epqx-repeat-item.epqx-row-in {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* Selection stays completely legible — ring, tint and badge remain; only
     the lift is dropped. */
  .epqx-root .epqx-card-opt.is-selected { transform: none !important; }
  .epqx-root .epqx-btn:active,
  .epqx-root .epqx-btn-review:active,
  .epqx-root .epqx-action-btn:active,
  .epqx-root .epqx-repeat-remove:active,
  .epqx-root .epqx-modal-continue:active,
  .epqx-root .epqx-modal-secondary:active,
  .epqx-root .epqx-delivery-submit:active,
  .epqx-root .epqx-warn-confirm:active,
  .epqx-root .epqx-warn-edit:active,
  .epqx-root .epqx-tab:active,
  .epqx-root .epqx-modal-tab:active,
  .epqx-root .epqx-pill:active,
  .epqx-root .epqx-rankpill:active,
  .epqx-root .epqx-spectrum-dot:active {
    transform: none !important;
  }
  .epqx-root .epqx-repeat-item { transition: none !important; }
}

/* =====================================================================
   PHASE 5 — PROGRESS, ORIENTATION AND COMPLETION (v1.0.108)
   ---------------------------------------------------------------------
   The progress rail is one segment per SECTION, not one bar across
   forty-one screens, so the questionnaire reads as a handful of chunks
   of work. Section names and numbers come from the approved
   table-of-contents labels; nothing here invents or renames anything.
   ===================================================================== */

/* The rail. Same height and radius as the single bar it replaces. */
.epqx-root .epqx-progress {
  display: flex;
  gap: 4px;
  background: transparent;      /* each segment carries its own track now */
  overflow: visible;
}
.epqx-root .epqx-progress-seg {
  flex: 1 1 0;
  min-width: 0;
  height: 10px;
  background: #e5e7eb;
  border-radius: 999px;
  overflow: hidden;
  position: relative;
}
.epqx-root .epqx-progress-seg-fill {
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--epqx-gold, #d8ae66), var(--epqx-gold-dark, #c89b4b));
  transition: width var(--epqx-dur-progress, 240ms) var(--epqx-ease, ease);
}
/* A finished section: fully filled, and a touch deeper so "behind me" and
   "where I am" are not the same colour. */
.epqx-root .epqx-progress-seg.is-done .epqx-progress-seg-fill {
  background: linear-gradient(90deg, var(--epqx-gold-dark, #c89b4b), #b98c3f);
}
/* The section being worked on: a soft ring so it is findable at a glance
   without shouting. */
.epqx-root .epqx-progress-seg.is-current {
  box-shadow: 0 0 0 2px rgba(216, 174, 102, 0.35);
}

/* ---------------------------------------------------------------------
   P5.2  TABLE OF CONTENTS — where am I, what is done, what is closed off.
   These entries live at body level, outside .epqx-root, so they are
   styled unscoped (as the existing TOC rules already are).
   --------------------------------------------------------------------- */

/* Completed: a checkmark in front of the label. Shape first, colour
   second — never colour alone. The tick is positioned ABSOLUTELY and the
   room for it is reserved by padding on every row, so a row's label sits
   in exactly the same place whether it is ticked or not (these rows are
   flex containers — an in-flow pseudo-element would be distributed by
   justify-content and shove the label off-centre). */
.epqx-toc-item, .epqx-toc-sub { position: relative; padding-left: 30px; }
.epqx-toc-sub { padding-left: 44px; }
.epqx-toc-item.is-done::before,
.epqx-toc-sub.is-done::before {
  content: "\2713";
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #1ba94c;
  font-weight: 900;
  font-size: 13px;
  line-height: 1;
}
.epqx-toc-sub.is-done::before { left: 24px; }
.epqx-toc-item.is-done { color: #33465c; }

/* Closed off by the donor's own answers: visible, so the shape of the
   questionnaire still makes sense, but inert. */
.epqx-toc-sub.is-unavailable {
  opacity: 0.4;
  cursor: default;
  text-decoration: line-through;
}
.epqx-toc-sub.is-unavailable:hover { background: transparent; color: #5b6470; }
.epqx-toc-group.is-unavailable { display: none; }

/* Current location: stronger than the old tint — a gold spine plus the
   existing highlight, so it is obvious which row you are on. */
.epqx-toc-item.is-current,
.epqx-toc-sub.is-current {
  box-shadow: inset 3px 0 0 0 var(--epqx-gold, #c79a52);
}

/* Expand/collapse affordance: the caret gets its own space and turns. */
.epqx-toc-item.has-children .epqx-toc-caret { transition: transform .15s ease; }

/* Mobile: a near-full-width sheet with comfortable rows, instead of a
   narrow menu pinned to the icon. */
@media (max-width: 600px) {
  .epqx-toc-menu {
    min-width: 0;
    width: calc(100vw - 24px);
    max-width: calc(100vw - 24px);
    left: 12px !important;
    padding: 10px;
  }
  .epqx-toc-item, .epqx-toc-sub { min-height: 48px; font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .epqx-root .epqx-progress-seg-fill { transition: none !important; }
  .epqx-toc-item.has-children .epqx-toc-caret { transition: none !important; }
}

/* =====================================================================
   v1.0.109 — two follow-ups from staging review
   ===================================================================== */

/* The header's right-hand stack: the section indicator always, with the
   optional encouragement message beneath it when that mode is on. */
.epqx-root .epqx-headright {
  justify-self: end;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  text-align: right;
}
.epqx-root .epqx-section-of {
  font-size: var(--epqx-fs-kicker, 13px);
  font-weight: 800;
  letter-spacing: 0.08em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--epqx-muted, #6b7280);
  white-space: nowrap;
}
@media (max-width: 600px) {
  .epqx-root .epqx-section-of { font-size: 12px; letter-spacing: 0.06em; }
}

/* (Field-label alignment is enforced in the isolation layer above, §3b,
   because a host theme can outrank an ordinary rule here.) */

/* =====================================================================
   PHASE 6 — SYSTEM STATUS (v1.0.110)
   ---------------------------------------------------------------------
   One quiet line under the questionnaire. Deliberately not a command
   bar: small, muted, and only as loud as the news it carries.

   NOTE: this component is a sibling of the questionnaire root, not a
   descendant, so it cannot use the design tokens — every value here is
   literal on purpose.
   ===================================================================== */
.epqx-app-status {
  /* A centred block rather than a flex row. A flex row was tried first, and
     on a phone a message long enough to wrap took the full width, which
     pushed the marker glyph out to the far left of a centred paragraph. The
     marker is now part of the text run (see below), so it wraps with the
     words and stays beside them at every width. */
  display: block;
  min-height: 22px;
  margin: 14px auto 0;
  max-width: 760px;
  padding: 0 12px;
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
  /* Every colour in this component is !important, for the reason given in
     the host-theme isolation note at the end of the section: it sits outside
     .epqx-root, so a theme recolouring bare text in its content area would
     otherwise repaint the donor's status line. */
  color: #5a6371 !important;
  transition: color 200ms ease;
}

/* The visible line. Screen-reader announcements come from the two
   off-screen regions below, so this is hidden from them to stop the same
   words being read twice. */
.epqx-app-status .epqx-status-text { min-width: 0; }

/* Off-screen announcement regions. Not display:none — a hidden live
   region is never announced. */
.epqx-app-status .epqx-status-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* A marker per state, so status is never carried by colour alone.

   These are deliberately DARKER shades of the plugin's own success and
   error colours (#1ba94c / #cf4231). Those two are used elsewhere as
   glyphs and fills, where a lighter hue is fine; here they would be
   13.5px body text on an unknown host page background, and the brand
   shades measure only ~4.1:1 against a light grey one. These shades
   clear 5:1 on both white and a light grey page. */
.epqx-app-status.is-ok      { color: #10702f !important; }
.epqx-app-status.is-error   { color: #b8352a !important; }
.epqx-app-status.is-pending { color: #5a6371 !important; }

/* The two OUTCOMES carry a marker glyph, so "it worked" and "it didn't" are
   never told apart by colour alone. Both are shapes every platform font has.

   Pending deliberately has NO marker: every pending message already ends in
   an ellipsis ("Saving your progress…", "Submitting your questionnaire…"),
   so a leading "…" glyph rendered as "… Saving your progress…" — the same
   punctuation twice. The words carry the meaning there; the marker is only
   needed where colour would otherwise be doing the work.

   The marker hangs off the visible text span, not the container, so it flows
   with the words. That span is aria-hidden, so the glyph is never read out —
   the announcement regions carry the plain wording. The trailing character is
   a non-breaking space, so the marker can never be orphaned on its own line. */
.epqx-app-status.is-ok .epqx-status-text::before,
.epqx-app-status.is-error .epqx-status-text::before {
  font-weight: 900;
}
.epqx-app-status.is-ok .epqx-status-text::before    { content: "\2713\00a0"; }
.epqx-app-status.is-error .epqx-status-text::before { content: "\0021\00a0"; }

/* Reassure, then get out of the way: a saved state stays on screen and
   fully legible, but settles back to the same muted grey as the rest of
   the line so it stops drawing the eye.

   This is a colour change and NOT a fade. Dropping the opacity was tried
   first and is what a "fade out" usually means, but 55% of a grey on a
   light page measures about 2:1 — the reassurance would still be there
   and no longer readable. Nothing is lost by de-emphasising with colour
   instead: the words do not change, the ✓ marker stays, and under
   reduced motion the change simply happens at once. */
.epqx-app-status.is-settled,
.epqx-app-status.is-settled.is-ok { color: #5a6371 !important; }

@media (max-width: 600px) {
  .epqx-app-status { font-size: 13px; margin-top: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .epqx-app-status { transition: none !important; }
}

/* ---------------------------------------------------------------------
   Host-theme isolation for this component (same job as §1–§3b above).

   This region is the one part of the plugin's own UI that lives OUTSIDE
   `.epqx-root`, which is where every other isolation rule is scoped —
   so nothing above protects it. Until v1.0.110 it was styled with
   inline styles, which no theme selector can outrank; moving it to
   classes is what makes the states, the settle and the reduced-motion
   rule possible, but it also handed a hostile theme a way in. A theme
   that uppercases, recolours, re-fonts or left-aligns bare <div>/<span>
   text inside its content area would otherwise reshape the status line
   on the live site.

   Only the properties a theme realistically leaks are forced. The state
   colours carry !important on their own rules above, so they stay correct
   and still outrank one another by specificity in the normal way.
   --------------------------------------------------------------------- */
.epqx-app-status,
.epqx-app-status .epqx-status-text {
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif !important;
  font-style: normal !important;
  text-transform: none !important;
  text-decoration: none !important;
  letter-spacing: normal !important;
  text-align: center !important;
}
.epqx-app-status { font-size: 13.5px !important; font-weight: 600 !important; line-height: 1.4 !important; }
@media (max-width: 600px) {
  .epqx-app-status { font-size: 13px !important; }
}

/* =====================================================================
   PHASE 7 — SECTION-BOUNDARY MOMENTS (v1.0.111)
   ---------------------------------------------------------------------
   A brief chapter marker over the question card when the donor moves
   forward into a new numbered section for the first time on a journey.
   It is a temporary node, not a screen: it has no index, is not in the
   table of contents, the review list, the progress arithmetic or any
   payload, and it removes itself.

   Everything here is scoped under `.epqx-root .epqx-card`, and the
   positioning context is created by a class the engine adds only while
   the card is up (`.epqx-has-break`) — so on all 41 screens, at rest,
   this section changes nothing at all.
   ===================================================================== */

/* The containing block, established ONLY for the moment the card exists.
   Making .epqx-card permanently relative would silently re-anchor any
   absolutely-positioned descendant on every screen; this cannot. */
.epqx-root .epqx-card.epqx-has-break { position: relative; }

.epqx-root .epqx-sectionbreak {
  position: absolute;
  inset: 0;
  z-index: 4;
  /* A plain block, because the content inside is pinned to the viewport
     rather than centred in the card — see .epqx-sectionbreak-inner. */
  display: block;
  overflow: hidden;
  /* The same white surface as the card it covers, so the moment reads as
     the card turning over rather than a panel flying in on top of it. */
  background: var(--epqx-card, #fff);
  border-radius: var(--epqx-radius-lg, 22px);
  /* The RESTING state is the visible one, and the entrance is a keyframe
     animation that runs as soon as the node is inserted.

     This is deliberately not "insert at opacity 0, then add a class on the
     next animation frame", which is the usual pattern and was tried first:
     when requestAnimationFrame does not fire promptly — a throttled tab, or
     one the browser is not currently painting — the card sits invisible for
     its whole hold and the donor stares at the screen they just left. An
     animation needs no callback, so it cannot stall. No fill-mode is used
     either: the values below ARE the end state, so nothing lingers holding a
     compositing layer once the animation finishes (the v1.0.106 lesson). */
  opacity: 1;
  transform: none;
  animation: epqxBreakIn var(--epqx-dur-break-in, 320ms) var(--epqx-ease, ease);
}

/* A very small rise. Anything larger reads as a panel flying in. */
@keyframes epqxBreakIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Lifting away, faster than it arrived, revealing the real screen that has
   already begun its normal forward entrance underneath. */
.epqx-root .epqx-sectionbreak.is-out {
  animation: epqxBreakOut var(--epqx-dur-break-out, 180ms) var(--epqx-ease-exit, ease) forwards;
  pointer-events: none;
}
@keyframes epqxBreakOut {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(-6px); }
}

/* Pinned to what the donor can actually see.

   The card being covered is as tall as the screen it replaces, and some of
   those screens are several viewports long on a phone. Centring the chapter
   text in the CARD put it a thousand pixels below the fold — the donor pressed
   Continue at the bottom of a long screen and got a blank white panel. Sticky
   positioning inside the full-height cover keeps the words in front of them
   wherever they were reading, without scrolling the page out from under them.
   On a card shorter than the viewport `min()` resolves to the card, so this is
   ordinary centring. */
.epqx-root .epqx-sectionbreak-inner {
  position: sticky;
  top: 0;
  height: min(100%, 100vh);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 14px;
  padding: 24px;
  margin: 0 auto;
  max-width: var(--epqx-width-read, 640px);
}

/* "Section 3" — the first half of the approved label, in the same kicker
   voice used above every screen, so the chapter marker is recognisably
   part of the questionnaire rather than a splash screen. */
.epqx-root .epqx-sectionbreak-lead {
  font-size: var(--epqx-fs-kicker, 13px);
  font-weight: 800;
  letter-spacing: 0.14em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--epqx-muted, #6b7280);
}

/* The one decorative mark: a short gold rule, the same accent the rail
   uses. It carries no information, so nothing is lost when it is not
   perceived. */
.epqx-root .epqx-sectionbreak-rule {
  width: 44px;
  height: 3px;
  border-radius: 2px;
  background: var(--epqx-gold, #d8ae66);
}

/* "Distribution of Your Estate" — the second half of the approved label,
   one step down from a screen heading so the chapter marker never looks
   like a question. */
.epqx-root .epqx-sectionbreak-title {
  font-size: clamp(24px, 2.6vw, 36px);
  font-weight: 800;
  line-height: var(--epqx-lh-heading, 1.15);
  letter-spacing: -0.02em;
  color: var(--epqx-ink, #1a1f2b);
  text-wrap: balance;
}

/* The donor's way on (v1.0.112). The divider dwells now, so it carries a
   real, visible, focusable control instead of an undiscoverable "press
   anything" shortcut. It is the questionnaire's own primary button, with its
   own approved "Continue" label, so nothing new is introduced. */
.epqx-root .epqx-sectionbreak-go { margin-top: 18px; }

/* The nav row is hidden while a divider is up, so there is exactly one
   Continue on screen. visibility, not display: the row keeps its height, so
   the page does not jump as the divider arrives and leaves.

   !important because this must not be a cascade argument. A second Continue
   showing through underneath the divider is not a cosmetic problem — it is two
   buttons that do different things, one of which is covered. The engine also
   sets it inline (see runSectionBreak), so the class and the inline style have
   to agree; this rule is what puts it back when the class is removed. */
.epqx-root .epqx-nav.epqx-nav-hidden {
  visibility: hidden !important;
  /* transition:none matters. Something in the cascade transitions `all` on
     this row, and `visibility` is a DISCRETE animatable property: with a
     transition attached it keeps reporting "visible" until the flip point, so
     the row can still be hit-testable and readable for the length of that
     transition. Under reduced motion, where the duration is forced to 1ms,
     it was observed never flipping at all. Taking the transition off the
     hidden state makes hiding immediate and unambiguous. */
  transition: none !important;
}

/* The heading takes focus so a screen reader says which section has been
   reached. It is not a control, and it is focused programmatically rather
   than tabbed to, so it draws no ring — exactly as every real screen heading
   behaves here (see focusScreenStart). The visible focus target on this
   divider is the Continue button below it. */
.epqx-root .epqx-sectionbreak-title:focus,
.epqx-root .epqx-sectionbreak-title:focus-visible { outline: none; }

/* Optional artwork. The frame reserves its space before the file decodes,
   so the card cannot shift as it loads, and `contain` means an
   illustration is scaled, never cropped into meaning something else. */
.epqx-root .epqx-sectionbreak-art {
  /* Width and height are both stated, rather than one width plus
     aspect-ratio. As a flex item the frame's automatic minimum size is its
     CONTENT's minimum height, and the illustrations are thousands of pixels
     tall — so an aspect-ratio box grew to 388px instead of staying square and
     the reserved space was wrong. `min-height: 0` plus a stated height cannot
     be talked out of the size it reserves. */
  --epqx-break-art: min(220px, 42vw);
  width: var(--epqx-break-art);
  height: var(--epqx-break-art);
  min-width: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.epqx-root .epqx-sectionbreak-img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

@media (max-width: 600px) {
  .epqx-root .epqx-sectionbreak-inner { gap: 12px; padding: 18px; }
  .epqx-root .epqx-sectionbreak-art { --epqx-break-art: min(150px, 38vw); }
  .epqx-root .epqx-sectionbreak-title { font-size: clamp(21px, 6vw, 28px); }
}

/* Reduced motion: the engine does not build the card at all on this path,
   so there is nothing to animate. These rules exist so that a card put on
   screen by any other route still cannot move. */
@media (prefers-reduced-motion: reduce) {
  .epqx-root .epqx-sectionbreak,
  .epqx-root .epqx-sectionbreak.is-out {
    animation: none !important;
    transform: none !important;
  }
}

/* =====================================================================
   v1.0.112 — THE VALIDATION WARNING COVERS THE PAGE
   ---------------------------------------------------------------------
   The warning overlay is now portaled to <body> (see epqx-engine.js), so
   it is a FIXED, full-viewport backdrop instead of an absolute box inside
   the questionnaire's own window. Everything behind it dims, which is
   what a question that has to be answered should look like.

   Being outside `.epqx-root` has two consequences, both handled here:
   the design tokens do not resolve (so every value is literal), and the
   isolation layer at the top of this file does not reach it (so the type
   guard is repeated, scoped to this component only).
   ===================================================================== */
.epqx-warn-overlay {
  position: fixed;
  inset: 0;
  border-radius: 0;
  /* Above the section menu (2147483000), below a Turnstile challenge
     (2147483600) — a challenge must always stay reachable. */
  z-index: 2147483200;
  padding: 24px;
  background: rgba(20, 24, 31, 0.62);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

/* Host-theme guard for the portaled box, matching §1-§3b inside the root. */
.epqx-warn-overlay,
.epqx-warn-overlay .epqx-warn,
.epqx-warn-overlay .epqx-warn-msg,
.epqx-warn-overlay .epqx-warn-confirm,
.epqx-warn-overlay .epqx-warn-edit {
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif !important;
  font-style: normal !important;
  text-transform: none !important;
  text-decoration: none !important;
  letter-spacing: normal !important;
  box-sizing: border-box !important;
}
.epqx-warn-overlay .epqx-warn-msg { text-align: left !important; }

/* The page behind must not scroll away underneath the warning. Applied by
   the engine only while the overlay is open. */
.epqx-warn-open { overflow: hidden !important; }

/* =====================================================================
   v1.0.113 — ONE ILLUSTRATION SIZE ACROSS THE QUESTIONNAIRE
   ---------------------------------------------------------------------
   Every screen illustration used to carry its own width (120, 260, 320,
   360, 380…), so the same family photograph was a different size on
   three consecutive screens. They now share one box.

   "The same size" has to mean the same BOX, not the same pixels: the
   illustrations range from 4725x8334 (tall) to 1884x1545 (wide), so
   forcing identical rendered dimensions would either stretch them or crop
   them, and both are worse than the inconsistency. Each one is scaled to
   fit inside the box and centred in it, so the footprint is identical on
   every screen and nothing is distorted.

   The box is reserved whether or not the file has decoded, so a screen
   does not reflow as its picture arrives.
   ===================================================================== */
.epqx-root .epqx-illus {
  width: 100%;
  max-width: var(--epqx-illus-w, 260px);
  max-height: var(--epqx-illus-h, 460px);
  height: auto;
  object-fit: contain;
  display: block;
  margin: 0 auto;
}

/* The two Your Details side illustrations keep their own hover treatment;
   only their SIZE comes from the shared box now. */
.epqx-root .epqx-couple-img.epqx-illus,
.epqx-root .epqx-assets-img.epqx-illus {
  max-width: var(--epqx-illus-w, 260px);
  max-height: var(--epqx-illus-h, 460px);
}

@media (max-width: 900px) {
  .epqx-root .epqx-illus {
    max-width: min(var(--epqx-illus-w, 260px), 42vw);
    max-height: min(var(--epqx-illus-h, 460px), 46vh);
  }
}
@media (max-width: 640px) {
  .epqx-root .epqx-illus {
    max-width: min(var(--epqx-illus-w, 260px), 70vw);
    max-height: min(var(--epqx-illus-h, 460px), 40vh);
  }

  /* PHONES: side illustrations (v1.0.120)
     -------------------------------------
     The two Your Details pictures sit BESIDE a form on a wide screen and
     ABOVE it on a phone, where every pixel they take is a pixel of form the
     donor has to scroll past. 70vw/40vh is a sensible ceiling for a picture
     that is the point of the screen; it is too generous for one that is
     decorating a form. Measured at 390x844 the couple rendered 260x338 —
     two fifths of the viewport before the first field.

     This is now the ONLY place that decides their phone size, and it needs
     no !important to be so: at (0,3,0) it outranks the (0,2,0) rule above
     and the 900px rule on specificity, and the one rule that DID outrank it
     — `.epqx-img { max-height: 210px !important }` in the 600px isolation
     block — no longer matches these two elements. Nothing is being shouted
     down; the conflict was removed instead. */
  .epqx-root .epqx-couple-img.epqx-illus,
  .epqx-root .epqx-assets-img.epqx-illus {
    max-width: min(150px, 42vw);
    max-height: min(200px, 24vh);
  }
}

/* =====================================================================
   v1.0.113 — THE CONFIRMATION POPUP
   ---------------------------------------------------------------------
   White, page-wide, a large green tick on the left and the message in
   dark grey beside it. The counterpart to the red validation warning, and
   built the same way: portaled to <body>, fixed, literal values (the
   design tokens do not resolve out here) and its own type guard.

   Save & Resume used to confirm itself on the small status line under the
   questionnaire, which is easy to miss for something the donor
   deliberately asked for.
   ===================================================================== */
.epqx-notice-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(20, 24, 31, 0.62);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  box-sizing: border-box;
}

.epqx-notice-overlay .epqx-notice {
  display: flex;
  align-items: flex-start;
  gap: 22px;
  width: min(640px, 96%);
  background: #ffffff;
  border-radius: 22px;
  padding: 32px 36px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
  box-sizing: border-box;
}

/* The tick. A shape, sized to be the first thing seen. */
.epqx-notice-overlay .epqx-notice-mark {
  flex: 0 0 auto;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  background: #e8f6ec;
  color: #10702f;
  font-size: 40px;
  font-weight: 900;
  line-height: 68px;
  text-align: center;
}

.epqx-notice-overlay .epqx-notice-body { flex: 1 1 auto; min-width: 0; }

.epqx-notice-overlay .epqx-notice-msg {
  color: #33404f;                 /* dark grey, 8.4:1 on white */
  font-size: clamp(17px, 1.6vw, 21px);
  font-weight: 700;
  line-height: 1.45;
}

.epqx-notice-overlay .epqx-notice-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 22px;
}

/* Host-theme guard: this box lives outside .epqx-root, so §1-§3b at the top
   of this file cannot reach it. */
.epqx-notice-overlay,
.epqx-notice-overlay .epqx-notice,
.epqx-notice-overlay .epqx-notice-msg,
.epqx-notice-overlay .epqx-notice-mark,
.epqx-notice-overlay .epqx-notice-ok {
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif !important;
  font-style: normal !important;
  text-transform: none !important;
  text-decoration: none !important;
  letter-spacing: normal !important;
  box-sizing: border-box !important;
}
.epqx-notice-overlay .epqx-notice-msg { text-align: left !important; }

/* The button is drawn here rather than inherited, because .epqx-btn lives
   under .epqx-root and this popup does not. */
.epqx-notice-overlay .epqx-notice-ok {
  border: 0;
  border-radius: 999px;
  background: #101828;
  color: #ffffff;
  font-weight: 800;
  font-size: 16px;
  padding: 12px 26px;
  cursor: pointer;
}
.epqx-notice-overlay .epqx-notice-ok:hover { opacity: 0.92; }
.epqx-notice-overlay .epqx-notice-ok:focus-visible {
  outline: 2px solid #1f4e79;
  outline-offset: 3px;
}

@media (max-width: 600px) {
  .epqx-notice-overlay .epqx-notice { flex-direction: column; align-items: center; text-align: center; gap: 16px; padding: 26px 22px; }
  .epqx-notice-overlay .epqx-notice-msg { text-align: center !important; }
  .epqx-notice-overlay .epqx-notice-actions { justify-content: center; }
}

/* =====================================================================
   v1.0.114 — NO ORPHAN LINES
   ---------------------------------------------------------------------
   The engine wraps the last two words of every heading and paragraph
   (plus any trailing tooltip badge) in this span, so the last line always
   carries at least two real words. See epqxNoOrphan().
   ===================================================================== */
.epqx-root .epqx-nobreak { white-space: nowrap; }

/* A long single word inside the bound tail must still be allowed to break
   rather than push the card sideways — the engine reverts the binding when
   it overflows, and this is the second line of defence. */
.epqx-root .epqx-nobreak { overflow-wrap: break-word; }

/* Headings and paragraphs take the full width of the container they sit in,
   even when that container centres its children. A column layout with
   `align-items: center` shrink-wraps a heading to its own text, which is how
   "What Will Your Legacy Be?" ended up in a 465px box inside a 545px column
   and could not be un-stranded without overflowing. `align-self: stretch`
   only touches the cross axis of a flex column, so it gives the heading the
   room it should have had and changes nothing about where the text sits —
   that is still governed by text-align. */
.epqx-root .epqx-heading,
.epqx-root .epqx-text { align-self: stretch; }

/* Headings and paragraphs use the full width of the container they are in.
   The 640px reading measure was capping paragraphs at roughly two thirds of
   a 1040px card, which forced wraps that would not otherwise happen — and
   every avoidable wrap is another chance to strand a word. */
.epqx-root .epqx-text { max-width: none; }

/* Let the browser help as well where it can: text-wrap:pretty asks it to
   avoid short last lines on its own. It is ignored by browsers that do not
   support it, which is why the engine does the work rather than relying on
   this. */
.epqx-root .epqx-heading,
.epqx-root .epqx-text {
  text-wrap: pretty;
}

/* =====================================================================
   v1.0.120 — MOBILE-ONLY CORRECTIONS
   ---------------------------------------------------------------------
   640px, not 600px, because that is where the ENGINE switches: see
   DEFAULT_BREAKPOINTS = { tablet: 1024, mobile: 640 } in epqx-engine.js.
   The older phone rules in this file use 600, which leaves a 600-640 band
   where the engine has already switched to the mobile LAYOUT but the phone
   CSS has not — a device at 620px got the mobile column arrangement with
   desktop sizing. New rules match the engine so the two agree, and 640 is
   exactly where tablet begins, so nothing here can reach a tablet or a
   desktop.
   ===================================================================== */
@media (max-width: 640px) {

  /* ---- Fields fill the card (Task 2) --------------------------------
     The narrow fields on Your Details card 2 are not a CSS width problem:
     every input is already width:100%. The container holding them is what
     shrank, and the reason is in the engine rather than the stylesheet.

     atBreakpoint() merges a breakpoint override ONTO the base layout:

         merged.layout = Object.assign({}, node.layout, over.layout)

     Card 2's desktop layout is { grid, "1fr 380px", align:"center" } and
     its mobile override is { flex, column, gap:20 } — which says nothing
     about `align`. So align:"center" survives the merge, applyLayout
     writes align-items:center onto a COLUMN flex container, and its
     children size to their content instead of the card. Measured at
     390px: fields 234px wide inside a 358px card, while card 1's fields
     were full width.

     Fixed on the child rather than the parent, because the parent's
     align-items is written inline by the engine and a stylesheet cannot
     outrank that. align-self on the child can. Only containers are
     stretched — illustrations and card groups are not .epqx-container, so
     anything deliberately centred stays centred. */
  .epqx-root .epqx-content .epqx-container.epqx-stack { align-self: stretch; }

  /* A grid child that is a form field should fill its single mobile
     column rather than sit at its content width. */
  .epqx-root .epqx-content .epqx-field { min-width: 0; }
  .epqx-root .epqx-content .epqx-input,
  .epqx-root .epqx-content .epqx-select,
  .epqx-root .epqx-content .epqx-textarea { max-width: none; min-width: 0; }

  /* The file-upload row was the ONE thing on the whole questionnaire that
     produced page-level horizontal scrolling on a phone, and it did so in
     v1.0.119 too. A native <input type="file"> carries an intrinsic width
     of roughly 289px in Chromium; with the paperclip, the gap and the
     UPLOAD button beside it the row measured 464px inside a 354px column
     at 390px, and the page scrolled 427px wide. Letting the row wrap and
     the native control shrink fixes it without touching the control's
     appearance anywhere above 640px. */
  .epqx-root .epqx-fileupload-row { flex-wrap: wrap; gap: 8px; }
  .epqx-root .epqx-fileupload-row input[type="file"] {
    flex: 1 1 60%;
    min-width: 0;
    max-width: 100%;
  }
  .epqx-root .epqx-fileupload-btn { flex: 0 0 auto; }

  /* ---- Two-choice cards: horizontal, square, nearly full width -------
     (Tasks 3, 4 and 5.) The class is put on the group by the schema; the
     two-column grid is a schema responsive.mobile layout, because that is
     a layout decision and the schema owns layout. What lives here is
     everything that is the same for all twelve of them.

     The group itself has to occupy the screen's full width before its two
     columns mean anything: its parent is a flex column with
     align-items:center written INLINE by the engine, which makes every
     child shrink-wrap. align-self on the child is the one thing that can
     outrank an inline align-items on the parent. */
  .epqx-root .epqx-two-choice {
    align-self: stretch;
    justify-self: stretch;
  }

  /* min-width:0 on the cards is what stops two grid children with wide
     labels from pushing the row past the viewport. */
  .epqx-root .epqx-two-choice > .epqx-card-opt {
    min-width: 0;
    width: auto;
    aspect-ratio: 1 / 1;
    padding: 10px 8px;
    justify-content: center;
  }

  /* The picture inside a square card must NOT become square with it.
     !important is needed here and is not decoration: the engine writes
     `imgSize` as an inline width AND height (see the radioCards builder,
     `im.style.width = sz + "px"; im.style.height = sz + "px"`), and the
     three Critical Decisions groups pass imgSize:220. Inline beats any
     selector, so the only way to hand the illustration its aspect ratio
     back on a phone is to override both axes. It also has to outrank the
     existing phone rule `.epqx-card-img { width:118px !important }` in the
     600px block above, which is !important for exactly the same reason.
     object-fit:contain then letterboxes it inside whatever space is left
     above the label. */
  .epqx-root .epqx-two-choice .epqx-card-img {
    width: auto !important;
    height: auto !important;
    max-width: 100% !important;
    max-height: 62% !important;
    object-fit: contain;
    margin: 0 auto;
  }

  /* Glyph pairs (the check and cross) scale with the card instead of
     carrying a fixed desktop size. */
  .epqx-root .epqx-two-choice .epqx-card-glyph {
    font-size: clamp(30px, 13vw, 56px);
    line-height: 1;
  }

  /* "Someone Else" is the longest label on any of these cards and has to
     fit a half-width card at 320px without becoming unreadable. */
  .epqx-root .epqx-two-choice .epqx-card-label {
    font-size: clamp(14px, 4vw, 17px);
    line-height: 1.2;
    text-align: center;
    overflow-wrap: break-word;
    hyphens: auto;
  }

  /* ---- Alternate-representatives modal (Additional issue 7) ----------
     Three measured phone defects, all of them present in v1.0.119:

     1. The box itself was the scroll container, and the close "x" is an
        absolutely-positioned child of it — so the x scrolled away with the
        content. At 320px the panel is 2184px tall against an 824px box, and
        after one flick the only way out of the dialog was the browser Back
        button. The modal already renders as box > [close, body, footer], so
        moving the scroll onto .epqx-modal-body pins BOTH the close control
        and the Continue footer without touching the markup.
     2. max-height was 96% of the OVERLAY, and the overlay is as tall as the
        questionnaire shell, not the window — measured 890px of modal inside
        a 700px viewport. Capping against the viewport fixes that; dvh is
        the mobile-browser-chrome-aware unit and vh is the fallback for
        engines that do not know it.
     3. 36px of horizontal padding inside a 261px box left the fields 189px
        wide. 18px gives them 225px — a third more room — and still reads as
        a padded dialog.
     4. The overlay is `position:absolute; inset:0` on the questionnaire
        shell and centres its child, so on a phone — where the shell is much
        taller than the window — centring pushed the dialog's lower half
        below the fold. Top-aligning it on phones puts the whole dialog
        where the donor is already looking.

     The overlay is NOT re-parented here: moving these two dialogs to the
     page level is a separate, already-flagged decision and is deliberately
     out of scope for a mobile pass. */
  .epqx-root .epqx-modal-overlay { align-items: flex-start; padding: 16px; }
  .epqx-root .epqx-modal {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 26px 18px 18px;
    max-height: calc(100vh - 96px);
    max-height: calc(100dvh - 96px);
  }
  .epqx-root .epqx-modal.epqx-modal-alt-reps {
    max-height: calc(100vh - 96px);
    max-height: calc(100dvh - 96px);
  }
  .epqx-root .epqx-modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .epqx-root .epqx-modal-footer { flex: 0 0 auto; }
  .epqx-root .epqx-modal-close { top: 8px; right: 8px; }
}

/* Touch-device hover (additional mobile issue 6): NO CHANGE NEEDED, and
   this note exists so the next person does not add one.

   The inverse guard `@media (hover: none), (pointer: coarse)` above (P4.6,
   added v1.0.107) already neutralises every hover lift and shadow —
   .epqx-card-opt, .epqx-couple-img, .epqx-btn, the pills, the entire-estate
   card overrides. Measured on an emulated coarse-pointer device against
   both v1.0.119 and v1.0.120: a hovered card computes transform:none in
   both. A draft of this pass added a second, duplicate block here; it was
   removed after that measurement rather than left in as decoration.

   The one hover property that DOES still apply on a coarse pointer is the
   gold border-color, which comes from the host-theme isolation rule in P4.6
   and is !important. It is deliberately left alone: a finger cannot produce
   that state without also selecting the card, and a selected card is gold
   anyway, so there is nothing visible to fix and suppressing it would mean
   another !important fighting an isolation rule. (v1.0.120) */

/* =====================================================================
   v1.0.124  CIRCULAR CHOICE ART — a real ring that can turn gold
   =====================================================================
   Every circular choice illustration (Spouse / Church / Other on the
   entire-estate screens, and the three on Rest & Residue step 7) carries
   its grey ring PAINTED INTO THE PNG. Measured: the ring is the outer
   5.8% of the radius on the @4x set and 7.9% on Married-Couple, colour
   #e6e7e8. Nothing in CSS drew it, so nothing in CSS could recolour it —
   which is why selecting a card only ever produced a faint rectangular
   halo and never the gold circle the design asks for.

   The engine now wraps that art in .epqx-card-media. The wrapper is a
   square with a 50% radius and `overflow: hidden`, so it clips the art to
   a circle; the art is scaled just past the clip so the baked ring falls
   outside it and disappears. The visible ring is then the wrapper's own
   border — grey at rest, gold when the card is selected.

   Scale maths: the baked ring's inner edge sits at 0.471 of the box on the
   @4x files and 0.460 on Married-Couple. To push it outside a clip of
   radius 0.5 the art must scale by at least 0.5 / 0.460 = 1.087, so 1.10
   clears every one of them with a little to spare. That crops the outer
   ~4.5% of each illustration, which is empty margin inside the ring.
   --------------------------------------------------------------------- */
.epqx-root .epqx-card-media {
  display: block;
  overflow: hidden;
  box-sizing: border-box;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 3px solid var(--epqx-line, #d0d5dd);
  background: #fff;
  transition: border-color var(--epqx-dur-select, 180ms) var(--epqx-ease, ease),
              box-shadow var(--epqx-dur-select, 180ms) var(--epqx-ease, ease);
}
/* The size lives on the wrapper now, so the image fills it. !important is
   needed against the 600px isolation rule `.epqx-card-img { width: 118px
   !important }`, which would otherwise shrink the art inside a full-size
   ring on a phone. */
.epqx-root .epqx-card-media .epqx-card-img {
  width: 100% !important;
  height: 100% !important;
  display: block;
  object-fit: contain;
  transform: scale(1.10);
}
/* THE point of all of the above. The chosen ring is a shade heavier than the
   grey one so the difference reads as a state and not just a hue — the
   selected card is never told apart by colour alone. */
.epqx-root .epqx-card-opt.epqx-card-bare.is-selected .epqx-card-media {
  border-width: 4px;
  border-color: var(--epqx-gold, #d8ae66);
  box-shadow: var(--epqx-ring-selected, 0 0 0 4px rgba(216, 174, 102, 0.20));
}
.epqx-root .epqx-card-opt.epqx-card-bare:focus-within .epqx-card-media,
.epqx-root .epqx-card-opt.epqx-card-bare:hover .epqx-card-media {
  border-color: var(--epqx-gold, #d8ae66);
}
/* The old rectangular halo is now redundant — the ring says it better and
   follows the shape of the artwork. The check badge is untouched. */
.epqx-root .epqx-card-opt.epqx-card-bare.is-selected {
  box-shadow: none;
}
/* Phones: the ring shrinks with the art, mirroring what the 600px block
   has always done to .epqx-card-img. */
@media (max-width: 600px) {
  .epqx-root .epqx-card-media { width: 118px !important; height: 118px !important; }
}

/* =====================================================================
   v1.0.125  Two host-theme and hover corrections found on staging.
   ===================================================================== */

/* 1. THE PROGRESS RAIL BROKE INTO FLOATING STUBS
   ----------------------------------------------
   Reported as "a gap in the progress bar": the gold fill of the section
   being worked on floated in the middle of its track with grey either
   side, instead of running from the left edge.

   It is a host-theme collision, which is why it never appeared in
   testing. `.epqx-progress-seg-fill` is a block whose width is set to a
   percentage; a theme rule as ordinary as `div { margin: 0 auto }`
   therefore centres it. Reproduced exactly: injecting that one
   declaration insets a 38.9% fill by 37px inside a 121px segment, and
   every empty segment's zero-width fill by 61px. The percentages were
   always right — 100% / 100% / 38.9% / 0 — only their position was
   wrong.

   Pinning the fill to the left is all that is needed, and it belongs in
   the isolation layer with the rest of the host-theme defences. */
.epqx-root .epqx-progress-seg-fill {
  margin: 0 !important;
  float: none !important;
  position: relative !important;
  left: 0 !important;
  right: auto !important;
  display: block !important;
  min-width: 0 !important;
  max-width: 100% !important;
}
/* The track itself, for the same reason: a centred or floated segment
   would break the rail into an uneven row. */
.epqx-root .epqx-progress-seg {
  margin: 0 !important;
  float: none !important;
}

/* 2. HOVER DROP SHADOW ON THE CIRCULAR CHOICES
   -------------------------------------------
   `.epqx-card-opt:hover` in the isolation layer adds a lift and a
   24px-blur shadow with !important. On a framed card that reads as the
   card lifting. On a BARE card there is no card to lift, so the shadow
   drew a rectangular ghost — with the rounded white box behind it —
   around a circular picture.

   On bare cards the ring is now the whole hover story: it goes gold (see
   the .epqx-card-media rules above) and nothing else moves. The SELECTED
   state is untouched. */
.epqx-root .epqx-card-opt.epqx-card-bare:hover,
.epqx-root .epqx-card-opt.epqx-card-bare:focus-within {
  box-shadow: none !important;
  background: transparent !important;
  background-color: transparent !important;
  transform: none !important;
  border-color: transparent !important;
}

/* ====================================================================
   v1.0.130 — ADMINISTRATOR TEST-FILL STRIP
   --------------------------------------------------------------------
   Never sent to a donor: the script that builds this strip is enqueued
   only for users who can manage_options, so on a donor's page these
   rules match nothing.

   The strip is appended to document.body, which puts it OUTSIDE
   .epqx-root and therefore outside the isolation layer that protects
   the questionnaire from the host theme. It is styled the same way the
   other body-portaled node (the section menu, .epqx-toc-menu above) is:
   every property it depends on is stated, including font-family, so
   nothing is inherited from whatever the theme has set on body.

   Deliberately grey rather than gold. It is scaffolding, and it should
   not read as part of the questionnaire in a screenshot.
   ==================================================================== */
.epqx-testbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 2147482000;                      /* under the section menu / warnings */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  margin: 0;
  padding: 8px 12px;
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  background: #1f2430;
  border-top: 1px solid #333a49;
  color: #e6e9ef;
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  font-size: 13px;
  line-height: 1.3;
  text-transform: none;
  letter-spacing: 0;
}
.epqx-testbar-tag {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  color: #99a2b3;
  white-space: nowrap;
}
.epqx-testbar-select {
  flex: 0 1 auto;
  max-width: 260px;
  box-sizing: border-box;
  margin: 0;
  padding: 5px 8px;
  background: #2b3140;
  color: #e6e9ef;
  border: 1px solid #3d4557;
  border-radius: 5px;
  font-family: inherit;
  font-size: 13px;
  height: auto;
}
.epqx-testbar-btn {
  flex: 0 0 auto;
  box-sizing: border-box;
  margin: 0;
  padding: 6px 12px;
  background: #384052;
  color: #e6e9ef;
  border: 1px solid #4a5468;
  border-radius: 5px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  text-transform: none;
  cursor: pointer;
  transition: background 120ms cubic-bezier(0.22, 1, 0.36, 1);
}
.epqx-testbar-btn:hover { background: #454f66; }
.epqx-testbar-btn:focus-visible { outline: 2px solid #c79a52; outline-offset: 2px; }
.epqx-testbar-btn[disabled] { opacity: 0.55; cursor: default; }

/* The third button creates real records — an archive entry, email, a HubSpot
   contact, a Dropbox bundle — so it does not look like the two that only fill
   fields. Red at rest; when armed (first press) it fills solid and says so,
   because "press again and it is real" has to be unmistakable. Colour is not
   carrying that meaning alone: the label changes too. */
.epqx-testbar-btn-danger {
  border-color: #8d3a34;
  background: #4a2422;
  color: #f2d6d2;
}
.epqx-testbar-btn-danger:hover { background: #5d2c29; }
.epqx-testbar-btn-danger.is-armed {
  background: #b03c31;
  border-color: #d85447;
  color: #fff;
}
.epqx-testbar-btn-danger.is-armed:hover { background: #c04437; }
.epqx-testbar-status {
  flex: 1 1 180px;
  min-width: 0;
  color: #aeb6c4;
  font-size: 12px;
}
.epqx-testbar-hide {
  flex: 0 0 auto;
  margin: 0;
  padding: 2px 8px;
  background: transparent;
  color: #99a2b3;
  border: 0;
  border-radius: 4px;
  font-family: inherit;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.epqx-testbar-hide:hover { color: #fff; background: rgba(255,255,255,0.10); }
.epqx-testbar-hide:focus-visible { outline: 2px solid #c79a52; outline-offset: 2px; }

/* The strip is fixed, so without this it would sit on top of whatever is
   at the bottom of the page — which at the bottom of a questionnaire
   screen is the Continue button. The class is added to .epqx-root only
   while the strip exists and removed when it is dismissed, so the
   donor-facing layout is never padded. */
.epqx-root.epqx-has-testbar { padding-bottom: 78px; }

@media (max-width: 640px) {
  .epqx-testbar { gap: 8px; padding: 7px 10px; }
  .epqx-testbar-select { flex: 1 1 100%; max-width: none; }
  .epqx-testbar-btn { flex: 1 1 auto; }
  .epqx-testbar-status { flex: 1 1 100%; }
  .epqx-root.epqx-has-testbar { padding-bottom: 132px; }
}

@media (prefers-reduced-motion: reduce) {
  .epqx-testbar-btn { transition: none; }
}
