
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
/* ⚑ iOS STOPS CHOOSING OUR TYPE SIZES. Stephen 2026-08-26: "yes, iOS is our
   platform and we should make verdeaux look consistent on that platform (no
   surprises)."
   WebKit defaults `text-size-adjust` to `auto` and INFLATES text by a factor
   derived from its block's width, so identical declarations rendered at
   different sizes depending on how wide their container happened to be — the
   plan sheet's alert read ~16px from a declared 9px while the stop labels
   beside it, also 9px, stayed small.
   ⚑ AND IT CANNOT SHIP ALONE: turning inflation off without raising the
   declared sizes would make the app SMALLER on iOS, not more consistent. The
   phone-side tokens are raised in the same change, just below. */
html{scroll-behavior:smooth;font-size:16px;
  -webkit-text-size-adjust:100%;text-size-adjust:100%}

/* ══ Metric-matched fallbacks (2026-08-07) ═══════════════════════════════════
   The three webfonts load with display=swap, so every first paint renders in
   a system font and then re-renders. The stack said `Georgia, serif` and
   `sans-serif`, which are nowhere near the fonts they stand in for — Georgia
   sets Cormorant's text 14% WIDER, so display headings wrapped to a different
   number of lines and the page jumped when the real font arrived.

   These faces are the same local fonts with their metrics bent to match. The
   numbers are MEASURED, not estimated: text rendered at 100px in the real font
   and in the fallback, width and line box compared, size-adjust set to the
   width ratio and ascent/descent set to the target's own (divided by
   size-adjust, which scales overridden metrics too). Residual error after, at
   100px: 0% on width and 0% on line height for all three.

   Local sources are deliberate. `local(Helvetica)` measures identically to
   Arial but does NOT honour ascent-override on macOS — it came back 14% tall
   while Arial, Georgia, Courier New and Times all matched the spec exactly. On
   a machine without the named font the face simply never loads and the stack
   falls through to the plain family it always used, so this is strictly better
   than what it replaces, never worse.

   Re-measure whenever a webfont changes: scripts/font-metrics-measure.js */
@font-face{font-family:"DM Sans Fallback";src:local("Arial");size-adjust:100.32%;ascent-override:98.69%;descent-override:30.90%;line-gap-override:0%}
@font-face{font-family:"Cormorant Fallback";src:local("Georgia");size-adjust:87.54%;ascent-override:105.09%;descent-override:33.13%;line-gap-override:0%}
@font-face{font-family:"DM Mono Fallback";src:local("Courier New");size-adjust:99.98%;ascent-override:99.02%;descent-override:31.01%;line-gap-override:0%}

:root {
 --cream: #FAF7F2;
 --cream-d: #F0EBE1;
 --warm: #F5F0E8;
 --white: #FEFCF8;
 --green: #2C4A3E;
 --green-mid: #3D6355;
 --green-lt: #5A8C7A;
 --green-pale: #EAF0ED;
 --gold: #C8A96E;
 --gold-lt: #E8D5A8;
 --gold-deep: #A07840;
 --gold-pale: rgba(200,169,110,.08);
 --parchment: #F2EBE0;
 --rose: #C97B6A;
 --sage: #5A8C7A;
 --plum: #7B5EA8;
 --amber-risk: #C97B3A;
 --danger: #B94040;
 /* 2026-08-05 (Stephen) — guide-card status pills: ONE geometry, five tones.
   These were sized for a 1-character "P", so real words clipped — "Planned"
   rendered as "ann". Every state now shares this rule AND a min-width, so a
   column of pills down the guide grid is one consistent width (Stephen: "all
   pills should be the same size so we need a naming convention that works on a
   reasonable size pill"). That constraint is what set the vocabulary: the
   longest label is 8 characters — BOOK NOW / MAR 2026 — and min-width is sized
   to it, which is NARROWER than the "by Mar 2026" it replaces, so nothing in
   the grid gets tighter than it already was.

   Tones — filled = something is true of this category, outline = nothing to do:
     Booked    settled green
     Book now  gold. Attention, NOT alarm: there is deliberately no red and no
               overdue state anywhere (Stephen: "we are reducing stress not
               creating it"). A window that opened months ago still reads
               "Book now" — the next action, never a scold.
     MAR 2026  muted outline — a window that opens later
     Anytime   muted outline — no lead time exists for this category at all
     Add       dashed outline — an empty slot you can fill, not a status */
.guide-budgeted.is-booked,
.guide-budgeted.is-anytime,
.guide-partial.is-due,
.guide-partial.is-dated,
.guide-skipped.is-add{
  display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;
  width:auto;min-width:62px;height:auto;padding:2px 7px;border-radius:20px;opacity:1;
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.54rem;letter-spacing:.06em;
  text-transform:uppercase;line-height:1.5;white-space:nowrap;font-weight:500}
.guide-budgeted.is-booked{background:var(--green-pale,#EAF0EC);color:var(--green,#2C4A3E);border:1px solid rgba(44,74,62,.18)}
.guide-partial.is-due{background:var(--gold-pale,#F4ECD8);color:var(--gold-deep,#A07840);border:1px solid rgba(200,169,110,.30)}
.guide-partial.is-dated,
.guide-budgeted.is-anytime{background:transparent;color:var(--text-muted,#88928d);border:1px solid rgba(44,74,62,.12)}
.guide-skipped.is-add{background:transparent;color:var(--ink-faint,#9a9a94);border:1px dashed rgba(44,74,62,.22)}
@media (max-width:560px){
  .guide-budgeted.is-booked,
  .guide-budgeted.is-anytime,
  .guide-partial.is-due,
  .guide-partial.is-dated,
  .guide-skipped.is-add{font-size:.5rem;padding:2px 6px;min-width:57px}
}
/* 2026-08-05 (Stephen) — the Compare rule line. Sits above the table in the DEMO
   and states how we ranked, plus what the locked cells are. Quiet card, not a
   banner: it should read as the grid explaining itself, not as an ad. The lock
   line is bronze so it ties to the 🔒 in the cells it describes. */
.vx-cmp-rule{margin:0 0 16px;padding:13px 15px;background:rgba(44,74,62,.035);border:1px solid rgba(44,74,62,.09);border-radius:12px}
.vx-cmp-rule-lead{margin:0;font-size:.84rem;line-height:1.55;color:#4a4a4a}
.vx-cmp-rule-lead strong{color:var(--green,#2C4A3E);font-weight:600}
.vx-cmp-rule-lock{margin:8px 0 0;padding-top:8px;border-top:1px solid rgba(44,74,62,.08);font-size:.8rem;line-height:1.5;color:var(--gold-deep,#A07840)}
.vx-cmp-rule-lock strong,.vx-cmp-rule-lock em{color:var(--gold-deep,#A07840)}
.vx-cmp-rule-lock em{font-style:italic}
@media (max-width:560px){.vx-cmp-rule{padding:11px 12px;margin-bottom:13px}.vx-cmp-rule-lead{font-size:.82rem}.vx-cmp-rule-lock{font-size:.78rem}}
/* 2026-05-14 — Demo Mode pill. Deeper bronze for sandbox-state
    differentiation. Distinct from --gold-deep (#A07840) so the pill
    reads as "different mode" rather than just "another accent." */
 --bronze: #7A5A2A;
 --ink: #1C1C1C;
 --charcoal: #1C1C1C;
 --ink-mid: #4A4A4A;
 --text-mid: #4A4A4A;
 --ink-muted: #4A4A4A;
 --ink-faint: #7A7A7A;
 --text-muted: #7A7A7A;
 --border: rgba(44,74,62,.1);
 --border-g: rgba(200,169,110,.25);
 --border-strong: rgba(200,169,110,.5);
 --radius: 12px;
 --radius-lg: 20px;
 /* THE MONEY COLUMN. Every editable $ field is this wide, whatever is in it.
    2026-08-07 (Stephen): "please make everything 9 digits so there is room
    (always)" — nine, not the seven first asked for, so no line can ever be the
    one that does not fit. Measured, not guessed: at --fs-amount in DM Sans 500
    tabular, "999999999" renders 81.6px and ten digits 90.7px, so 86px holds nine
    with room for the caret and degrades to scrolling rather than clipping beyond.
    A field sized from its own value cannot grow to hold what is being typed into
    it, which is what made a long entry depend on a repaint to fit — and the
    repaint is what mangled it. */
 --money-field-w: 86px;
 --ff-d: 'Cormorant Garamond', 'Cormorant Fallback', Georgia, serif;
 --ff-b: 'DM Sans', 'DM Sans Fallback', Arial, sans-serif;
 --ff-m: 'DM Mono', 'DM Mono Fallback', 'Courier New', monospace;
 /* 2026-07-28 (Stephen) — canonical TYPE SCALE tokens. Before this every size was an ad-hoc
    per-rule rem/px, which is why type drifted (dollars rendered in all 3 families at .6–2.2rem).
    Roles bind to these so the system is enforced, not hand-matched. See
    docs/2026-07-28-typography-system-proposal.md. Money = DM Sans, --fs-amount, weight 500, tabular,
    #33352f (the soft, single money face); DM Mono is retired from all functional dollars; Cormorant
    is reserved for display titles + the ONE hero 'wow' number per surface (Stephen's calls). */
 --fs-eyebrow: .62rem;
 --fs-caption: .78rem;
 --fs-amount: .9rem;
 --fs-body: 1rem;
 /* 2026-08-19 (Stephen) — THE PLAN'S TYPE SCALE, MEASURED OFF HIS OWN MOCK-UP.
    "Day headings are 14px, Trip fonts are 12px, Stops are 10px", and the
    spreadsheet agrees: level 0 is 14 (the day) and 12 (the trip), level 1 is 11
    (a stop's face), level 2 is 10 (its detail).
    An earlier note here flattened all of these to one size on a reading of
    "all the trip fonts the same" — that was about the FACE, not about the
    hierarchy, and flattening it cost the list its levels. Four sizes, named,
    so a later edit moves the scale rather than one line of it. */
 /* 2026-08-19 (Stephen), measured off his own card: "fonts should be two points
    smaller each detail so a Trip = 13p, Stops = 11p, editable details = 9p."
    Three steps, two points apart, named once — the day keeps 14 above them. */
 --fs-day:  .875rem;   /* 14px — the day heading */
 --fs-trip: .8125rem;  /* 13px — a trip's name, and + Add a trip */
 --fs-stop: .6875rem;  /* 11px — a stop's row: the two place names */
 --fs-stopdet: .5625rem;/* 9px — inside a stop: Leave by, From, To, Group */
 /* ⚑ EVERY EXPAND ARROW IN THE PLAN, AT ONE SIZE. Stephen 2026-08-27: "can we
    make the expand arrows on the Trip cards the same size as the new arrows on
    the stops?" So this is the plan's caret token, not the stop row's, and it was
    renamed from --fs-stopcaret the moment it stopped being about one row.
    A trip's caret carried .78rem and its ⚠ variant a THIRD size at .72rem, so
    one control changed size depending on whether the trip was tight.

    ⚑ THE ARROW HAS ITS OWN SIZE, AND IT IS THE ONLY THING THAT DOES.
    The caret was a hardcoded .72rem — not on his ladder at all, which sits at
    --fs-eyebrow .62, --fs-caption .78, --fs-amount .9, --fs-body 1.

    ⚑ AND IT NO LONGER SHARES WITH THE CLOCK. For one round they did, because he
    asked for exactly that — "the time fonts to match that sizing". Looking at
    it: "the arrow size is better but time is still too big - may we raise arrow
    one more font size but make the time fonts 1 size smaller for they are
    secondary data to the stop title." So they move in OPPOSITE directions and a
    shared token is now the wrong shape. The clock went back to --fs-stop, the
    stop name's own token; only the arrow keeps a size of its own.

    ⚑ SECONDARY IS CARRIED BY TINT, NOT BY BEING SMALLER THAN THE NAME. One rung
    under .9 is .78, which is what the name reads — dropping a second rung to
    .62 would put a time at 10px, and the times are already the muted half of
    the row with only a TYPED one in ink. That contrast is what makes them read
    as supporting the place rather than competing with it. */
 --fs-caret: .9rem;/* = --fs-amount — the arrow, one rung up again */
 --fs-cat-title: .9rem;   /* 2026-07-28 (Stephen): category titles = DM Sans, same size as the dollars (was Cormorant 1.4rem serif — unreadable on mobile) */
 --fs-section-title: clamp(1.5rem, 3vw, 2.2rem);
 --fs-page-title: clamp(2rem, 5vw, 3rem);
 --money-ink: #33352f;
}
/* ⚑ THE PHONE'S OWN SIZES, DECLARED RATHER THAN INFLATED. Scoped to the
   breakpoint where WebKit was doing this for us, so DESKTOP IS UNTOUCHED — it
   never autosized, and raising these globally would grow the plan sheet ~40% on
   a laptop for no reason.

   ⚑ AND THEY ARE THE BUDGET CARD'S TOKENS, NOT A GUESS. The first pass at this
   read the inflation off a screenshot and landed on 13px/15px; Stephen, on the
   phone: "all other fonts sizing are too big for the limited spacing." He had
   already answered this question on 2026-08-18 — "please make sure the style,
   fonts and font sizes are the same as the Budget card, for that is a simple
   design" — and the answer is written a few hundred lines below, over the stop
   block: four tokens and nothing else. A stop NAME is what the Budget line item
   is, and the detail box is labels:

     --fs-caption .78rem  values, names, the words you read
     --fs-eyebrow .62rem  labels above a field

   So these two stop tokens are those two, restated at the breakpoint where they
   have to be declared. Measuring a screenshot invented a scale; his own card
   already had one. */
@media (max-width:767px){
  :root{
    --fs-stopdet: .62rem;   /* = --fs-eyebrow — the labels inside a stop */
    --fs-stop:    .78rem;   /* = --fs-caption — the Budget line item exactly */
    --fs-caret: 1rem;   /* = --fs-body — "raise arrow one more font size" */
  }
}

body {
 font-family: var(--ff-b);
 background: var(--cream);
 color: var(--ink);
 min-height: 100vh;
 overflow-x: hidden;
 line-height: 1.6;
}
body::before {
 content: ''; position: fixed; inset: 0;
 background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.025'/%3E%3C/svg%3E");
 pointer-events: none; z-index: 0;
}

/* App header — matched to the home page #topnav (verdeaux-new-moon.netlify.app/)
 so navigating between home → app feels seamless: identical padding,
 backdrop opacity, blur, and logo size. */
header {
 position: fixed; top: 0; left: 0; right: 0; z-index: 900;
 display: flex; align-items: center; justify-content: space-between;
 /* 2026-05-13 — Dynamic Island / notch safe-area. The cream background
    bleeds to the device edge (status bar visually flows into the header),
    while the actual logo + auth buttons inset by env(safe-area-inset-top)
    so they sit cleanly below the island. On non-iOS browsers env() falls
    back to 0 and the header reads exactly as before. */
 padding: max(16px, calc(env(safe-area-inset-top, 0px) + 12px))
          max(48px, env(safe-area-inset-right, 48px))
          16px
          max(48px, env(safe-area-inset-left, 48px));
 background: rgba(250,247,242,1); /* 2026-07-21: dropped backdrop-filter. The bg is fully opaque so it blurred nothing, but on iPadOS WebKit a backdrop-filter layer swallows taps on descendants that paint OUTSIDE its box — which is why the account-menu dropdown options were unresponsive on iPad (Apple 2.1a rejection). Zero visual change. */
 border-bottom: 1px solid var(--border-g);
}
.logo { font-family: var(--ff-d); font-size: 1.45rem; font-weight: 500; letter-spacing: .04em; color: var(--green); text-decoration: none; }
.logo em { font-style: italic; color: var(--gold); }
/* Mirror home's .tnav-right pattern exactly */
.header-right { display: flex; align-items: center; gap: 10px; }
.header-greeting { font-size: .82rem; color: var(--text-mid); letter-spacing: .04em; font-family: var(--ff-b); }
.header-greeting[hidden] { display: none; }
.header-pill {
 appearance: none; -webkit-appearance: none;
 background: transparent;
 color: var(--gold, #C8A96E);
 border: 1.5px solid var(--gold, #C8A96E);
 padding: 8px 20px; border-radius: 999px;
 font-family: var(--ff-b); font-size: .875rem; font-weight: 500;
 letter-spacing: .02em; text-transform: none;
 text-decoration: none; cursor: pointer;
 /* 2026-05-14 — Pill-family transition canon: all .25s ease.
    Was a split (background .2s, transform .15s, color .2s). */
 transition: all .25s ease;
}
.header-pill:hover { background: var(--gold, #C8A96E); color: #fff; transform: translateY(-1px); }
.header-pill:focus-visible { outline: 2px solid var(--gold, #C8A96E); outline-offset: 3px; }
.header-pill.header-auth-btn.is-signed-in {
 background: var(--green, #2C4A3E);
 color: #fff;
 border: 1.5px solid var(--green, #2C4A3E);
}
.header-pill.header-auth-btn.is-signed-in:hover {
 background: #1e3329; color: #fff; border-color: #1e3329; transform: translateY(-1px);
}
/* 2026-07-31 (Stephen) — DESKTOP demo "Save my plan" conversion CTA. On mobile the demo
   footer carries Save; on desktop/tablet the footer is gone, so the convert action moves
   to a header pill sitting just left of the Vera avatar, styled like the "Log in" pill.
   Shown ONLY in a live demo at ≥601px; the avatar (the "Vera icon") is always present in
   a demo (header resolves signed-in because a demo owns a wedding id). */
#vxDemoSavePill{display:none}
@media (min-width:601px){ body.vx-demo-active #vxDemoSavePill{display:inline-flex;align-items:center} }

/* ═══ Header avatar + dropdown (2026-04-29) ════════════════════════
   Replaces the signed-in pill with an initial-circle avatar that
   opens a 3-section menu: wedding context, planning-spaces switcher
   (multi-wedding only), and Privacy / Sign out actions. */
.vx-header-avatar-wrap{position:relative;display:none}
.vx-header-avatar-wrap[hidden]{display:none!important}
body.is-signed-in .vx-header-avatar-wrap:not([hidden]){display:block}
.vx-header-avatar{appearance:none;border:none;padding:0;cursor:pointer;width:34px;height:34px;border-radius:50%;background:var(--green,#2C4A3E);color:#fff;display:flex;align-items:center;justify-content:center;position:relative;border:1.5px solid var(--gold,#C8A96E);transition:transform .15s,box-shadow .15s}
.vx-header-avatar:hover{transform:translateY(-1px);box-shadow:0 4px 14px rgba(44,74,62,.18)}
.vx-header-avatar:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
.vx-header-avatar[aria-expanded="true"]{box-shadow:0 4px 16px rgba(44,74,62,.22)}
.vx-header-avatar-initial{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;font-weight:500;letter-spacing:.01em;line-height:1;text-transform:uppercase}
/* Brand-avatar bust (Olsson) — circular crop biased toward the face. The
   chat thumbnail has Olsson's face high in the 9:16 source; for a 1:1
   crop the source overflows ~78% of container height, so we need a low
   object-position vertical to keep the face near the top of the visible
   circle. CSS variable lets sadmin tune live without redeploying via:
     document.documentElement.style.setProperty('--vx-avatar-y', '15%') */
.vx-header-avatar-bust{
  width:100%;height:100%;object-fit:cover;
  object-position:50% var(--vx-avatar-y, 50%);
  border-radius:50%;display:block;background:var(--green,#2C4A3E)
}
.vx-header-avatar-bust[hidden]{display:none}
.vx-header-avatar-dot{position:absolute;top:-2px;right:-2px;width:9px;height:9px;border-radius:50%;background:var(--gold,#C8A96E);box-shadow:0 0 0 2px var(--cream,#FAF7F2)}
.vx-header-avatar-dot[hidden]{display:none}

.vx-header-dropdown{position:absolute;top:calc(100% + 8px);right:0;min-width:260px;max-width:300px;background:#fff;border:1px solid rgba(44,74,62,.1);border-radius:14px;padding:6px;box-shadow:0 12px 36px rgba(28,28,28,.16);opacity:0;transform:translateY(-4px);transition:opacity .18s,transform .18s;z-index:200}
.vx-header-dropdown:not([hidden]){opacity:1;transform:translateY(0)}
.vx-header-dropdown[hidden]{display:none}
.vx-header-dd-section{padding:8px 10px}
.vx-header-dd-section + .vx-header-dd-section{border-top:1px solid rgba(44,74,62,.06)}
.vx-header-dd-context{padding:14px 14px 10px}
.vx-header-dd-couple{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.05rem;font-weight:500;color:var(--green,#2C4A3E);font-style:italic;line-height:1.2}
.vx-header-dd-meta{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.06em;color:var(--text-muted);margin-top:2px}
.vx-header-dd-label{font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px;padding-left:4px}
.vx-header-dd-actions{padding:6px}
.vx-header-dd-item{appearance:none;background:transparent;border:none;width:100%;display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:8px;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;color:var(--ink,#1C1C1C);text-align:left;transition:background .12s}
.vx-header-dd-item:hover{background:rgba(200,169,110,.1)}
.vx-header-dd-item svg{flex-shrink:0;color:var(--green,#2C4A3E);opacity:.85}
.vx-header-dd-switcher-row{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;color:var(--ink,#1C1C1C);transition:background .12s}
.vx-header-dd-switcher-row:hover{background:rgba(200,169,110,.1)}
.vx-header-dd-switcher-row.is-active{color:var(--green);font-weight:500}
.vx-header-dd-switcher-row .vx-header-dd-check{margin-left:auto;color:var(--gold,#C8A96E);opacity:0;font-size:.78rem}
.vx-header-dd-switcher-row.is-active .vx-header-dd-check{opacity:1}
.vx-tips-context{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.06em;color:var(--gold-deep,#A07840);font-weight:500;margin-left:4px}
/* 2026-07-24 — Release/build id footer in the account (Vera) dropdown. The one
   reliable "what am I actually running?" readout; on iOS it equals the OTA
   manifest version (ios-<sha>). Tap to copy. Mirrors .vx-header-dd-meta (DM Mono, muted). */
.vx-header-dd-build{appearance:none;background:transparent;border:none;border-top:1px solid rgba(44,74,62,.06);width:100%;display:flex;align-items:baseline;gap:8px;padding:9px 14px 5px;margin-top:2px;cursor:pointer;text-align:left;transition:background .12s}
.vx-header-dd-build:hover{background:rgba(200,169,110,.08)}
.vx-header-dd-build-label{font-family:var(--ff-m,'DM Mono',monospace);font-size:.55rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);flex:0 0 auto}
.vx-header-dd-build-id{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.03em;color:var(--green,#2C4A3E);margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:190px}
.vx-header-dd-build.is-dev .vx-header-dd-build-id{color:var(--gold-deep,#A07840)}

/* Tips video lightbox — reuses same shape as Videos tab modal */
.vx-tips-modal{position:fixed;inset:0;background:rgba(28,28,28,.86);display:flex;align-items:center;justify-content:center;z-index:9999;padding:20px}
.vx-tips-modal-inner{background:#000;border-radius:10px;max-width:480px;width:100%;max-height:90vh;display:flex;flex-direction:column;overflow:hidden;position:relative}
.vx-tips-modal video{width:100%;max-height:80vh;background:#000;display:block}
.vx-tips-modal-close{position:absolute;top:14px;right:18px;background:rgba(0,0,0,.5);color:#fff;border:none;border-radius:50%;width:34px;height:34px;font-size:1.4rem;line-height:1;cursor:pointer;z-index:1}
.vx-tips-modal-close:hover{background:rgba(0,0,0,.85)}
.vx-tips-modal-caption{background:#0d0d0d;color:rgba(255,255,255,.85);font-family:var(--ff-m,'DM Mono',monospace);font-size:.66rem;letter-spacing:.08em;text-transform:uppercase;padding:8px 14px;display:flex;justify-content:space-between;align-items:center;gap:10px}
.vx-tips-modal-caption .vx-tips-caption-title{color:#fff;font-weight:500;letter-spacing:.04em;text-transform:none;font-family:var(--ff-d,'Cormorant Garamond',serif);font-style:italic;font-size:1rem;letter-spacing:.01em}
/* Reusable Vera mark — small portrait + eyebrow text. Used in the
   Tips & Tricks caption so every help video impression is also a
   Vera impression. Drop into other surfaces (advisor notes, Decision
   Log entries) for consistent attribution. */
.vx-vera-mark{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto}
.vx-vera-mark-img{width:24px;height:24px;border-radius:50%;object-fit:cover;background:var(--cream,#FAF7F2);box-shadow:0 0 0 2px rgba(200,169,110,.36)}
.vx-vera-mark-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.78)}
.vx-tips-modal-caption .vx-vera-mark-eyebrow{color:rgba(255,255,255,.78)}
/* Light-background variant — when the Vera mark is dropped onto a
   cream/white surface (advisor notes, Decision Log), eyebrow flips
   to gold-deep so it stays readable. */
.vx-vera-mark[data-on="light"] .vx-vera-mark-eyebrow{color:var(--gold-deep,#A07840)}
/* ═══ Cinematic launcher (shared across all video modals) ═══════════
   Wraps any <video> in .vx-cinema-stage and gets:
     - fade-in (600ms) on first frame loaded
     - fade-out (800ms) + verdeaux wordmark fade-in on natural end
     - 2.6s logo hold then auto-close (close handler is the modal's own)
   Both the Tips/Welcome modal and the Videos library subscriber-click
   modal share this CSS; the JS is inlined in each _openPlayer. */
.vx-cinema-stage{position:relative;background:#000;opacity:0;transition:opacity 600ms ease-out}
.vx-cinema-stage.is-in{opacity:1}
.vx-cinema-stage.is-out video{opacity:0;transition:opacity 800ms ease-in}
/* Framing masks — driven by data-framing on the stage. The video file is
   always rectangular (HeyGen output); we mask client-side so the player
   shape matches the framing choice (full = rectangle, circle = circular).
   2026-05-24 — added explicit aspect ratio + object-fit:cover to "full"
   so every video plays in the same 4:5 frame regardless of the talking-
   photo source's native shape. Olsson variants are taller-or-wider per
   source image; without this CSS, every video sized to its native MP4
   dimensions and the modal felt inconsistent. object-position centers
   horizontally + biases slightly up so the face stays visible when
   cropping a tall vertical source. */
.vx-cinema-stage[data-framing="full"]{aspect-ratio:4/5;max-width:min(90vw,80vh,440px);max-height:min(90vw,80vh,550px);margin:0 auto;overflow:hidden;background:#000;border-radius:10px}
/* 2026-05-24 — transform:scale(1.5) REVERTED. The zoom anchored at
   center 30% pushed faces OFF the frame while keeping tables/legs IN
   (origin was at her chest; scaling outward pushed the head up and
   away). Stephen flagged on spot-check; per-video review queued for
   tomorrow (task #69) to find a repeatable pattern.
   Current state: object-fit:cover + object-position:center top so the
   face is anchored to the top of the frame. Some videos will show
   room/scene context at the bottom until the per-video framing review
   defines tighter values per source composition. */
.vx-cinema-stage[data-framing="full"] video{width:100%;height:100%;object-fit:cover;object-position:center top;display:block}
.vx-cinema-stage[data-framing="circle"]{aspect-ratio:1/1;max-width:min(90vw,80vh,480px);max-height:min(90vw,80vh,480px);margin:0 auto;border-radius:50%;overflow:hidden;background:var(--cream,#FAF7F2)}
.vx-cinema-stage[data-framing="circle"] video{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
/* 2026-07-14 — "reel" framing for the 9:16 prep-video renders (intro card +
   burned captions + logo sting). The old "full" stage is a 4:5 top-anchored
   crop that would cut the caption band off a vertical video. Applied
   explicitly by the prep modal, and auto-applied by the loadedmetadata
   sniffer (end of file) when a portrait video lands in a "full" stage. */
.vx-cinema-stage[data-framing="reel"]{aspect-ratio:9/16;max-width:min(90vw,47vh,380px);max-height:min(160vw,84vh);margin:0 auto;overflow:hidden;background:#000;border-radius:14px}
.vx-cinema-stage[data-framing="reel"] video{width:100%;height:100%;object-fit:cover;display:block}
/* 2026-07-15 (Stephen) — reel videos float free: no black side panels.
   The 480px modal card was wider than the 9:16 stage; for reel framing
   the inner goes transparent and shrink-wraps, the stage carries the
   shadow, and the close button rides above the video like the prep
   modal's. The sniffer flips framing post-metadata, so :has() reacts. */
.vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="reel"]),
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="reel"]){background:transparent;border-radius:0;overflow:visible;width:auto;max-width:none;box-shadow:none}
.vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="reel"]) .vx-cinema-stage,
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="reel"]) .vx-cinema-stage{box-shadow:0 24px 80px rgba(0,0,0,.55)}
.vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="reel"]) .vx-vid-modal-close,
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="reel"]) .vx-tips-modal-close{top:-44px;right:0;background:rgba(250,247,242,.95);color:#2C4A3E;border:1.5px solid #C8A96E}
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="reel"]) .vx-tips-modal-caption{display:none}
/* 2026-07-15 — offline estimate guard (found via TestFlight 1.0(2) review:
   airplane mode leaked the $250k demo sentinel as "$48,374 allocated /
   $201,626 remaining"). Offline, live market rates can't load, so the
   totals strip hides and a Vera-toned notice explains why — honest
   numbers or no numbers. */
body.vx-net-offline #vxBudgetTotalsStrip{display:none!important}
.vx-offline-note{margin:14px 0;padding:14px 16px;border-left:2px solid var(--gold-deep,#A07840);background:rgba(250,243,230,.6);border-radius:0 12px 12px 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.88rem;color:var(--charcoal,#1C1C1C);line-height:1.55}
.vx-offline-note strong{color:var(--green,#2C4A3E)}

/* Circle-mode modal chrome — when the stage is a circle, strip the
   black rectangular surround + caption bar so the user sees JUST a
   circle floating on the dimmed page backdrop. Close button floats
   outside the circle's top-right edge. Uses :has() (Safari 15.4+,
   Chrome 105+, Firefox 121+ — all supported by our target browsers). */
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="circle"]),
.vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="circle"]){
  background:transparent;box-shadow:none;border-radius:0;max-width:none;overflow:visible
}
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-tips-modal-caption{display:none}
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-tips-modal-close,
.vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-vid-modal-close{
  top:-12px;right:-12px;background:rgba(250,247,242,.95);color:var(--green,#2C4A3E);border:1.5px solid var(--gold,#C8A96E);box-shadow:0 4px 14px rgba(0,0,0,.35)
}
.vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-tips-modal-close:hover,
.vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-vid-modal-close:hover{
  background:#fff
}
/* On narrow viewports the floating-outside close button would clip past
   the screen edge — pull it inside the circle so it stays tappable. */
@media (max-width: 520px){
  .vx-tips-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-tips-modal-close,
  .vx-vid-modal-inner:has(.vx-cinema-stage[data-framing="circle"]) .vx-vid-modal-close{
    top:14px;right:14px
  }
}
.vx-cinema-end{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:var(--cream,#FAF7F2);
  font-family:var(--ff-d,'Cormorant Garamond',serif);
  font-size:clamp(2.4rem,6vw,3.4rem);font-weight:400;
  color:var(--green,#2C4A3E);letter-spacing:.02em;
  opacity:0;transition:opacity 800ms ease-in 200ms;
  cursor:pointer;user-select:none;
}
.vx-cinema-end[hidden]{display:none}
.vx-cinema-end em{color:var(--gold,#C8A96E);font-style:italic;font-weight:400}
.vx-cinema-end.is-shown{opacity:1}

.vx-tips-video-wrap{position:relative;background:#000}
/* Shared tap-for-sound overlay used by both Tips and Videos players.
   All videos start muted — overlay sits centered-bottom over the stage
   with a soft pulse to draw attention. Tap → unmute + restart from 0. */
.vx-cinema-unmute{position:absolute;left:50%;bottom:80px;transform:translateX(-50%);display:inline-flex;align-items:center;gap:10px;padding:11px 22px;background:rgba(250,247,242,.95);color:var(--green,#2C4A3E);border:1.5px solid var(--gold,#C8A96E);border-radius:100px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;font-weight:500;cursor:pointer;box-shadow:0 6px 24px rgba(0,0,0,.4);animation:vxCinemaUnmutePulse 1.6s ease-in-out infinite;z-index:2}
.vx-cinema-unmute:hover{background:#fff;transform:translateX(-50%) translateY(-1px)}
.vx-cinema-unmute span:first-child{font-size:1.05rem}
@keyframes vxCinemaUnmutePulse{0%,100%{box-shadow:0 6px 24px rgba(0,0,0,.4),0 0 0 0 rgba(200,169,110,.6)}50%{box-shadow:0 6px 24px rgba(0,0,0,.4),0 0 0 12px rgba(200,169,110,0)}}
@media(max-width:480px){
 .vx-header-dropdown{min-width:240px;right:-8px}
 /* 2026-06-27 (mobile fix #4) — the avatar is the SOLE header control on
    phones, so it needs a ≥44px touch target. The visible disc stays ~32px
    (with its real green fill + gold ring); a transparent ::after overlay
    extends the hittable area to 44px without enlarging the circle. The
    button keeps position:relative (set in the base rule) so the overlay
    anchors to it. Mobile-only (≤480px) — desktop 34px disc unchanged. */
 .vx-header-avatar{width:32px;height:32px;min-width:32px;min-height:32px}
 .vx-header-avatar::after{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:44px;height:44px;min-width:44px;min-height:44px;border-radius:50%}
 .vx-header-avatar-initial{font-size:.78rem}
}

.bridge { position: relative; z-index: 1; max-width: 900px; margin: 0 auto; padding: 6.5rem 2rem 0; }

.step-bar {
 display: flex; align-items: center; justify-content: flex-start;
 background: transparent; border: none; border-radius: 0; overflow: visible;
}
.step-bar::before,.step-bar::after {
 content: '|'; color: rgba(44,74,62,.3);
 font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .85rem; font-weight: 300;
 pointer-events: none; flex-shrink: 0; line-height: 1;
}
.step-node {
 padding: 0 16px; min-height: 38px; display: flex; align-items: center; gap: 0;
 text-decoration: none; transition: color .18s; cursor: pointer;
 background: transparent; border: none; text-align: center; width: auto;
}
.step-node--done:hover,.step-node--next:hover { background: transparent; }
.step-node--current { background: transparent; }
.step-node--next { opacity: 1; cursor: pointer; }

.sn-num { display: none; }

.sn-name {
 /* 2026-05-14 — Switched from raw 13px to .82rem for unit consistency
    with the rest of the chrome (header-greeting .82rem, header-pill
    .875rem, btn-primary .95rem). Active-state weight aligned with
    brand family — 500 → 500 + green color shift carries the
    active emphasis without bumping to out-of-family 600. */
 font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .82rem;
 font-weight: 500; line-height: 1; white-space: nowrap; letter-spacing: .03em;
}
.step-node--done .sn-name { color: var(--text-muted); }
.step-node--current .sn-name { color: var(--green); font-weight: 500; }
.step-node--next .sn-name { color: var(--text-muted); }

.step-divider {
 width: auto; background: none; flex-shrink: 0;
 color: rgba(44,74,62,.3);
 font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .85rem; font-weight: 300; line-height: 1;
}
.step-divider::after { content: '|'; }

/* ═══ Vera tab (2026-05-09) ═════════════════════════════════════════
   First-position peer of Budget / Vendor+ / Contracts+ / Your Plan.
   Always green to mark her as a persona, not a function. Slightly faded
   when inactive, full saturation when she's the active surface. */
.step-node-vera .sn-name { color: var(--green); font-weight: 500; opacity: .82; transition: opacity .18s, font-weight .18s; }
.step-node-vera:hover .sn-name { opacity: 1; }
.step-node-vera.is-active .sn-name { opacity: 1; font-weight: 600; }

/* ═══ Vera introduction screen (section-vera) ═══════════════════════
   Soft landing — sits over the wallpaper layer, centered card with the
   Olsson portrait + calm-collaborative copy + a single Claude-style
   input. Emotionally distinct from the rest of the surfaces (which are
   text-dense) — this is the moment the user meets the persona. */
.vx-vera-stage{display:flex;align-items:flex-start;justify-content:center;min-height:calc(100vh - 200px);padding:32px 20px 64px;position:relative;z-index:1}
.vx-vera-card{max-width:720px;width:100%;text-align:left;background:rgba(250,247,242,.78);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(200,169,110,.22);border-radius:24px;padding:36px clamp(28px,5vw,48px) 40px;box-shadow:0 12px 48px rgba(28,28,28,.08)}
/* 2026-05-09 (revised): header is a 33/66 grid — avatar column on the
   left, text column on the right. Form below the header spans the FULL
   card content width (no indent). The avatar fills its 33% column up
   to a 200px max so it scales gracefully across viewports. */
.vx-vera-header{display:grid;grid-template-columns:33% 1fr;gap:24px;align-items:start;margin-bottom:30px}
/* Portrait composition: source webp is 405×720 with a circular vignette
   centered. object-fit:cover at center 35% places her face at the
   optical centre. 12px cream halo via box-shadow gives the avatar room
   to breathe; matches the generosity of the original centered version. */
/* 2026-05-09: hard 200×200 pixels (not responsive width:100%) to
   guarantee a perfect square in every browser. Safari can interpret
   aspect-ratio inside grid contexts inconsistently — fixed dimensions
   eliminate that risk. Mobile breakpoint overrides to 120×120. The
   drop shadow has 0 vertical offset so the halo radiates symmetrically;
   any vertical offset reads as "the circle bulges down" → oval. */
.vx-vera-portrait{width:200px;height:200px;flex-shrink:0;border-radius:50%;object-fit:cover;object-position:center center;background:var(--cream);margin:0;display:block;justify-self:start;align-self:start;box-shadow:0 0 0 12px var(--cream),0 0 0 13px rgba(200,169,110,.24),0 0 28px rgba(28,28,28,.06)}
/* 2026-06-03 (Stephen) — Vera brief card: her portrait + read, gold-accented.
   Compact portrait so search controls stay close; small enough to keep side-by-side on mobile. */
.vx-brief{display:flex;gap:15px;align-items:flex-start;margin:0 0 16px;padding:15px 18px;border:1px solid rgba(200,169,110,.30);border-left:3px solid var(--gold,#c8a96e);border-radius:10px;background:linear-gradient(180deg,rgba(250,247,242,.72),rgba(242,235,224,.42))}
.vx-brief-portrait{width:58px;height:58px;flex-shrink:0;border-radius:50%;object-fit:cover;object-position:center;background:var(--cream);box-shadow:0 0 0 2px var(--cream),0 0 0 3px rgba(200,169,110,.45)}
.vx-brief-main{flex:1;min-width:0}
.vx-brief-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:1px 0 7px}
/* 2026-07-28 (Stephen) — CANONICAL VERA VOICE: Vera's spoken/answer prose stays Cormorant serif
   on purpose (her warm voice; never sans-ified). ONE shared voice/quote type spec; the scattered
   per-surface answer rules below keep only their own layout (margins) and inherit this face. */
.vx-brief-body,
.vx-vera-similar-line,
.vx-vera-memory-line,
.vx-vera-coach-line{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.05rem;line-height:1.5;color:var(--ink,#1C1C1C)}
@media(max-width:560px){.vx-brief{gap:12px;padding:14px 15px}.vx-brief-portrait{width:46px;height:46px}.vx-brief-body{font-size:1rem}}
.vx-vera-header-text{min-width:0;padding-top:18px}
.vx-vera-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 4px;font-weight:500}
.vx-vera-headline{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:clamp(1.8rem,4vw,2.4rem);font-weight:400;color:var(--green);line-height:1.1;letter-spacing:-.01em;margin:0 0 8px}
.vx-vera-headline em{color:var(--gold);font-style:italic}
/* 2026-05-09: matched to .pt-sub for cross-surface consistency.
   Vendor+ uses .pt-sub for its subtitle copy; Vera's intro now reads
   in the same register so the persona's voice doesn't typographically
   shout louder than the rest of the editorial subtitles. */
.vx-vera-intro{font-size:.88rem;color:var(--text-muted);margin-top:0;margin-bottom:0;line-height:1.65;max-width:580px}
/* 2026-05-14 — Demo "Try yourself" solo-coach card. Sits above the
   question prompt on Vera after a visitor exits the guided demo via
   the completion CTA's "Try yourself" button. Frames what they're
   doing (sandbox, won't save) and points at the avatar menu for
   sign-out. Cream tint + gold-deep eyebrow + sage left-border so it
   reads as a contextual frame, not a warning. × dismisses. */
.vx-demo-solo-coach{position:relative;margin:0 0 24px;padding:16px 44px 16px 18px;background:linear-gradient(180deg,rgba(250,247,242,.85),rgba(242,235,224,.6));border:1px solid rgba(200,169,110,.32);border-left:3px solid var(--sage,#5A8C7A);border-radius:10px}
.vx-demo-solo-coach-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin-bottom:6px}
.vx-demo-solo-coach-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;font-weight:500;font-style:italic;color:var(--green,#2C4A3E);line-height:1.25;margin-bottom:8px}
.vx-demo-solo-coach-body{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;color:var(--ink-mid,#4A4A4A);line-height:1.6}
.vx-demo-solo-coach-body strong{color:var(--green,#2C4A3E);font-weight:500}
.vx-demo-solo-coach-link{color:var(--gold-deep,#A07840);text-decoration:underline;text-decoration-color:rgba(200,169,110,.4);text-underline-offset:2px;font-weight:500;transition:color .15s,text-decoration-color .15s}
.vx-demo-solo-coach-link:hover{color:var(--green,#2C4A3E);text-decoration-color:var(--green,#2C4A3E)}
.vx-demo-solo-coach-close{position:absolute;top:10px;right:10px;width:24px;height:24px;background:transparent;border:0;border-radius:4px;color:var(--text-muted,#7A7A7A);font-size:18px;line-height:1;cursor:pointer;padding:0;transition:background .12s,color .12s}
.vx-demo-solo-coach-close:hover{background:rgba(44,74,62,.08);color:var(--green,#2C4A3E)}
/* Question + form + skip span the full card content width — explicitly
   not indented to align with the text column above. The 33/66 grid
   above keeps the header balanced; below it the prompt is the focal
   point and gets the full canvas. */
/* Vera planning board — drafts stack (2026-05-09).
   Sits below the question form, above the off-platform mini-plan.
   Each card is a peer in the stack: title · meta · [Continue →] [×]
   plus a drag handle. New drafts animate in. Drag-over highlights the
   drop slot. */
.vx-vera-drafts-board{max-width:720px;margin:24px auto 12px;padding:0 20px}
.vx-vera-drafts-board[hidden]{display:none}
/* Inline mode: board sits directly below the submit button on the
   Vera card — no max-width constraint (it inherits the card's width),
   no horizontal padding (the card already has its own), and a tight
   top margin so the first card aligns flush with the submit button. */
.vx-vera-drafts-board--inline{max-width:none;margin:12px 0 0;padding:0}
.vx-vera-drafts-board--inline .vx-vera-draft{margin-bottom:8px}
.vx-vera-drafts-board--inline .vx-vera-draft:last-child{margin-bottom:0}
.vx-vera-drafts-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 10px;font-weight:500}
.vx-vera-draft{position:relative;background:var(--white,#fff);border:1px solid rgba(44,74,62,.12);border-radius:14px;padding:14px 14px 14px 18px;margin:0 0 10px;display:flex;align-items:center;gap:14px;box-shadow:0 1px 3px rgba(28,28,28,.04);transition:box-shadow .15s,transform .12s,border-color .15s;animation:vxDraftIn .25s ease-out}
.vx-vera-draft.is-dragging{opacity:.45;transform:scale(.98);box-shadow:0 6px 18px rgba(28,28,28,.12)}
.vx-vera-draft.is-drop-target{border-color:var(--gold,#C8A96E);background:rgba(250,247,242,.85)}
.vx-vera-draft[data-status="active"]{border-left:3px solid var(--green,#2C4A3E);padding-left:15px}
.vx-vera-draft-handle{flex:0 0 16px;width:16px;height:24px;cursor:grab;color:var(--text-muted,#9a9a9a);display:flex;align-items:center;justify-content:center;font-family:var(--ff-m,'DM Mono',monospace);font-size:1.05rem;line-height:1;user-select:none}
.vx-vera-draft-handle:active{cursor:grabbing}
.vx-vera-draft-handle::before{content:'⋮⋮'}
.vx-vera-draft-body{flex:1;min-width:0}
.vx-vera-draft-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.1rem;font-weight:400;color:var(--green,#2C4A3E);line-height:1.3;margin:0 0 3px}
.vx-vera-draft-meta{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted,#7A7A7A)}
.vx-vera-draft[data-status="active"] .vx-vera-draft-meta::before{content:'• Resuming · ';color:var(--green,#2C4A3E)}
.vx-vera-draft-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}
.vx-vera-draft-continue{appearance:none;background:var(--green,#2C4A3E);color:var(--white,#fff);border:none;border-radius:8px;padding:8px 14px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:500;cursor:pointer;transition:background .15s;white-space:nowrap}
.vx-vera-draft-continue:hover{background:var(--green-deep,#1f3528)}
.vx-vera-draft-close{appearance:none;background:transparent;border:none;color:var(--text-muted,#9a9a9a);font-size:1.1rem;line-height:1;width:26px;height:26px;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}
.vx-vera-draft-close:hover{background:rgba(44,74,62,.08);color:var(--green,#2C4A3E)}
@keyframes vxDraftIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}

/* Similarity prompt card — appears when a new submission matches an
   existing draft's workflow_id. Three quick choices: Revise the
   existing one (loads its plan + replaces with new intent), Replace
   (archives old, inserts new), or Keep both. */
.vx-vera-similar{margin:14px 0;padding:16px 18px;background:var(--cream,#FAF7F2);border:1px solid rgba(200,169,110,.4);border-radius:12px;animation:vxDraftIn .22s ease-out}
.vx-vera-similar-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 6px;font-weight:500}
.vx-vera-similar-line{margin:0 0 12px}
.vx-vera-similar-line em{color:var(--green,#2C4A3E);font-style:italic}
.vx-vera-similar-actions{display:flex;flex-wrap:wrap;gap:8px}
.vx-vera-similar-btn{appearance:none;background:var(--white,#fff);border:1px solid rgba(44,74,62,.22);color:var(--green,#2C4A3E);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;padding:7px 14px;border-radius:8px;cursor:pointer;transition:all .15s}
.vx-vera-similar-btn:hover{background:var(--green-pale,#eaf0ed);border-color:var(--green)}
.vx-vera-similar-btn[data-primary]{background:var(--green,#2C4A3E);color:var(--white,#fff);border-color:var(--green)}
.vx-vera-similar-btn[data-primary]:hover{background:var(--green-deep,#1f3528)}

/* 2026-05-28 (Stephen "remove that feature totally"): empty-state
   coaching cards retired from Vendor+/Budget/Contracts+. The tools are
   intuitive enough; on-demand Vera videos are the only help surface.
   CSS + IIFE + JS hooks deleted in one pass. */

/* Returning-Vera memory card — appears above the question form when the
   wedding has at least one prior decision. Soft inline-card register
   (no shadow) so it reads as part of the conversation, not a separate
   panel. Quick-action buttons inline at the bottom. */
.vx-vera-memory{position:relative;margin:20px 0 4px;padding:14px 36px 16px 16px;border-left:2px solid var(--gold,#C8A96E);background:rgba(250,247,242,.55);border-radius:0 12px 12px 0}
.vx-vera-memory-close{position:absolute;top:8px;right:10px;background:transparent;border:none;color:var(--text-muted,#7A7A7A);font-size:1.1rem;line-height:1;width:24px;height:24px;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}
.vx-vera-memory-close:hover{background:rgba(44,74,62,.08);color:var(--green,#2C4A3E)}
.vx-vera-memory-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 6px}
.vx-vera-memory-line{margin:0}
.vx-vera-memory-line em{color:var(--green,#2C4A3E);font-style:italic}
.vx-vera-memory-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.vx-vera-memory-btn{appearance:none;background:var(--white,#fff);border:1px solid var(--border-g,rgba(44,74,62,.22));color:var(--green,#2C4A3E);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;padding:8px 14px;border-radius:999px;cursor:pointer;transition:all .15s}
.vx-vera-memory-btn:hover{background:var(--green-pale,#eaf0ed);border-color:var(--green)}
.vx-vera-memory-btn[data-secondary]{background:transparent;color:var(--text-muted)}
.vx-vera-memory-btn[data-secondary]:hover{color:var(--green);background:var(--green-pale,#eaf0ed)}

/* 2026-07-11 — Vera coach card (Phase 1). One per-arrival note from the
   vera-coach function; same soft inline register as the memory card but
   green-edged so the two read as distinct voices (coach = forward-looking,
   memory = recap). Reuses .vx-vera-memory-btn for its actions. */
.vx-vera-coach{position:relative;margin:20px 0 4px;padding:14px 36px 16px 16px;border-left:2px solid var(--green,#2C4A3E);background:rgba(234,240,237,.5);border-radius:0 12px 12px 0}
.vx-vera-coach-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 6px}
.vx-vera-coach-line{margin:0}
.vx-vera-coach-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
/* 2026-07-14 — Vera milestone-reminder offer. Same inline register as the
   coach card but GOLD-edged so the one-time offer reads as a distinct
   voice from the daily coach note. Reuses the coach eyebrow/line/actions
   classes. The modal variant is the post-Welcome-video moment. */
.vx-vera-milestone{position:relative;margin:16px 0 4px;padding:14px 36px 16px 16px;border-left:2px solid var(--gold-deep,#A07840);background:rgba(250,243,230,.55);border-radius:0 12px 12px 0}
.vx-milestone-modal{position:fixed;inset:0;background:rgba(28,28,28,.55);display:flex;align-items:center;justify-content:center;z-index:9999;padding:20px}
.vx-milestone-modal-card{max-width:460px;width:100%;background:var(--white,#FEFCF8);border:1px solid rgba(200,169,110,.35);border-radius:18px;box-shadow:0 18px 56px rgba(28,28,28,.22);padding:26px 26px 22px}
.vx-milestone-modal-head{display:flex;align-items:center;gap:12px;margin-bottom:10px}
.vx-milestone-modal-head img{width:44px;height:44px;border-radius:50%;object-fit:cover}
/* Vera header ⋯ menu (holds the Coaching slider). Card gets position
   context for the absolute button + popover. */
.vx-vera-card{position:relative}
.vx-vera-menu-btn{position:absolute;top:10px;right:12px;appearance:none;background:transparent;border:none;color:var(--text-muted,#7A7A7A);font-size:1.3rem;line-height:1;width:32px;height:32px;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s;z-index:5}
.vx-vera-menu-btn:hover{background:rgba(44,74,62,.08);color:var(--green,#2C4A3E)}
.vx-vera-menu-pop{position:absolute;top:46px;right:12px;z-index:40;background:var(--white,#FEFCF8);border:1px solid rgba(200,169,110,.35);border-radius:12px;box-shadow:0 14px 36px rgba(28,28,28,.16);padding:14px 16px;width:min(280px,80vw)}
.vx-vera-menu-row{display:flex;align-items:center;gap:14px;justify-content:space-between}
.vx-vera-menu-label{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;font-weight:500;color:var(--ink,#1C1C1C)}
.vx-vera-menu-sub{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;line-height:1.45;color:var(--text-mid,#4A4A4A);margin-top:3px}
.vx-switch{position:relative;display:inline-block;flex:none}
.vx-switch input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;z-index:2}
.vx-switch-track{display:block;width:40px;height:24px;border-radius:999px;background:#cfcac0;transition:background .18s;position:relative}
.vx-switch input:checked + .vx-switch-track{background:var(--green,#2C4A3E)}
.vx-switch-thumb{position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .18s}
.vx-switch input:checked + .vx-switch-track .vx-switch-thumb{transform:translateX(16px)}
/* Compact switch for the avatar-dropdown Coaching row. */
.vx-switch--sm .vx-switch-track{width:34px;height:20px}
.vx-switch--sm .vx-switch-thumb{width:14px;height:14px}
.vx-switch--sm input:checked + .vx-switch-track .vx-switch-thumb{transform:translateX(14px)}
.vx-header-dd-coaching{display:flex;align-items:center;cursor:default}

.vx-vera-question{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.35rem;color:var(--green);font-weight:400;margin:18px 0 12px;text-align:left}
.vx-vera-story-link{display:inline-flex;align-items:center;gap:8px;margin:18px 0 0;font-family:var(--ff-m,'DM Mono',monospace);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-mid,#4A4A4A);text-decoration:none;border-bottom:1px dashed rgba(200,169,110,.4);padding-bottom:2px;transition:color .15s,border-color .15s}
.vx-vera-story-link:hover{color:var(--green);border-color:var(--gold)}
.vx-vera-story-link span{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;letter-spacing:0}
/* 2026-05-11 — Demo-mode banner. Sits below the fixed header, full-width,
   amber accent so it reads as "you are in a sandbox". Persistent until
   the visitor signs up or the wedding row is deleted. */
/* 2026-05-11 — Banner replaced by a "Demo Mode" greeting swap in the
   header. The banner class is left in place but hidden by default so
   any orphan banner DOM is invisible. */
.vx-demo-banner { display:none !important }
.vx-demo-banner-legacy {
  position:fixed; top:0; left:0; right:0; z-index:1000;
  background:linear-gradient(180deg, rgba(200,146,58,.18), rgba(200,146,58,.10));
  border-bottom:1px solid rgba(200,146,58,.4);
  padding:9px 24px;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  font-family:var(--ff-m,'DM Mono',monospace); font-size:11px;
  letter-spacing:.05em; color:var(--bronze, #7A5A2A);
}
/* Demo greeting label. 2026-08-05 — the greeting path no longer ADDS this
   class: Stephen asked for a plain "Demo", not a pill, because the header
   already has the gold Save-my-plan CTA carrying the visual weight. The rule
   is kept because #vx-demo-banner-era code and any future badge use may still
   want it; nothing in the greeting renderer applies it today. */
#header-greeting.is-demo-greeting {
  font-family:var(--ff-m,'DM Mono',monospace) !important;
  font-size:11px !important;
  letter-spacing:.14em !important;
  text-transform:uppercase !important;
  color:#FFF !important;
  /* 2026-05-14 — Tokenized. See --bronze in :root. */
  background:var(--bronze, #7A5A2A) !important;
  padding:5px 12px !important;
  border-radius:999px !important;
  font-weight:500 !important;
}
.vx-demo-banner-label {
  font-weight:500; text-transform:uppercase; letter-spacing:.14em;
  background:var(--bronze, #7A5A2A); color:#FFF;
  padding:3px 10px; border-radius:999px; font-size:10px;
}
.vx-demo-banner-text { flex:1; min-width:200px; line-height:1.5; }
.vx-demo-banner-text strong { color:#5A3F12; font-weight:500; }
.vx-demo-banner-cta {
  display:inline-flex; align-items:center; gap:6px;
  padding:7px 16px; border-radius:999px;
  background:var(--bronze, #7A5A2A); color:#FFF;
  text-decoration:none; font-size:11px; font-weight:500;
  letter-spacing:.06em; text-transform:uppercase;
  transition:background .15s;
}
.vx-demo-banner-cta:hover { background:#5A3F12; color:#FFF; }
/* 2026-05-11 — Banner removed. The demo context lives in the header
   greeting swap ("Demo Mode" pill replaces "Hi, Avery"). The
   .vx-demo-active body class still applies so feature-specific CSS
   can target the demo session if needed, but it no longer pushes
   any chrome down. */
body.vx-demo-active { /* greeting swap handles the demo context */ }
/* 2026-06-24 v2 (estimate-led demo, REAL read-only budget) — Step 1 now shows
   the REAL Verdeaux budget UI in a READ-ONLY, ESTIMATE-LED mode: the estimate
   headline card (#vxDemoEstimateSurface) as the hero, ABOVE the actual expandable
   category sections (.vxb-section, rendered by VerdeauxBudget into the mount) so the
   visitor can open any category and see the per-line math. KEY INSIGHT: in the demo
   day_priority is null + total_budget=250000 forces the engine into OVER fundMode,
   so the real .vxb-section category totals AND per-line item values ALREADY equal the
   realistic estimate (bucketEstimate) — the visible categories sum to the headline.
   The ONLY extras (the Tips reserve card + the budget topper, which surfaces as
   Remaining) are hidden below. ALL planning controls (Optimize/Resize/Reset, the
   priority Must/Nice/Skip bands, lock CTAs, the Allocated/Remaining strip) are the
   PAID upgrade and are hidden here. The earlier #190 blanket-hide rule (which hid
   EVERY #section-budget child except the surface and replaced the sections with a
   flat custom breakdown) is GONE. Subscribers are unaffected (no vx-demo-active). */

/* (§4) Headline card alignment — the surface sits OUTSIDE .tool-grid, so mirror
   .tool-grid's content box (max-width:900px; margin:0 auto; 2rem side padding) so the
   headline lines up horizontally with the real sections that render inside the grid.
   Lighter bottom padding now that it's a header card stacked above the sections, not
   a full-page surface. */
body.vx-demo-active #vxDemoEstimateSurface { max-width: 900px; margin: 0 auto; padding: 1.75rem 2rem 0.5rem; box-sizing: border-box; }
/* 2026-07-27 (Stephen) — ⓘ "What this estimate assumes": a quiet disclosure showing the
   sourced tier profile the estimate applied, with a Vera handoff.
   2026-07-28 — the .vxda-* CLASS rules are un-scoped from the demo (were body.vx-demo-active)
   so the logged-in Budget's #vxBudgetAssume sibling can reuse the exact visual language
   (Stephen: the demo simplifications should be our brand). The class names are unique to this
   feature, so un-scoping is inert for everyone else. The #vxDemoAssume/#vxDemoEstimateSurface
   ID rules stay demo-specific. */
body.vx-demo-active #vxDemoAssume,
#vxBudgetAssume{font-family:var(--ff-b,'DM Sans',sans-serif)}
.vxda-toggle{display:inline-flex;align-items:center;gap:7px;background:transparent;border:none;padding:3px 0;font-family:inherit;font-size:.8rem;font-weight:500;color:#5b6a64;cursor:pointer;transition:color .15s ease}
.vxda-toggle:hover{color:#2C4A3E}
.vxda-i{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;border:1.3px solid currentColor;font-family:var(--ff-d,'Cormorant Garamond',serif);font-style:italic;font-size:.74rem;font-weight:600;line-height:1;flex:0 0 auto}
.vxda-chev{transition:transform .18s ease;font-size:1rem;line-height:1;color:#9a948a}
.vxda-toggle.is-open .vxda-chev{transform:rotate(90deg)}
.vxda-panel{margin-top:9px;padding:13px 15px;background:rgba(44,74,62,.035);border:1px solid rgba(44,74,62,.09);border-radius:12px;max-width:520px}
.vxda-lead{margin:0 0 9px;font-size:.82rem;line-height:1.5;color:#4a4a4a}
.vxda-lead strong{color:#2C4A3E;font-weight:600}
.vxda-lead em{font-style:italic;color:#2C4A3E}
.vxda-list{list-style:none;margin:0 0 10px;padding:0;display:flex;flex-direction:column;gap:6px}
.vxda-row{display:flex;justify-content:space-between;gap:12px;font-size:.82rem;line-height:1.4;border-bottom:1px solid rgba(44,74,62,.06);padding-bottom:5px}
.vxda-row:last-child{border-bottom:none;padding-bottom:0}
.vxda-k{color:#8a908a;flex:0 0 auto}
.vxda-v{color:#2C4A3E;font-weight:500;text-align:right}
.vxda-v.is-unset{color:#b0757a;font-weight:500;font-style:italic}
.vxda-src{margin:0 0 12px;font-size:.72rem;line-height:1.5;color:#8a908a}
.vxda-src a{color:#5b6a64;text-decoration:underline;text-underline-offset:2px}
.vxda-vera{display:inline-flex;align-items:center;gap:6px;background:#2C4A3E;color:#FAF7F2;border:none;border-radius:40px;padding:9px 16px;font-family:inherit;font-size:.8rem;font-weight:600;cursor:pointer;transition:background .15s ease}
.vxda-vera:hover{background:#24413a}
/* Logged-in Budget sibling: give the ⓘ a little breathing room under the plan summary. */
#vxBudgetAssume{margin:-0.4rem 0 1.1rem}
body.vx-demo-active #vxBudgetAssume{display:none}
/* 2026-06-29 (explore opening — footer/estimate clearance) — trim the MOBILE top
   padding so the "Estimated cost — $X" headline sits higher (it's now the first
   thing the visitor sees after the landing scroll-to-top); was 1.25rem. Demo-only;
   desktop padding (above) is unchanged. */
@media (max-width: 680px) { body.vx-demo-active #vxDemoEstimateSurface { padding: 0.25rem 1.25rem 0.5rem; } }
/* (2026-08-04 — the demo-only .bridge override is GONE, and that is the point.
   It existed for one day because the GLOBAL mobile offset over-reserved for the
   totals strip, and the demo hides that strip, so the demo could afford to sit
   higher. The global rule (~line 6150) is now derived from the header's own
   height instead of a round number, which makes it tight for everyone — so the
   demo needs no exception, and demo / early-access / account share one offset
   again. Removing the fork is worth more than the 4px it was buying.) */
/* 2026-06-29 (explore opening — footer/estimate clearance) — the concierge footer
   is position:fixed;bottom:0 (~118px tall: 88px min-height + 30px padding), so its
   last rows could overlap the bottom of the demo budget. Reserve clearance equal to
   the footer height so the footer never sits on top of budget content. Demo-only
   (body.vx-demo-active); subscribers' #section-budget is untouched. */
body.vx-demo-active #section-budget { padding-bottom: 140px; } /* 2026-07-04: was 120px; +20px for the step title's 2-line clamp */
/* 2026-07-27 (Stephen) — Budget line items were eating screen height: 14px/14px padding
   and a 16px name (bigger than the 13px category titles). Tighten the padding and bring the
   name to the category-title size so the hierarchy reads right.
   2026-07-28 — un-scoped from the demo (was body.vx-demo-active): give active accounts the same
   tighter density so the demo + logged-in budgets read the same (Stephen). NOTE the !important:
   un-scoping dropped the demo selector's specificity, so without it the base .vxb-item rule
   (padding:14px, later in source ~L8940/L9045) wins and the tightening silently no-ops. */
#section-budget .vxb-item { padding-top: 6px !important; padding-bottom: 6px !important; }
#section-budget .vxb-item-name { font-size: .78rem !important; }
/* 2026-07-28 (Stephen) — declutter the ACTIVE budget to match the demo's calm: hide the bulk
   "Skip all" + the reset-to-median ↺ controls (category AND per-line) for EVERYONE.
   (2026-08-13: the per-line Skip tag this note used to protect is DELETED — Stephen,
   "skip on the line header is confusing and redundant to $0". Excluding a line is now
   the None segment in the expand, which values it at $0. .vxb-item-priority remains for
   the non-Gen4 fallback and stays demo-hidden below.)
   These three were moved OUT of the demo §2 block; this is now their single source of truth. */
#section-budget .vxb-bulk-toggle,      /* category / sub-group bulk "Skip all" */
#section-budget .vxb-reset-medians,    /* category / sub-group reset-to-benchmark ↺ */
#section-budget .vxb-item-reset { display: none !important; }   /* per-line reset-to-median ↺ */
/* (2026-08-04 — the bare "Package price" input was briefly hidden here on 08-03; it is now
   DELETED outright — renderer, handlers, and styles. Usage audit behind that call: 14 of 15
   real package prices were lock-backed (pinned through Lock → categoryLocks, which works),
   and the bare typed input was ignored by the Gen7 planner AND deleted at the next hydrate.
   Lock is the single sanctioned way to pin a category. Nothing to hide any more.) */
/* 2026-06-29 (explore opening) — DROP the budget page-title H1 in the demo. Its role
   (the "wedding style" framing) now lives as a synced wedding-style pill row rendered
   inside the demo estimate surface (#vxDemoEstimateSurface), so the redundant H1 is
   hidden. Demo-only (body.vx-demo-active); subscribers keep the H1 untouched. */
body.vx-demo-active #section-budget .vx-budget-page-title { display: none !important; }

/* (§2) Hide every PLANNING control in the demo budget — these are the paid upgrade.
   The read-only category sections + their per-line dollar values stay visible. */
body.vx-demo-active #vxBudgetTotalsStrip,                 /* Allocated / Budget / Remaining strip (replaced by the headline) */
body.vx-demo-active #vxBudgetAdvisorNote,                 /* "What will this cost?" advisor prose (planning-move references) */
body.vx-demo-active #vxBudgetPlanSummary,                 /* page-title sub: "Click Optimize / Resize…" planning copy */
body.vx-demo-active #section-budget .vxb-toolbar,         /* Optimize / Resize / Save PDF / Collapse all toolbar */
body.vx-demo-active #section-budget .vxb-section-foundation, /* "Your budget" foundation block (orphaned today — defensive) */
body.vx-demo-active #section-budget #vxbFundingBanner,
body.vx-demo-active #section-budget .vxb-funding-banner,
body.vx-demo-active #section-budget #vxFundingStatus,
body.vx-demo-active #section-budget .vxb-item-priority,   /* per-line Must / Nice / Skip band control */
/* NOTE: the per-line $/$$/$$$/$$$$ quality control is INTENTIONALLY SHOWN in the demo —
   it is the visitor's interactive "test a different scenario" control (change a line's
   quality, watch the estimate move). It lives inside the line's expand
   (.vxb-item-detail → "Quality tier" → .vxb-tier-segs), reached via the per-line
   chevron; interactive in demo, no gate. Do NOT hide it there.
   (2026-08-13: the older .vxb-band-cycle pill this note used to name is deleted — it
   had rendered nowhere for weeks. .vxb-tier-segs is the control now.) */
/* .vxb-item-reset / .vxb-bulk-toggle / .vxb-reset-medians (per-line reset ↺ / bulk "Skip all" /
   category reset ↺) moved OUT of this demo-only block on 2026-07-28 — now hidden for EVERYONE
   via the universal declutter rule above (Stephen: match the demo's calm on active accounts).
   Don't re-add them here. */
body.vx-demo-active #section-budget .vxc-lock-cta,        /* category Lock CTA */
body.vx-demo-active #section-budget .vxc-lock-chrome,     /* lock chrome wrapper */
body.vx-demo-active #section-budget .vxb-quality-row,     /* Tier Estimator Quality pill (paid planning control) */
body.vx-marquee-demo #section-budget .vxb-quality-row,    /* …also hidden in the marquee demo */
/* (§3) Hide the only visible "extra" beyond the per-category estimate: the Tips
   reserve card. (There is no separate .vxb-section[data-cat="contingency"] — the
   mount renders only category sections + this Tips reserve card; the allocated
   plan's contingency/topper lives in the now-hidden totals strip.) Hiding it keeps
   the visible category sections summing to the estimate headline. */
body.vx-demo-active #section-budget .vxb-tips-section { display:none !important; }

/* (§7) Keep the per-line amount INPUTS read-only in the demo (pointer-events off +
   muted) so the math is visible but not editable — editing is the paid upgrade. The
   section expand toggle (data-cat-expand) stays fully interactive so "look at the
   math underneath" pays off. */
body.vx-demo-active #section-budget .vxb-amount-input { pointer-events:none !important; background:transparent !important; border-color:transparent !important; cursor:default !important; }
/* 2026-05-11 — Demo-mode lockdown. Visitors who accidentally land on
   surfaces other than Vera (or who want to poke around after the
   workflow exits) should NOT be able to:
   · Edit Wedding Details (the seeded profile is what every story
     builds on — corrupting it breaks subsequent demos)
   · Export PDFs (marketing-quality artifacts shouldn't ship from a
     throwaway session)
   · Invite real partners to a soon-to-be-deleted wedding
   · Modify auth (passkeys / passwords on a throwaway account is moot)
   The header avatar still lets the visitor sign out. */
body.vx-demo-active [data-acc-tab="shared"],
body.vx-demo-active [data-acc-panel="shared"],
body.vx-demo-active [data-acc-tab="account"],
body.vx-demo-active [data-acc-panel="account"],
body.vx-demo-active #btn-pdf,
body.vx-demo-active #vxbPrintBudget,
body.vx-demo-active button[onclick*="saveBudgetPDF"],
body.vx-demo-active button[onclick*="savePDF"],
body.vx-demo-active button[onclick*="window.print"],
body.vx-demo-active button[data-action="print"],
body.vx-demo-active .vx-invite-card { display:none !important }
/* 2026-05-19 — Phase nav (Compare/Interview/Follow-up) stays visible in
   demo. Without it the visitor has no orientation cue inside Vendor+ and
   can't navigate back to verify a locked vendor landed in the Compare
   table. The inline Back/Go phase-actions remain hidden — those are
   redundant with the tab strip and tempted visitors off the guided path.
   Earlier rule (2026-05-11) hid both; revisited after Stephen flagged
   the missing orientation as a usability blocker. */
body.vx-demo-active .phase-actions { display:none !important }
/* 2026-08-03 — Wedding Details READ-ONLY LOCKDOWN REMOVED (CSS + the JS
   readonly/disabled pass that paired with it). The demo is now always the
   editable free-explore sandbox, so the lock (and its "Demo mode · Wedding
   Details are read-only — sign up to plan your own" banner) had no remaining
   purpose: it was the last thing making the demo look and behave differently
   from a real account. Edits land on the visitor's own ephemeral is_demo
   wedding row (24h TTL), so containment is unchanged. The matching
   vx-try-yourself-active revert rules went with it — nothing left to revert. */
/* Top-tab lockdown — 2026-07-26 (C): Chat is now OPEN in the demo (cited web-research Vera
   is the differentiator — let visitors feel it, capped at 5 turns server-side). Only
   Contracts+ (#sn-3) stays a locked premium add; its tooltip + treatment carry the
   "sign up to unlock" cue. */
body.vx-demo-active #sn-3,
body.vx-demo-active #sn-3:hover {
  opacity:.42 !important;
  /* 2026-07-31 (Stephen) — pointer-events stays ON so the hover-reveal call-out fires
     (the JS intercepts the CLICK to keep the locked surface unreachable, then opens the
     "Save your plan" unlock nudge — see _wireDeskNavCoach). Was pointer-events:none, which
     also killed hover. Cursor is a pointer (the click now DOES something: it unlocks). */
  cursor:pointer !important;
  position:relative;
}
body.vx-demo-active #sn-3 .sn-name::after {
  content:" 🔒";
  font-size:.78em;
  margin-left:3px;
  opacity:.8;
}
body.vx-demo-active #sn-3:hover .sn-name {
  text-decoration:none;
}

/* 2026-05-19 — Try-yourself mode overrides. When the visitor exits the
   marquee demo into "Try it yourself", the experience should feel like
   a real subscriber's sandbox — they can edit Wedding Details, browse
   any unlocked tab, print/save PDFs, etc. Chat + Contracts+ stay
   paywalled (still gated by .vx-demo-active above; .vx-try-yourself-active
   does NOT override those — those are the upgrade hooks). */
body.vx-try-yourself-active [data-acc-tab="shared"],
body.vx-try-yourself-active [data-acc-panel="shared"],
body.vx-try-yourself-active [data-acc-tab="account"],
body.vx-try-yourself-active [data-acc-panel="account"],
body.vx-try-yourself-active #btn-pdf,
body.vx-try-yourself-active #vxbPrintBudget,
body.vx-try-yourself-active button[onclick*="saveBudgetPDF"],
body.vx-try-yourself-active button[onclick*="savePDF"],
body.vx-try-yourself-active button[onclick*="window.print"],
body.vx-try-yourself-active button[data-action="print"],
body.vx-try-yourself-active .vx-invite-card {
  display: revert !important;
}
body.vx-try-yourself-active .phase-actions {
  display: revert !important;
}
/* 2026-08-03 — the vx-try-yourself-active Wedding-Details revert rules were
   removed with the lockdown they existed to undo. Nothing to revert now: the
   demo ships editable by default. */

/* ═══ Demo containment (2026-07-19) ══════════════════════════════════
   A throwaway session must not leave durable artifacts behind. Placed
   AFTER the try-yourself overrides on purpose: try-yourself reverts the
   marquee demo's tab hides, so it is the leakier of the two modes and
   both need naming explicitly.

   Two leaks, found by driving a simulated demo session:
     · Wallpaper upload — the Wedding Details lockdown greys inputs,
       selects, textareas and button[type="submit"], but these controls
       are type="button" and slipped the selector entirely: "Choose
       photo" opened a real file picker and uploaded for real. Storage
       has no FK to weddings, so cron-cleanup-demo-weddings reclaims the
       row and the auth user but never those bytes — they are stranded
       permanently.
     · Wallet pass — reachable from the Tasks bar in demo, and from the
       account panel too once try-yourself reverts that hide. The DB
       side self-cleans (wedding_wallet_passes CASCADEs on wedding_id),
       but it installs a signed .pkpass on a real device that keeps
       counting down to a wedding we delete overnight.

   Passkeys need no rule here — enrollment is gated server-side by
   mark_email_login_verified(), which a demo account can never satisfy.
   The wallpaper's real guard is likewise server-side (RLS on the
   wallpapers bucket); this is the visible half. */
body.vx-demo-active #vxWdWallpaperFs .vx-wp-actions button,
body.vx-try-yourself-active #vxWdWallpaperFs .vx-wp-actions button {
  pointer-events: none !important;
  opacity: .55;
  cursor: not-allowed !important;
  background-color: rgba(0,0,0,.025) !important;
}
body.vx-demo-active #vxTasksWalletPass,
body.vx-try-yourself-active #vxTasksWalletPass,
body.vx-demo-active #vxWalletPassFieldset,
body.vx-try-yourself-active #vxWalletPassFieldset {
  display: none !important;
}
/* Say why the control is dead rather than leaving it mysteriously grey.
   Try-yourself makes the rest of this panel editable and hides the
   panel's read-only banner, so nothing else would explain it. */
.vx-wp-demo-note { display: none }
body.vx-demo-active .vx-wp-demo-note,
body.vx-try-yourself-active .vx-wp-demo-note {
  display: block;
  margin-top: 10px;
  font-family: var(--ff-m,'DM Mono',monospace);
  font-size: 11px;
  letter-spacing: .05em;
  color: var(--bronze, #7A5A2A);
}
/* Size and format limits describe an upload they can't perform — drop
   them so the note is the only thing speaking. */
body.vx-demo-active .vx-wp-upload-help,
body.vx-try-yourself-active .vx-wp-upload-help { display: none }

.vx-vera-form{display:flex;flex-direction:column;gap:10px;margin:0}
.vx-vera-input{width:100%;min-height:62px;padding:14px 16px;border:1.5px solid rgba(44,74,62,.18);border-radius:14px;background:var(--white);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;line-height:1.5;color:var(--ink);resize:vertical;transition:border-color .18s,box-shadow .18s}
.vx-vera-input::placeholder{color:var(--text-muted);font-style:italic}
.vx-vera-input:focus{outline:none;border-color:var(--green);box-shadow:0 0 0 3px rgba(44,74,62,.08)}
.vx-vera-submit{appearance:none;background:var(--green);color:var(--white);border:none;border-radius:12px;padding:13px 24px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;font-weight:500;letter-spacing:.02em;cursor:pointer;transition:background .15s,transform .08s}
.vx-vera-submit:hover{background:var(--green-deep,#1f3528)}
.vx-vera-submit:active{transform:translateY(1px)}
.vx-vera-submit:disabled{background:var(--text-muted);cursor:not-allowed;opacity:.7}
.vx-vera-skip{margin-top:22px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;color:var(--text-muted)}
.vx-vera-skip a{color:var(--text-mid);text-decoration:none;border-bottom:1px dotted rgba(44,74,62,.3);padding-bottom:1px;transition:color .15s,border-color .15s}
.vx-vera-skip a:hover{color:var(--green);border-bottom-color:var(--green)}

/* Plan + step rendering — consent cards land below the hero card on submit */
.vx-vera-plan-wrap{max-width:720px;margin:0 auto;padding:0 20px 64px}
.vx-vera-plan-loading{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.05rem;font-style:italic;color:var(--text-mid);text-align:center;padding:32px 0}
.vx-vera-plan-card{background:var(--white);border:1px solid rgba(44,74,62,.12);border-radius:18px;padding:28px clamp(20px,4vw,40px);margin-bottom:18px;box-shadow:0 6px 24px rgba(28,28,28,.06)}
.vx-vera-plan-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.55rem;font-weight:400;color:var(--green);margin:0 0 6px;line-height:1.25}
.vx-vera-plan-title em{color:var(--gold);font-style:italic}
.vx-vera-plan-time{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted);margin:0 0 18px}
.vx-vera-plan-intro{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.05rem;color:var(--text-mid);line-height:1.55;font-style:italic;margin:0 0 22px}
.vx-vera-step{padding:14px 18px;margin:10px 0;border-left:2px solid var(--gold);background:rgba(250,247,242,.6);border-radius:0 10px 10px 0}
.vx-vera-step-kind{display:inline-block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin-bottom:5px;font-weight:500}
.vx-vera-step[data-kind="write"] { border-left-color:var(--green-mid,#3a6b59) }
.vx-vera-step[data-kind="write"] .vx-vera-step-kind { color:var(--green-mid,#3a6b59) }
.vx-vera-step[data-kind="narrate"] { border-left-color:rgba(200,169,110,.55) }
.vx-vera-step-text{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;color:var(--charcoal,#2a2a2a);line-height:1.55;margin:0 0 4px}
.vx-vera-step-why{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:.88rem;color:var(--text-muted);font-style:italic;line-height:1.5;margin:4px 0 0}
.vx-vera-consent{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.vx-vera-consent button{appearance:none;border:1.5px solid var(--border-g,rgba(44,74,62,.2));background:var(--white);color:var(--text-mid);padding:9px 16px;border-radius:10px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;cursor:pointer;transition:all .15s}
.vx-vera-consent button.primary{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-vera-consent button.primary:hover{background:var(--green-deep,#1f3528)}
.vx-vera-consent button:not(.primary):hover{background:var(--green-pale,#eaf0ed);color:var(--green);border-color:var(--green)}
.vx-vera-followup{margin:24px 0 0;padding:18px 20px;border-top:1px dashed var(--border,rgba(28,28,28,.08));text-align:center}
.vx-vera-followup-q{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;font-style:italic;color:var(--green);margin:0 0 10px}
.vx-vera-restart{appearance:none;background:transparent;border:1px solid var(--border-g,rgba(44,74,62,.25));color:var(--text-mid);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:8px 16px;border-radius:999px;cursor:pointer;transition:all .15s}
.vx-vera-restart:hover{background:var(--green-pale,#eaf0ed);color:var(--green);border-color:var(--green)}
@media (max-width:560px){
  .vx-vera-card{padding:24px 20px 30px;border-radius:18px}
  /* Header collapses to vertical stack on phones — portrait centered
     above the text. Grid → flex-column for clean stacking. */
  .vx-vera-header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;margin-bottom:18px}
  .vx-vera-header-text{text-align:center;padding-top:0}
  .vx-vera-portrait{width:120px;max-width:120px;height:120px;aspect-ratio:auto;box-shadow:0 0 0 8px var(--cream),0 0 0 9px rgba(200,169,110,.24),0 0 22px rgba(28,28,28,.05)}
  .vx-vera-headline{font-size:1.8rem}
  .vx-vera-intro{font-size:.98rem;max-width:none}
  .vx-vera-question{font-size:1.2rem;text-align:center;margin-top:12px}
}
/* Off-platform mini-plan card — rendered when the AI plan generator
   produces a printable plan for tasks Verdeaux can't directly execute
   (vows, family diplomacy, seating chart). Same brand register as the
   Vera plan card; numbered ordered list with cream backplates. */
.vx-vera-mini-plan{background:var(--white);border:1px solid rgba(44,74,62,.12);border-radius:18px;padding:32px clamp(20px,4vw,44px);margin-bottom:18px;box-shadow:0 6px 24px rgba(28,28,28,.06)}
.vx-vera-mini-plan-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 10px}
.vx-vera-mini-steps{list-style:none;padding:0;margin:14px 0 18px;counter-reset:vxStep}
.vx-vera-mini-step{display:flex;gap:16px;padding:14px 0;border-bottom:1px dashed rgba(28,28,28,.08)}
.vx-vera-mini-step:last-child{border-bottom:none}
.vx-vera-mini-step-num{flex:0 0 36px;width:36px;height:36px;border-radius:50%;background:var(--cream,#FAF7F2);border:1px solid rgba(200,169,110,.45);color:var(--gold-deep,#A07840);font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;line-height:34px;text-align:center;font-weight:500}
.vx-vera-mini-step-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.18rem;font-weight:400;color:var(--green);margin:0 0 6px;line-height:1.3}
.vx-vera-mini-step-text{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;color:var(--charcoal,#2a2a2a);line-height:1.6;margin:0}
.vx-vera-mini-closing{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1rem;font-style:italic;color:var(--text-mid);margin:18px 0 0;padding-top:14px;border-top:1px solid rgba(28,28,28,.06)}
.vx-vera-mini-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px}
.vx-vera-mini-btn{appearance:none;background:var(--white);border:1px solid var(--border-g,rgba(44,74,62,.25));color:var(--text-mid);padding:10px 18px;border-radius:10px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;cursor:pointer;transition:all .15s}
.vx-vera-mini-btn:hover{background:var(--green-pale,#eaf0ed);color:var(--green);border-color:var(--green)}
.vx-vera-mini-btn:disabled{opacity:.7;cursor:not-allowed}

/* Print stylesheet — when window.print() is invoked from the off-
   platform plan card, _vxVeraMiniAction clones the card into a
   #vx-print-host node attached directly to body. We hide every direct
   body child except that host, print, then unmount the host on
   afterprint. This isolation strategy is independent of upstream DOM
   nesting so it survives layout refactors. */
#vx-print-host{display:none}
@media print {
  html.vx-printing-vera-plan body > *{display:none !important}
  html.vx-printing-vera-plan body > #vx-print-host{display:block !important}
  html.vx-printing-vera-plan #vx-print-host [data-print-hide="1"]{display:none !important}
  html.vx-printing-vera-plan #vx-print-host .vx-vera-mini-plan{box-shadow:none;border:1px solid #ccc;page-break-inside:avoid;margin:0}
  html.vx-printing-vera-plan body{padding:0 !important;background:#fff !important}
}

/* ═══ End Vera ══════════════════════════════════════════════════════ */

/* ═══ Vera Concierge — guided-walkthrough footer (2026-05-09) ═══════
   Persistent footer (or floating panel on desktop) that shows the
   current step of a Vera-launched workflow. Travels with the user
   across surfaces — same footer, instruction copy adapts to whichever
   tab the user is on. Brand register matches the Vera intro: cream
   card, gold accent, Cormorant headlines, DM Sans body. */
.vx-concierge-footer{position:fixed;left:0;right:0;bottom:0;z-index:950;background:rgba(250,247,242,.96);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-top:1px solid rgba(200,169,110,.32);box-shadow:0 -8px 32px rgba(28,28,28,.10);padding:14px clamp(16px,4vw,32px) 16px;animation:vxConFadeIn .32s cubic-bezier(.22,1.2,.36,1)}
.vx-concierge-footer[hidden]{display:none}
@keyframes vxConFadeIn{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
.vx-concierge-card{
  max-width:1100px;margin:0 auto;
  display:grid;grid-template-columns:48px 1fr auto;
  gap:18px;align-items:center;position:relative;
  /* 2026-05-13 — Pinned minimum height so the footer doesn't resize
     between steps when instruction text length varies. Demo viewers
     can read each step without their eye chasing the Continue button
     up and down. Same value desktop + mobile so feel is consistent. */
  min-height:88px
}
/* 2026-05-11 — Processing overlay. Two flavors:
   · default (concierge-card overlay) — used in the live app where the
     visitor is task-focused; small ring on the card itself.
   · demo (centered modal popup) — used in /demo sessions where the
     visitor needs an unmistakable "Vera is running live" signal.
   The popup variant gets a backdrop blur + dim and stays centered so
   it's the clear focal point during demo fires. */
.vx-concierge-processing{position:absolute;inset:-14px -16px;background:rgba(250,247,242,.96);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;gap:18px;border-radius:8px;z-index:5;animation:vxCpFade .22s ease}
@keyframes vxCpFade{from{opacity:0}to{opacity:1}}
.vx-cp-ring{width:32px;height:32px;border:2.5px solid rgba(200,169,110,.18);border-top-color:var(--gold);border-right-color:var(--gold);border-radius:50%;animation:vxCpSpin .8s linear infinite;flex-shrink:0}
@keyframes vxCpSpin{to{transform:rotate(360deg)}}
.vx-cp-text{display:flex;flex-direction:column;gap:4px;min-width:0;max-width:560px}
.vx-cp-label{font-family:var(--ff-m,'DM Mono',monospace);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);font-weight:500}
.vx-cp-phase{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.05rem;color:var(--green);line-height:1.3;font-style:italic}
/* Demo popup — centered, fixed, full-viewport backdrop dim. */
.vx-cp-popup-backdrop{position:fixed;inset:0;z-index:9990;background:rgba(28,28,28,.42);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;animation:vxCpFade .22s ease}
.vx-cp-popup{background:var(--white,#FEFCF8);border:1px solid rgba(200,169,110,.4);border-radius:20px;padding:36px 44px;box-shadow:0 32px 80px rgba(28,28,28,.28);display:flex;flex-direction:column;align-items:center;gap:18px;max-width:520px;text-align:center;animation:vxCpPopIn .32s cubic-bezier(.22,1.2,.36,1)}
@keyframes vxCpPopIn{from{transform:translateY(8px) scale(.96);opacity:0}to{transform:none;opacity:1}}
.vx-cp-popup .vx-cp-ring{width:56px;height:56px;border-width:3px}
.vx-cp-popup .vx-cp-label{font-size:11.5px;letter-spacing:.16em}
.vx-cp-popup .vx-cp-phase{font-size:1.4rem;color:var(--green);line-height:1.25}
/* 2026-05-11 — Pulse highlight applied to a budget section right after
   a demo lock fires, so the visitor sees the row "celebrate" the
   value change ($5,523 → $11,000) instead of missing it.
   2026-05-13 — Generalized: `.vx-action-pulse` is the canonical name
   for live Vera actions (any successful execute step), `.vx-demo-pulse`
   stays as a stable alias so existing demo-only call-sites don't break.
   Both render the same keyframe. */
.vx-demo-pulse,
.vx-action-pulse{animation:vxDemoPulse 1.8s ease}
@keyframes vxDemoPulse{
  0%   { box-shadow: 0 0 0 0 rgba(83,126,90,0); background:transparent }
  20%  { box-shadow: 0 0 0 4px rgba(83,126,90,.22); background:rgba(83,126,90,.06) }
  60%  { box-shadow: 0 0 0 4px rgba(200,169,110,.18); background:rgba(200,169,110,.06) }
  100% { box-shadow: 0 0 0 0 rgba(200,169,110,0); background:transparent }
}
/* Demo-mode replacement card inside the step body — soft amber accent
   so the visitor reads it as "what would happen here," not real action.
   2026-05-14 — Sub-component sizing aligned with the standard step
   eyebrow + title so visitors don't perceive subtle drift between
   real steps and preview cards. The visual differentiation comes from
   the card's wrapping context (it sits inside the instruction slot,
   not as a top-level step), not from font-size variance. */
.vx-concierge-demo-replacement{padding:10px 0}
.vx-concierge-demo-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);font-weight:500;margin-bottom:6px}
.vx-concierge-demo-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;color:var(--green);font-style:italic;line-height:1.25;margin-bottom:6px}
.vx-concierge-demo-body{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;color:var(--text-mid,#4A4A4A);line-height:1.55}
.vx-concierge-avatar{width:48px;height:48px;border-radius:50%;object-fit:cover;background:var(--cream);box-shadow:0 0 0 3px var(--cream),0 0 0 4px rgba(200,169,110,.32),0 0 12px rgba(28,28,28,.06)}
.vx-concierge-body{
  min-width:0;
  /* 2026-05-13 — Cross-fade transition between steps. The .vx-step-anim
     class is toggled by _render() on every step change: removed, reflow
     forced, re-added — which re-triggers the keyframe. Content fades
     down + slightly translates up on entry, giving a deliberate
     editorial feel instead of a hard innerHTML swap. */
  display:flex;flex-direction:column;justify-content:center;
}
.vx-concierge-body.vx-step-anim{animation:vxStepFade 420ms cubic-bezier(.22,1,.36,1) both}
@keyframes vxStepFade{
  from{opacity:0;transform:translateY(6px)}
  to{opacity:1;transform:translateY(0)}
}

/* 2026-05-13 — Premium demo backdrop. Subtle vignette dim across the
   page when BOTH demo AND concierge are active, layered BEHIND the
   footer (z 940 < footer 950) but ABOVE normal page content. Creates
   a stage-light feel — Vera's script + the highlighted surface
   above are clearly the focal points. Cinematic without being heavy. */
body.vx-demo-active.vx-concierge-active::after{
  content:'';position:fixed;inset:0;
  background:linear-gradient(180deg,rgba(28,28,28,0) 30%,rgba(28,28,28,.07) 100%);
  pointer-events:none;z-index:940;
  animation:vxDemoBackdropFadeIn 480ms ease both;
}
@keyframes vxDemoBackdropFadeIn{from{opacity:0}to{opacity:1}}
.vx-concierge-meta{display:flex;align-items:center;gap:12px;margin-bottom:3px;flex-wrap:wrap}
.vx-concierge-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);font-weight:500}
.vx-concierge-progress{font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);font-weight:500}
.vx-concierge-step-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;font-weight:400;color:var(--green);margin:0 0 2px;line-height:1.25}
.vx-concierge-step-title em{color:var(--gold);font-style:italic}
.vx-concierge-step-instruction{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;color:var(--text-mid);line-height:1.5;margin:0}
.vx-concierge-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}
.vx-concierge-btn{appearance:none;border:1.5px solid transparent;border-radius:10px;padding:9px 16px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:500;cursor:pointer;transition:all .15s;white-space:nowrap}
/* 2026-05-14 — Focus ring + disabled state. Same 2px gold / 3px
   offset pattern used by .vx-header-avatar:focus-visible. Disabled
   state was previously invisible (just the [disabled] attribute, no
   CSS). */
.vx-concierge-btn:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:3px}
.vx-concierge-btn:disabled{opacity:.55;cursor:not-allowed;background:rgba(44,74,62,.06);color:var(--text-muted);border-color:rgba(44,74,62,.12)}
.vx-concierge-btn-primary{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-concierge-btn-primary:hover{background:var(--green-deep,#1f3528)}
.vx-concierge-btn-ghost{background:transparent;color:var(--text-mid);border-color:rgba(44,74,62,.18)}
.vx-concierge-btn-ghost:hover{background:rgba(44,74,62,.06);color:var(--green);border-color:var(--green)}
.vx-concierge-dots{max-width:1100px;margin:10px auto 0;display:flex;justify-content:center;gap:6px}
.vx-concierge-dot{width:6px;height:6px;border-radius:50%;background:rgba(44,74,62,.2);transition:background .18s,transform .18s,box-shadow .18s}
.vx-concierge-dot.is-current{background:var(--green);transform:scale(1.4)}
.vx-concierge-dot.is-done{background:var(--gold)}
/* 2026-05-16 — Past-step dots are clickable for review-mode navigation.
   ::before expands hit area to ~24px without enlarging the visual dot.
   Hover ring + focus-visible outline communicate the affordance. */
.vx-concierge-dot.is-clickable{cursor:pointer;position:relative}
.vx-concierge-dot.is-clickable::before{content:'';position:absolute;inset:-9px;border-radius:50%}
.vx-concierge-dot.is-clickable:hover{box-shadow:0 0 0 4px rgba(200,169,110,.22)}
.vx-concierge-dot.is-clickable:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
/* When the footer is visible, push everything else up so it never covers content */
body.vx-concierge-active{padding-bottom:140px}
/* Section-specific bottom-padding for surfaces that have scrollable
   inner content (Chat) or fixed-bottom UI of their own. Without these,
   the footer overlays content the user needs to see. */
body.vx-concierge-active #section-ideas,
body.vx-concierge-active #section-budget,
body.vx-concierge-active #section-interviews,
body.vx-concierge-active #section-reviews,
body.vx-concierge-active #section-timeline,
body.vx-concierge-active #section-vera{padding-bottom:160px}
/* ═══ 2026-06-24 — DEMO SLIM FOOTER + CENTERED NARRATION POP-UP ═════════
   Redesign (replaces the #189 3-row mobile footer + the tall desktop
   narration footer FOR THE DEMO ONLY). In the marquee demo:
     · the footer collapses to ONE slim row: Vera (re-open note) ·
       "STEP X OF 6" + step title · Back · Forward · Exit;
     · the full step narration moves to the centered #vxConNote pop-up.
   ALL of this is gated on body.vx-marquee-demo (NOT vx-demo-active) — the live
   "Try it yourself" walkthrough runs NON-marquee workflows in the SAME footer
   and must keep the original footer (avatar + meta + inline narration +
   Mark-done/Exit) entirely unchanged. vx-marquee-demo is toggled in _render
   (demoNav) and removed in _exit / _demoTryYourself, so it is present ONLY
   during the marquee workflow. One responsive design, no media-query forking;
   gentle fade only (NO timed open/close behavior). */

/* — Slim footer (marquee demo only) — */
body.vx-marquee-demo .vx-concierge-card{
  /* avatar · body(meta+title) · Back · Forward · Exit, all on one row */
  grid-template-columns:40px minmax(0,1fr) auto;
  gap:12px;align-items:center;min-height:0;
}
body.vx-marquee-demo .vx-concierge-avatar{width:40px;height:40px;cursor:pointer}
body.vx-marquee-demo .vx-concierge-avatar:hover{box-shadow:0 0 0 3px var(--cream),0 0 0 5px rgba(200,169,110,.55),0 0 14px rgba(28,28,28,.10)}
body.vx-marquee-demo .vx-concierge-avatar:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:3px}
/* The full narration node is hidden in the marquee demo (it now lives in the
   pop-up); _render still WRITES it by id (canonical write target) and mirrors
   its innerHTML into #vxConNoteBody. Try-yourself keeps it VISIBLE. */
body.vx-marquee-demo #vxConStepInstruction{display:none}
/* 2026-07-04 (Stephen — mobile type pass) — the step title is Vera's script line;
   it must never truncate. Was white-space:nowrap + ellipsis, which cut "Your
   market budget — the realistic starting point" on phones. Allow up to TWO lines
   (line clamp), which fits every current step title at 320px-wide body columns;
   the footer clearance paddings below reserve room for the taller card. */
body.vx-marquee-demo .vx-concierge-step-title{font-size:1.02rem;margin:0;line-height:1.25;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
body.vx-marquee-demo .vx-concierge-meta{margin-bottom:1px}
body.vx-marquee-demo .vx-concierge-body{display:flex;flex-direction:column;justify-content:center;min-width:0}
body.vx-marquee-demo .vx-concierge-actions{flex-shrink:0}
/* 2026-07-27 (Stephen) — the guided-tour footer matches the new demo look: a floating
   rounded card (not a full-width bottom bar), pill buttons (was 10px rounded-rect), and no
   step-dots (the "steppy" element the new look drops). Marquee-demo scoped so the real-app
   concierge is untouched. */
body.vx-marquee-demo .vx-concierge-footer{left:12px;right:12px;bottom:12px;max-width:720px;margin:0 auto;border:1px solid rgba(44,74,62,.16);border-radius:16px;box-shadow:0 14px 40px rgba(28,28,28,.16)}
body.vx-marquee-demo .vx-concierge-btn{border-radius:40px}
body.vx-marquee-demo .vx-concierge-dots{display:none}
/* Slim footer ⇒ smaller body offset everywhere it's active. 2026-07-04 — +20px
   headroom (84→104 / 100→120) for the step title's second line now that the
   one-line ellipsis is gone (2-line clamp above). */
body.vx-marquee-demo.vx-concierge-active{padding-bottom:104px}
body.vx-marquee-demo.vx-concierge-active #section-ideas,
body.vx-marquee-demo.vx-concierge-active #section-budget,
body.vx-marquee-demo.vx-concierge-active #section-interviews,
body.vx-marquee-demo.vx-concierge-active #section-reviews,
body.vx-marquee-demo.vx-concierge-active #section-timeline,
body.vx-marquee-demo.vx-concierge-active #section-vera{padding-bottom:120px}
/* 2026-06-27 — BASE mobile reflow for the concierge footer (NON-marquee).
   The intro tour (_veraIntroTour) and live "Try it yourself" walkthrough run
   the footer WITHOUT body.vx-marquee-demo, so the marquee-scoped mobile rules
   below never applied to them — leaving the 3-col 48px/1fr/auto grid intact on
   phones, where the 4 nowrap action buttons + avatar starved the 1fr body
   column to ~1 word/line. This unscoped block reflows the base card so the
   avatar+body sit on row 1 and the actions wrap full-width on row 2. Desktop
   unchanged (mobile-only @media). Marquee demo keeps its own slim layout via
   the higher-specificity body.vx-marquee-demo rules below + the original
   marquee 560px block. */
@media (max-width:560px){
  .vx-concierge-card{ grid-template-columns:40px 1fr; grid-template-rows:auto auto; gap:10px 12px; align-items:start; min-height:0 }
  .vx-concierge-avatar{ grid-column:1; grid-row:1 }
  .vx-concierge-body{ grid-column:2; grid-row:1 }
  .vx-concierge-actions{ grid-column:1 / -1; grid-row:2; flex-wrap:wrap; justify-content:flex-start }
  .vx-concierge-actions .vx-concierge-btn{ flex:1 1 auto }
  body.vx-concierge-active{ padding-bottom:200px }
}
@media (max-width:560px){
  body.vx-marquee-demo .vx-concierge-card{grid-template-columns:32px minmax(0,1fr) auto;gap:8px}
  body.vx-marquee-demo .vx-concierge-avatar{width:32px;height:32px}
  body.vx-marquee-demo .vx-concierge-step-title{font-size:.92rem}
  body.vx-marquee-demo .vx-concierge-actions{gap:6px}
  body.vx-marquee-demo .vx-concierge-actions .vx-concierge-btn{padding:7px 9px;font-size:.74rem}
  /* 2026-07-26 (C) — slim the guided-tour footer on mobile: less vertical padding + a
     tighter step title so it eats less of the screen when a visitor opts into the tour. */
  body.vx-marquee-demo .vx-concierge-footer{padding:9px clamp(12px,3.5vw,20px) 11px}
  body.vx-marquee-demo .vx-concierge-step-title{font-size:.88rem;line-height:1.25}
  /* On the narrowest marquee viewports, hide the scenario eyebrow so the meta
     row stays single-line (STEP X OF 6 alone is enough orientation). */
  body.vx-marquee-demo #vxConWorkflowTitle{display:none}
}

/* — Centered narration pop-up (marquee demo only) —
   Scoped under body.vx-marquee-demo for parity with the slim-footer rules
   above. The #vxConNote node is static + hidden by default and only ever
   unhidden by the marquee-guarded _vxConOpenNote, so this is defense-in-depth. */
body.vx-marquee-demo .vx-con-note{position:fixed;inset:0;z-index:9970;display:flex;align-items:center;justify-content:center;padding:24px}
body.vx-marquee-demo .vx-con-note[hidden]{display:none}
body.vx-marquee-demo .vx-con-note-scrim{position:absolute;inset:0;background:rgba(28,28,28,.18);backdrop-filter:blur(1px);-webkit-backdrop-filter:blur(1px)}
body.vx-marquee-demo .vx-con-note-card{
  position:relative;z-index:1;
  background:var(--white,#FEFCF8);border:1px solid rgba(200,169,110,.40);
  border-radius:18px;box-shadow:0 28px 70px rgba(28,28,28,.24);
  max-width:min(560px,92vw);max-height:78vh;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:26px 30px 28px;
  animation:vxConNoteIn .26s cubic-bezier(.22,1.2,.36,1);
}
@keyframes vxConNoteIn{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
body.vx-marquee-demo .vx-con-note-close{
  position:absolute;top:12px;right:14px;width:32px;height:32px;line-height:1;
  appearance:none;border:0;border-radius:50%;background:rgba(44,74,62,.06);
  color:var(--text-mid,#4A4A4A);font-size:1.35rem;cursor:pointer;transition:background .14s,color .14s;
  display:flex;align-items:center;justify-content:center;
}
body.vx-marquee-demo .vx-con-note-close:hover{background:rgba(44,74,62,.12);color:var(--green)}
body.vx-marquee-demo .vx-con-note-close:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
body.vx-marquee-demo .vx-con-note-head{display:flex;align-items:center;gap:12px;margin:0 28px 12px 0}
body.vx-marquee-demo .vx-con-note-avatar{width:44px;height:44px;border-radius:50%;object-fit:cover;background:var(--cream);box-shadow:0 0 0 3px var(--cream),0 0 0 4px rgba(200,169,110,.32);flex-shrink:0}
body.vx-marquee-demo .vx-con-note-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.38rem;font-weight:400;color:var(--green);margin:0;line-height:1.2}
body.vx-marquee-demo .vx-con-note-title em{color:var(--gold);font-style:italic}
body.vx-marquee-demo .vx-con-note-body{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;color:var(--text-mid,#4A4A4A);line-height:1.6}
body.vx-marquee-demo .vx-con-note-body strong{color:var(--green);font-weight:600}
body.vx-marquee-demo .vx-con-note-body em{font-style:italic}
@media (max-width:560px){
  body.vx-marquee-demo .vx-con-note{padding:14px;align-items:flex-end}
  body.vx-marquee-demo .vx-con-note-card{max-width:100%;max-height:82vh;padding:22px 20px 24px;border-radius:16px 16px 0 0}
  body.vx-marquee-demo .vx-con-note-title{font-size:1.22rem}
}
/* ─── 2026-06-25 (marquee no-venues dead-end) — prominent pop-up shown when a
   visitor enters a ZIP with no bookable wedding venues (after the widen
   escalation exhausts). The rest of the demo (Compare → corridor → Map) all
   build on real venues, so a no-venues result is a DEAD END: this gives a clear
   pop-up + Restart back to the quick-entry box (try a bigger nearby city)
   instead of relying on the soft inline sparse-note. Reuses .vx-con-note*
   structure/styling (same centered modal); only the Restart action button is
   new. Scoped to body.vx-marquee-demo for parity; the #vxConNoVenues node is
   static + hidden by default and only ever unhidden by the marquee-guarded
   _vxMarqueeNoVenuesGraceful, so this is defense-in-depth. */
body.vx-marquee-demo .vx-con-note-actions{display:flex;justify-content:flex-end;margin-top:18px}
body.vx-marquee-demo .vx-con-note-btn{
  font-family:var(--ff-m,monospace);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;
  background:var(--green,#2C4A3E);color:var(--cream,#FBF8F2);border:none;border-radius:8px;
  padding:11px 20px;cursor:pointer;transition:background .15s,box-shadow .15s;
}
body.vx-marquee-demo .vx-con-note-btn:hover{background:var(--green-deep,#22382F);box-shadow:0 4px 14px rgba(28,28,28,.14)}
body.vx-marquee-demo .vx-con-note-btn:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
/* ═══ End Concierge footer ═════════════════════════════════════════ */

.handoff {
 background: rgba(200,169,110,.06); border: 1px solid rgba(200,169,110,.2);
 border-top: none; border-radius: 0 0 14px 14px;
 padding: .8rem 1.4rem; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.handoff-label { font-family: var(--ff-m); font-size: .54rem; letter-spacing: .12em; text-transform: uppercase; color: var(--gold-deep); white-space: nowrap; }
.handoff-pills { display: flex; flex-wrap: wrap; gap: 5px; }
.h-pill { background: white; border: 1px solid var(--border-g); border-radius: 6px; padding: 3px 10px; font-size: .73rem; color: var(--ink-mid); }
.h-pill strong { font-weight: 500; color: var(--ink); }
.h-pill.h-pill-ideas { background: rgba(200,169,110,.08); border-color: rgba(200,169,110,.35); color: var(--ink-mid); position: relative; }
.h-pill.h-pill-ideas strong { color: var(--gold-deep); }
.h-pill.h-pill-ideas::before { content: ""; color: var(--gold); margin-right: 5px; font-size: .82rem; line-height: 0; vertical-align: middle; }
.h-pill.h-pill-ideas-sit { max-width: 360px; }
.ideas-handoff-clear { margin-left: auto; background: none; border: none; font-family:var(--ff-b,'DM Sans',sans-serif); font-size:.8rem; letter-spacing:normal; color: var(--ink-faint); cursor: pointer; display: inline-flex; align-items: center; gap: 3px; padding: 4px 6px; border-radius: 4px; transition: color .12s, background .12s; }
.ideas-handoff-clear:hover { color: var(--danger); background: rgba(185,64,64,.05); }

/* 2026-04-30: Stephen reported Compare Proposals leaking onto Chat +
   Up Next pages. The plain `display: none` rule was being beaten by
   something in the cascade. !important ensures non-active sections
   stay invisible regardless. JS routing also enforces inline style. */
.section-page { display: none !important; }
.section-page.active { display: block !important; }

.budget-intro { position: relative; z-index: 1; max-width: 900px; margin: 1.5rem auto 0; padding: 0 2rem; display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.budget-intro-heading { font-family: var(--ff-d); font-size: clamp(1.5rem,3vw,2rem); font-weight: 400; color: var(--green); letter-spacing: -.01em; line-height: 1.1; }
.budget-intro-heading em { font-style: italic; color: var(--gold); }
.budget-intro-meta { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.budget-intro-stat { display: flex; align-items: baseline; gap: 5px; }
.budget-intro-num { font-family: var(--ff-d); font-size: 1.25rem; font-weight: 400; color: var(--charcoal); }
.budget-intro-num.italic { color: var(--gold); font-style: italic; }
.budget-intro-lbl { font-family: var(--ff-m); font-size: .56rem; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); }
.budget-intro-sep { width: 1px; height: 22px; background: var(--border-g); flex-shrink: 0; }

.divider { height: 1px; background: linear-gradient(90deg,transparent,rgba(200,169,110,.3),transparent); max-width: 1200px; margin: 0 auto; }
/* 2026-05-01 Slice 5.7b: Budget page is single-column. The 320px sidebar
   (Live Total, Category breakdown, What-If) was retired — gap headline
   replaces Live Total, the category list IS the breakdown, and the
   slider model that What-If depended on is gone. Widths match
   .timeline-wrap on the Scouting page so navigation between Budget
   and Scouting reads as one centered column at every breakpoint. */
.tool-grid { display: grid; grid-template-columns: 1fr; gap: 28px; align-items: start; padding: 1.75rem 2rem 80px; max-width: 900px; margin: 0 auto; position: relative; z-index: 1; }

/* ── Slice 5.7b: gap headline, locked rows, feedback slot, empty state ── */
/* 2026-05-02: gap headline visually retired — its job (state the dollar
   gap up top) moved into the body sentence Opus produces in the advisor
   note below. The IIFE that powered it still runs (its listeners are
   harmless) but the rendered output is hidden so "What will this cost?"
   becomes the editorial page-top headline. Keep the empty-state nudge
   (no funding set yet) by routing it through the no_funding template in
   _vxAdvisorNote — same prompt, new slot. */
.vx-gap-headline { display: none !important; }
/* 2026-05-04: hero scale unified to .ss-hero (Insights canonical). */
.vx-gap-headline-lead { font-family: var(--ff-d); font-size: clamp(2rem,5vw,3rem); font-weight: 400; color: var(--green); line-height: 1.05; margin: 0 0 .75rem; }
.vx-gap-headline-lead em { font-style: italic; color: var(--gold); }
.vx-gap-headline-lead.is-over em { color: var(--amber-risk); }
.vx-gap-headline-lead.is-severe em { color: var(--danger); }
.vx-gap-headline-sub { font-family: var(--ff-b); font-size: .88rem; color: var(--text-muted); line-height: 1.65; max-width: 580px; margin: 0; }
.vx-gap-headline-sub a { color: inherit; text-decoration: underline; cursor: pointer; }
/* 2026-05-02 v4 advisor note — mirrors Vendor IQ's .page-title /
   .pt-heading / .pt-sub pattern so alignment, color, and weight match
   across surfaces. Heading is upright green (the question mark carries
   energy on its own; italic was redundant). Eyebrow is regular
   sentence-case prose, not mono uppercase — matches .pt-sub. Body is
   slightly looser (1rem, line-height 1.6) to give the 2-3 Opus
   sentences room to breathe. */
.vx-advisor-note { position: relative; z-index: 1; max-width: 820px; margin: 0 auto; padding: 1rem 2rem 1.4rem; }
.vx-advisor-note:empty { display: none; }
/* 2026-05-06 — height lock for the Budget advisor note. Re-analysis
 *   fires after every line-item toggle; without a reserved height the
 *   surrounding rows bounce as the paragraph grows/shrinks. min-height
 *   covers ~5-6 lines at the body's line-height (1.6) — the typical
 *   factual-observation length. Longer notes still expand naturally;
 *   shorter notes leave a small reserved gap rather than reflow the
 *   page. Scoped via the section selector so other surfaces with the
 *   same component (e.g., advisor reads on Insights) aren't affected. */
#section-budget #vxBudgetAdvisorNote { min-height: 7em; }
/* 2026-05-04: heading + subhead retired — gap-headline above is the page
   title, no second title competing. Stubs hidden so legacy renders that
   still emit the H3/subhead don't visually duplicate the hero. */
.vx-advisor-note-heading { display: none !important; }
.vx-advisor-note-subhead { display: none !important; }
.vx-advisor-note-body { font-family: var(--ff-b); font-size: 1rem; color: var(--ink); line-height: 1.6; max-width: 60ch; margin: 0; transition: opacity .25s ease; }
.vx-advisor-note-body p + p { margin-top: 10px; }
.vx-advisor-note.is-fading .vx-advisor-note-body { opacity: 0.35; }
/* Mirror .page-title's responsive padding tiers exactly so the advisor
   heading aligns with the Vendor IQ heading at every breakpoint. */
@media (max-width: 768px) {
 .vx-advisor-note { padding: 1rem 1.25rem 1.25rem; }
}
@media (max-width: 640px) {
 .vx-advisor-note { padding: 1rem 1rem 1rem; }
 .vx-advisor-note-heading { font-size: clamp(1.3rem,5vw,1.7rem); }
 .vx-advisor-note-subhead { font-size: .8rem; }
 .vx-advisor-note-body { font-size: .92rem; }
}
@media (max-width: 480px) {
 .vx-advisor-note { padding: 1rem .75rem .9rem; }
}
@media (max-width: 360px) {
 .vx-advisor-note { padding: 1rem .75rem .75rem; }
}

.budget-intro-meta-only { margin-top: .5rem; padding-top: 0; }
.budget-intro-meta-only .budget-intro-meta { justify-content: flex-start; }

/* Locked category row — single line, tight visual weight, vendor inline.
   2026-05-01 Slice 5.7 polish v2: outer box hugs the locked-badge with
   only 3px of breathing room top/bottom; title is vertically centered
   to the badge's mid-line. The legacy chrome decoration (dashed top
   border / margin-top / padding-top from the older below-the-head
   layout) is neutralized in this context so the chrome reads as a
   single inline element. */
.vxb-section.is-locked { padding: 14px 22px; background: var(--cream-warm,#F0EBE1); border-color: rgba(44,74,62,.12); box-shadow: 0 2px 16px rgba(44,74,62,.04); animation: vxb-lock-settle 0.5s ease-out; }
/* 2026-05-21 — Smooth visual transition when a category flips into the
   locked state. The section re-renders entirely (planned → locked) so we
   can't tween the value directly; instead we fade-in + slight scale-from
   the locked card so the visitor reads "settled" rather than "snapped".
   Demo polish per Stephen's "premier for even the demos" feedback. */
@keyframes vxb-lock-settle {
  0%   { opacity: 0; transform: translateY(-2px) scale(0.995); background: rgba(244,236,219,0.5); }
  60%  { opacity: 1; transform: translateY(0) scale(1.005); background: rgba(244,236,219,0.9); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.vxb-section.is-locked .vxb-section-head { cursor: default; padding: 0; margin: 0; border: none; flex-direction: row; align-items: center; justify-content: space-between; gap: 12px; min-height: 0; }
.vxb-section.is-locked .vxb-section-head:hover { border: none; }
/* 2026-05-01 polish: unified body typography. ALL body text on the
   budget page (titles, amounts, tags, button labels, lock content)
   uses DM Sans 0.9rem weight 400 — same treatment as item names —
   for uniform readability. Headlines (gap headline) stay display
   serif. Microcopy (.vxb-item-util) keeps its italic-mono treatment.
   Small color-coded metadata pills (.vxb-pill-*) stay distinctive. */
.vxb-section.is-locked .vxb-section-title { line-height: 1.2; margin: 0; align-self: center; }
.vxb-section.is-locked .vxb-items { display: none; }
.vxb-section.is-locked .vxb-chevron { display: none; }
.vxb-section.is-locked .vxc-lock-chrome { margin: 0; padding: 0; border: none; margin-left: auto; }
.vxb-section.is-locked .vxc-lock-badge { margin: 0; }
.vxb-section.is-locked .vxc-lock-cta { display: none; } /* unlocked CTA hidden when locked */

/* Planned category row — single-line header, padding matched to locked
   (1px vertical) so the row hugs its content. White background
   differentiates from cream-locked rows. Chevron sits 9px from the
   title; meta + Lock chrome push right. Expanded state restores
   padding so the items list breathes inside the section. */
/* 2026-05-01 polish: matches the wider expanded-state padding across
   both collapsed and expanded rows so the head dimensions stay
   constant and the polished feel applies to every category row. The
   head's bottom border is transparent when collapsed so vertical
   footprint matches the expanded state, then becomes visible (the
   "line above the line items") when expanded. */
.vxb-section.is-planned { padding: 14px 22px; box-shadow: 0 2px 16px rgba(44,74,62,.04); }
.vxb-section.is-planned .vxb-section-head { min-height: 36px; padding-bottom: 0; margin-bottom: 0; border-bottom: none; }
/* Divider sits above the items list (not under the head) so the head's
   own height never grows on expand — the visual change is items
   appearing, not the header shifting. */
.vxb-section.is-planned.is-expanded .vxb-items { margin-top: 14px; padding-top: 12px; padding-bottom: 6px; border-top: 1px solid var(--border, #eae5dd); }
.vxb-section.is-locked .vxb-section-head { min-height: 36px; }
.vxb-section.is-planned .vxb-section-head { flex-direction: row; align-items: center; gap: 9px; flex-wrap: wrap; }
/* Planned title matches locked exactly — DM Sans 0.9rem 400. */
.vxb-section.is-planned .vxb-section-title { line-height: 1.2; margin: 0; align-self: center; }
.vxb-section.is-planned .vxb-chevron { margin-left: 0; }
.vxb-section.is-planned .vxb-section-meta { margin-left: auto; }

/* ── ⚑ A WORKSHEET-OWNED CATEGORY LOOKS LIKE EVERY OTHER CATEGORY ────────
   Stephen 2026-08-27: "Transportation category on the Budget page should
   operate like every other expandable category."

   ⚑ AND IT ALREADY HAD THE RIGHT MARKUP. `.is-owned-elsewhere` renders the same
   `vxb-section-head / vxb-head-name / vxb-section-meta` a planned category does
   — it simply had NO RULES AT ALL, so it fell out of the row layout its
   neighbours get and stacked centred instead. `.vxb-owned-link` had none either,
   which is why it painted as a raw browser anchor: blue, underlined, and the
   only thing on the page that looks like a 1998 hyperlink.

   Nothing here restyles the category. It gives it the styling everything else
   already had — see unresolved-var-deletes-the-property for why a missing rule
   is not a neutral state. */
/* ⚑ THE SAME BOX AS A PLANNED CATEGORY, so the money column is ONE column.
   Stephen 2026-08-28: "the right justification for all of the categories is not
   exact (including transportation)." MEASURED at 402pt: planned sections carry
   `padding: 14px 22px` (line ~2410) and this one carried NO padding rule at
   all, so it fell back to the base 16px — and its amount landed at x=383 where
   every neighbour's sat at 375. Eight pixels, on every row, for as long as this
   category has existed. The file's own note above says it: a missing rule is
   not a neutral state. */
.vxb-section.is-owned-elsewhere { padding: 14px 22px;
  box-shadow: 0 2px 16px rgba(44,74,62,.04); }
.vxb-section.is-owned-elsewhere .vxb-section-head {
  min-height: 36px; padding-bottom: 0; margin-bottom: 0; border-bottom: none;
  flex-direction: row; align-items: center; gap: 9px; flex-wrap: wrap;
}
.vxb-section.is-owned-elsewhere .vxb-section-meta { margin-left: auto; }
.vxb-section.is-owned-elsewhere .vxb-section-title { line-height: 1.2; margin: 0; align-self: center; }

/* The worksheet link reads as the same affordance as every other control on the
   page — not as a raw <a>. Same face and size as the section meta it sits in. */
.vxb-owned-link {
  font-family: var(--ff-b,'DM Sans',sans-serif);
  font-size: .9rem; font-weight: 400;
  color: var(--vx-green,#2C4A3E);
  text-decoration: none;
  white-space: nowrap;
}
.vxb-owned-link::after { content: ' \203A'; }
.vxb-owned-link:hover, .vxb-owned-link:focus-visible { text-decoration: underline; }

@media (max-width: 560px) {
  /* Matches the planned-category behaviour at the same breakpoint: the meta
     drops to its own full-width row rather than crowding the title. */
  .vxb-section.is-owned-elsewhere .vxb-section-meta {
    margin-left: 0; width: 100%; justify-content: flex-start;
  }
}
/* 2026-07-04 (Stephen — mobile scannability): on phones the section head WRAPS the
   meta cluster (scale pill + amount + state tag) onto its own line, but the
   margin-left:auto above kept pushing it to the RIGHT edge — a ragged indent that
   forces a zigzag eye-path. Left-justify the wrapped row and give it the full
   width so it always takes its own line: amounts form a scannable left-aligned
   column under the titles. Desktop (one-line head) keeps title-left/meta-right. */
@media (max-width: 600px) {
  .vxb-section.is-planned .vxb-section-meta { margin-left: 0; width: 100%; justify-content: flex-start; }
}
.vxb-section.is-planned .vxc-lock-chrome { margin: 0; padding: 0; border: none; }
/* Mini "Lock" button — matches the .vxc-lock-edit / .vxc-lock-unlock pill
   on locked rows (small bordered chip), replaces the older dashed-border
   "Lock category — vendor signed" CTA. */
.vxc-lock-cta-mini { font-style: normal; }
.vxc-lock-cta-mini:hover { border-color: var(--gold,#C8A96E); color: var(--gold-deep,#A07840); }
.vxb-section-meta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-family: var(--ff-b,'DM Sans',sans-serif); font-size: 0.9rem; font-weight: 400; color: var(--text-mid); }
.vxb-amount { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: 0.9rem; font-weight: 400; color: var(--green,#2C4A3E); letter-spacing: normal; }
/* 2026-07-04 (Stephen — Early Access premium chrome): the planned/partial
   checkbox-era tag is RETIRED from display. The tag element now reads 'skipped'
   permanently and is CSS-gated to show ONLY at data-state="skipped" (an explicit
   couple action worth labeling). Its old slot carries .vxb-aside-pill instead:
   the engine-truthful count of ideas the model set aside for the category. */
.vxb-amount-tag { display: none; font-family: var(--ff-b,'DM Sans',sans-serif); font-size: 0.9rem; font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--text-muted); padding: 2px 10px; background: var(--cream-warm,#F0EBE1); border-radius: 100px; }
.vxb-section[data-state="skipped"] .vxb-amount-tag,
.vxb-subgroup[data-state="skipped"] .vxb-amount-tag { display: inline-block; }
.vxb-section.is-locked .vxb-amount-tag { display: none; }
/* ⚑ "Tap to plan" is a BUTTON where a real worksheet sits behind the category —
   Stephen: "it only closes the category and does not take a user to the new
   worksheet." As a span in the section head it inherited the head's only
   behaviour, which is collapse. Styled as the quiet action it is, not as a
   second primary next to the amount. */
/* ⚑ The receipt for a save that already worked. Stephen: "no save button or
   save on exit of a field" — it saved on blur the whole time and said nothing.
   Quiet, brief, and out of the way: this confirms, it does not celebrate. */
.vx-tp{position:relative}
.vx-tp-saved{position:absolute;top:10px;right:12px;z-index:3;pointer-events:none;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;letter-spacing:.04em;
  color:var(--green,#2C4A3E);background:var(--green-pale,#EAF0ED);
  border:1px solid rgba(44,74,62,.16);border-radius:999px;padding:3px 10px;
  opacity:0;transform:translateY(-3px);transition:opacity .18s ease,transform .18s ease}
.vx-tp-saved.is-on{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion: reduce){
  .vx-tp-saved{transition:none}
}

/* "+ Add address" — the inline form, so adding a place never leaves the plan. */
.vx-addpl{margin:8px 0 4px;padding:12px;border:1px solid rgba(44,74,62,.16);border-radius:10px;
  background:var(--white,#fff);display:flex;flex-direction:column;gap:8px}
.vx-addpl-l{display:flex;flex-direction:column;gap:3px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.72rem;color:var(--text-mid,#4A4A4A)}
/* ⚑ THE THIRD INPUT SURFACE, AND THE ONE NO GATE KNEW ABOUT. .84rem is 13.4px,
   under the zoom threshold, so this form has thrown the page out of frame since
   it shipped — the stop panel and the create form were both fixed by name and
   this was never in the list. ios-input-zoom-validate DISCOVERS the surfaces
   now rather than enumerating them, which is the only version of that check
   that survives a fourth one being added. */
.vx-addpl-l input,.vx-addpl-l select{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:1rem;
  padding:6px 8px;border:1px solid rgba(44,74,62,.20);border-radius:7px;background:var(--white,#fff);
  color:var(--text,#1C1C1C)}
.vx-addpl-act{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.vx-addpl-save{padding:5px 14px;border-radius:999px;cursor:pointer;font-size:.78rem;
  font-family:var(--ff-b,'DM Sans',sans-serif);border:1px solid var(--green,#2C4A3E);
  background:var(--green,#2C4A3E);color:#fff}
.vx-addpl-cancel{padding:5px 12px;border-radius:999px;cursor:pointer;font-size:.78rem;
  font-family:var(--ff-b,'DM Sans',sans-serif);border:1px solid rgba(44,74,62,.20);
  background:none;color:var(--text-mid,#4A4A4A)}
.vx-addpl-msg{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;color:var(--text-mid,#4A4A4A)}

/* ── Compare vehicle-class cards ─────────────────────────────────────────
   Stephen: "the three menu look from the Pinterest corridor view, which span
   and size across the map block." Lifted from `.tier` in hotel-demo.html so the
   two screens are the same control, not two takes on one idea. flex:1 1 0 makes
   N cards divide the block evenly — two classes or four, always full width. */
.vx-cmp-tabs{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.vx-cmp-tier{flex:1 1 0;min-width:96px;cursor:pointer;text-align:left;
  border:1px solid var(--border,rgba(44,74,62,.1));background:var(--white,#fff);
  border-radius:12px;padding:10px 12px;transition:.16s;
  font-family:var(--ff-b,'DM Sans',sans-serif);display:block}
.vx-cmp-tier:hover{border-color:var(--gold,#C8A96E)}
/* ── ⚑ ON A PHONE THE MENU IS ONE ROW OF SQUARE CARDS ────────────────────
   Stephen 2026-08-18: "the boxes are taking up a lot of the screen on mobile"
   — then, on seeing them turned into pills: "I liked the square box look for
   the fleet type menus but the descriptions are too big."

   So the shape stays and the CONTENT shrinks. Five cards at min-width 96px
   wrapped to two rows at 390px, roughly 120px of chrome before the comparison
   starts. One horizontally scrolling row of the same square cards is about
   half that, and every class is still one swipe away.

   The seat line does the rest of the work: "5-8 seat" and "14 seat" rather
   than "8 seats" and "14 seats", set on the vehicle class itself so the card's
   three lines all still come from the server. */
@media (max-width:560px){
  .vx-cmp-tabs{flex-wrap:nowrap;overflow-x:auto;gap:7px;margin:0 0 11px;
    padding-bottom:2px;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}
  .vx-cmp-tabs::-webkit-scrollbar{display:none}
  .vx-cmp-tabs{scrollbar-width:none}
  /* Square, as before — only narrower, tighter and no longer wrapping. */
  .vx-cmp-tier{flex:0 0 auto;min-width:0;max-width:44vw;padding:8px 11px;
    border-radius:12px;scroll-snap-align:start;display:block}
  .vx-cmp-tier-sym{font-size:.95rem;letter-spacing:.01em}
  .vx-cmp-tier-lab{font-size:10.5px;margin-top:0;
    /* The class name is the one line allowed to clip: the seat count above it
       already says what the vehicle is. */
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .vx-cmp-tier-hint{font-size:10.5px;margin-top:0;min-height:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}

.vx-cmp-tier-sym{display:block;font-family:var(--ff-m,'DM Mono',monospace);font-size:1.05rem;
  color:var(--gold-deep,#A07840);font-weight:500;letter-spacing:.04em}
/* ⚑ "seats" IS A UNIT, NOT A TITLE. The range above it is the heading now, so
   this drops to a quiet label — the same relationship as a number and its unit
   on any spec sheet. */
.vx-cmp-tier-lab{display:block;font-size:11.5px;font-weight:500;letter-spacing:.03em;
  color:var(--text-mid,#4A4A4A);margin-top:0}
.vx-cmp-tier-hint{display:block;font-size:11px;color:var(--text-mid,#4A4A4A);margin-top:1px;min-height:1em}
/* ⚑ A class the plan does not use is DIMMED, not removed and not disabled.
   Stephen: "if we do not use one of the fleet classes in the transportation
   guide then it is gray." They can still open it — a couple deciding between a
   minibus and a coach needs to see both — so this is weight, not a barrier. */
.vx-cmp-tier.is-unused{background:var(--cream-warm,#F5EFE3);border-color:rgba(44,74,62,.08)}
.vx-cmp-tier.is-unused .vx-cmp-tier-sym{color:var(--text-muted,#7A7A7A)}
.vx-cmp-tier.is-unused .vx-cmp-tier-lab{color:var(--text-mid,#4A4A4A);font-weight:500}
.vx-cmp-tier.is-unused .vx-cmp-tier-hint{color:var(--text-muted,#7A7A7A);font-style:italic}
.vx-cmp-tier.is-unused:hover{border-color:var(--gold,#C8A96E)}
.vx-cmp-tier[aria-pressed="true"]{background:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E)}
.vx-cmp-tier[aria-pressed="true"] .vx-cmp-tier-sym{color:var(--gold,#C8A96E)}
.vx-cmp-tier[aria-pressed="true"] .vx-cmp-tier-lab,
.vx-cmp-tier[aria-pressed="true"] .vx-cmp-tier-hint{color:var(--cream,#F5EFE3)}

/* ⚑ Read-only tier chips on the Transportation lines. Stephen: "the chips do not
   update any totals and are read-only, they are just for expectation setting."
   Same shape as the interactive picker so the category reads like every other
   one — no pointer, no hover lift, and dimmed enough to say so without shouting. */
/* ⚑ THE PLACEHOLDER LADDER IS PRESSABLE; THE CONTRACT LADDER IS NOT. The
   read-only chips below explain a FUNDED number and must stay inert. These
   explain a recommendation nobody has accepted (`fundsCategory:false`), so a
   couple can walk the four rungs and see what each would cost. */
.vxb-owned-line .vxb-tier-segs.is-placeholder .vxb-tier-seg {
  appearance: none; border: 0; background: none; font: inherit; cursor: pointer; }
.vxb-owned-line .vxb-tier-segs.is-placeholder .vxb-tier-seg:focus-visible {
  outline: 2px solid var(--gold,#C8A96E); outline-offset: 1px; border-radius: 100px; }

/* ⚑ TWO ROWS ON A PHONE, or the four segments push the amount off the money
   column — the same wrap that made the contract rows read three different ways
   before the ladder came off them. Name first, then tier and amount together,
   so the amount still lands in the column it shares with everything else. */
@media (max-width: 560px) {
  #section-budget .vxb-owned-lines.is-suggested .vxb-owned-line {
    display: grid; grid-template-columns: 1fr auto;
    grid-template-areas: "name name" "tier amt";
    row-gap: 6px; column-gap: 10px; align-items: center; }
  #section-budget .vxb-owned-lines.is-suggested .vxb-owned-line-name { grid-area: name; }
  #section-budget .vxb-owned-lines.is-suggested .vxb-tier-segs {
    grid-area: tier; justify-self: start; }
  #section-budget .vxb-owned-lines.is-suggested .vxb-owned-line-amt {
    grid-area: amt; justify-self: end; margin-left: 0; }
}

.vxb-owned-line .vxb-tier-segs.is-readonly { cursor: default; opacity: .82; }
.vxb-owned-line .vxb-tier-segs.is-readonly .vxb-tier-seg { cursor: default; pointer-events: none; }
.vxb-owned-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.vxb-owned-line .vxb-owned-line-amt { margin-left: auto; }
/* ⚑ THE TRANSPORTATION ROWS SET NO TYPE SIZE AT ALL, so they inherited the page
   default and rendered VISIBLY LARGER than every other category — whose rows are
   pinned at .78rem (.vxb-item-name) / .86rem (.vxb-item-name-row). Stephen,
   2026-08-28: "the fonts are bigger in the transportation section". Matched to
   the neighbours rather than to a number picked here, so a later change to the
   item rows moves both. */
.vxb-owned-line { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .86rem;
  color: var(--charcoal,#1C1C1C); }
.vxb-owned-line .vxb-owned-line-hrs { font-size: .78rem; color: var(--text-muted,#88928d); }
.vxb-owned-line .vxb-owned-line-amt { font-size: .86rem; font-variant-numeric: tabular-nums; }
.vxb-owned-lines .vxb-owned-lede { font-family: var(--ff-m,monospace); font-size: .62rem;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted,#88928d);
  margin: 0 0 8px; }
.vxb-owned-lines .vxb-owned-foot { font-size: .74rem; color: var(--text-muted,#88928d);
  margin: 6px 0 0; line-height: 1.45; }

/* ⚑ ONE MONEY COLUMN DOWN THE WHOLE CARD. The category amount sits 4px inside
   the head (2px head padding + 2px meta padding); the contract rows below it
   had neither and landed at 379 against the category's 375. Same 4px here, so a
   couple reads one column from the header straight down through the contracts
   rather than two that nearly line up. Derived from the header's own offsets,
   not picked. */
.vxb-owned-body .vxb-owned-lines { padding-right: 4px; }

/* The body a category head now opens onto. Collapsed by CSS rather than by
   markup, mirroring `.vxb-items` exactly: _toggleExpand flips the class on the
   node and never re-renders the section, so a body that only EXISTS when
   expanded can never appear. */
.vxb-owned-body { display: flex; flex-direction: column; gap: 14px; }
.vxb-section:not(.is-expanded) .vxb-owned-body {
  max-height: 0; overflow: hidden; opacity: 0; pointer-events: none;
  margin: 0; padding: 0; }
.vxb-section.is-expanded .vxb-owned-body {
  max-height: none; opacity: 1; margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--border,#eae5dd); }
.vxb-owned-body .vxb-owned-link { align-self: flex-start; }

/* ⚑ "NONE" ON THE ONE CATEGORY THAT HAD NO LINE ITEMS TO DECLINE.
   Stephen 2026-09-02: "have a 'none' if the couple does not want to include in
   their budget just like the other categories."

   Both the note and the plan it replaces are ALWAYS in the DOM and swapped
   here, for the same reason `.vxb-owned-body` is collapsed by CSS: pressing
   None takes the SURGICAL refresh path (_refreshSection), which repaints the
   amount, the tag and the button but never re-renders the section. Markup that
   only exists in one state would never appear on the device — the bug that
   shipped when the body itself was emitted conditionally.

   ⚑ AND THE PLAN IS HIDDEN, NOT DELETED. The rows stay in the DOM carrying
   their own prices; the note above names what the plan comes to, so a category
   reading $0 cannot be mistaken for a plan that was lost. Include puts back
   exactly the same numbers, because nothing recomputed them. */
/* ⚑ A DECLINED VEHICLE, STRUCK RATHER THAN HIDDEN.
   Stephen 2026-09-03: "a couple can decide to not fund something after they get
   the hours from the worksheet." The row stays and keeps its price, because the
   price is the fact they are deciding against — hiding it would leave a couple
   unable to see what Include would cost them, and would make the plan look
   shorter than it is. Same treatment a skipped line item gets: dimmed, with the
   amount struck. */
#section-budget .vxb-owned-line-wrap.is-declined .vxb-owned-line-name,
#section-budget .vxb-owned-line-wrap.is-declined .vxb-owned-line-amt {
  color: var(--text-muted,#88928d); }
/* ⚑ GREY, NOT STRUCK. Stephen 2026-09-03, looking at three declined vehicles:
   "for consistency, any line item estimate that is not included should be gray
   not a line through the estimate." The muted colour above already says "not in
   your total"; the strike said it a second time and read as a correction rather
   than a choice. Applied to every not-included line item, not only these rows —
   the skipped-item and Tips rules below carried the same strike, so leaving them
   would have made this the inconsistent one. */
.vxb-owned-lede .vxb-owned-lede-part { color: var(--green-mid,#3a6b59); }
/* The None segment reads as an opt-out, not as a cheaper rung — no gold. */
#section-budget .vxb-owned-line .vxb-tier-seg.is-none.is-active {
  background: var(--cream-warm,#F0EBE1); color: var(--text-muted,#88928d);
  border-color: var(--border,#eae5dd); }

/* ⚑ WHAT THEY ARE PUTTING BEHIND ONE VEHICLE. Stephen 2026-09-03: "more into
   the limo, less into the shuttle." Laid out on the same row shape as the tier
   strip above it, so the two decisions about a vehicle — who drives it and what
   you spend on it — read as a pair rather than as a field bolted under a
   picker. The plan's own figure sits after the box: a couple has to be able to
   see what they are moving away from, and clearing the box gets it back. */
.vxb-owned-spend { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.vxb-owned-spend .vxb-amount-prefix { margin-left: auto; }
.vxb-owned-spend .vxb-amount-input { width: 7ch; }
.vxb-owned-spend .vxb-owned-spend-plan {
  flex-basis: 100%; text-align: right; font-size: .72rem;
  color: var(--text-muted,#88928d); }
/* A declined vehicle is not being paid for, so there is nothing to set. */
.vxb-owned-line-wrap.is-declined .vxb-owned-spend { opacity: .5; }
.vxb-owned-line-wrap.is-declined .vxb-owned-spend .vxb-amount-input {
  pointer-events: none; }

.vxb-owned-aside-note { display: none; }
.vxb-section.is-set-aside .vxb-owned-aside-note {
  display: block; margin: 0; font-size: .8rem; line-height: 1.5;
  color: var(--text-muted,#88928d); }
/* One selector: `is-suggested` is a modifier ON `.vxb-owned-lines`, so
   naming it again would look like a guarantee against a rule that does not
   exist. Nothing ID-scoped sets display on this container. (`is-contingency`
   retired 2026-09-03 with the garage-contingency row it modified.) */
.vxb-section.is-set-aside .vxb-owned-lines { display: none; }

/* ⚑ ON A PHONE THE CONTRACT ROW IS A GRID, NOT A WRAPPING FLEX LINE. Measured
   in the Simulator once the category could actually open: `flex-wrap:wrap` let
   each row break wherever its own content happened to run out of room, so
   $6,630 dropped to a line of its own, $440 sat beside the tier pills and $925
   stayed inline. Three rows, three shapes, and no money column to read down.

   Two fixed rows instead — name on the first, tier and amount on the second —
   so the amounts right-align as a column whatever the vehicle is called.

   ⚑ `#section-budget`-SCOPED ON PURPOSE. `.vxb-owned-line` is declared as a
   plain flex row later in this file, and a same-specificity `display:flex`
   further down would silently beat `display:grid` — the failure that shipped
   layout markup without its cascade once already. */
/* ⚑ ONE LINE, LIKE A STATIONERY ITEM. Stephen sent me to look at Stationery in
   the Simulator, and the reference is unambiguous: name · chevron · ONE compact
   tier pill · amount, on a single row with a divider under it. The transport
   rows were printing the whole four-segment ladder ($ $$ $$$ $$$$), which is
   ~110pt of chrome and the reason they wrapped three different ways.

   Only the ACTIVE segment shows on a phone. Nothing is lost: these chips are
   read-only by charter — "the chips do not update any totals and are read-only,
   they are just for expectation setting" — so the three a couple cannot choose
   were only ever telling them where this one sits, and the pill still does.
   The full ladder returns above 560px where there is room for it. */
/* ⚑ THE ROW IS NOW TITLE + AMOUNT ONLY, so the mobile rule that hid three of
   the four tier segments is gone with the segments themselves — a rule for a
   shape nobody renders is the next drift. The ladder lives in the detail box
   below, where Ceremony Programs keeps its own. */
#section-budget .vxb-owned-line { column-gap: 10px; }
#section-budget .vxb-owned-line .vxb-owned-line-amt { margin-left: auto; }
/* The divider that makes them read as a list rather than a paragraph. */
#section-budget .vxb-owned-line-wrap + .vxb-owned-line-wrap {
  border-top: 1px solid var(--border,#eae5dd); padding-top: 10px; margin-top: 10px; }

/* ⚑ THE SAME PANEL A REAL LINE ITEM OPENS. `.vxb-item-detail` is styled only
   under `.vxb-item.is-open`, and a contract row is not a `.vxb-item` — so the
   open state is mirrored here with the SAME values rather than a second look
   that drifts. Everything inside (the tier row, its eyebrow) then inherits the
   existing `#section-budget .vxb-item-detail ...` rules untouched. */
#section-budget .vxb-owned-line-wrap.is-open .vxb-item-detail {
  max-height: none; opacity: 1; overflow: visible; margin: 6px 0 2px;
  padding: 16px 18px; background: var(--cream-warm,#F0EBE1); border-radius: 12px; }
#section-budget .vxb-owned-line-wrap .vxb-item-detail p { font-size: .8rem;
  line-height: 1.5; color: var(--text-mid,#5b625a); margin: 0 0 6px; }

/* ── Level three: one contract's own detail ────────────────────────────── */
.vxb-owned-line-wrap { display: flex; flex-direction: column; }
.vxb-owned-expand { appearance: none; border: 0; background: none; cursor: pointer;
  padding: 0 2px; line-height: 1; color: var(--text-muted,#88928d);
  transition: transform .18s ease; flex: 0 0 auto; }
.vxb-owned-line-wrap.is-open .vxb-owned-expand { transform: rotate(90deg); }
/* Collapsed the way `.vxb-item-detail` is — max-height, not display — so the
   two panels open identically instead of one snapping and one animating. */
.vxb-owned-detail { max-height: 0; overflow: hidden; opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .vxb-owned-expand { transition: none; }
}
.vxb-amount-tag.is-action { display: inline-block; border: 1px solid rgba(44,74,62,.18);
  background: var(--white,#fff); color: var(--green,#2C4A3E); cursor: pointer;
  font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .84rem; padding: 4px 12px;
  transition: background .18s ease, border-color .18s ease; }
.vxb-amount-tag.is-action:hover { background: var(--green-pale,#EAF0ED);
  border-color: rgba(44,74,62,.34); }
.vxb-section.is-locked .vxb-amount-tag.is-action { display: none; }
/* The set-aside pill — quiet gold invitation, tap target is the whole head
   (expanding reveals the deferred lines). DM Mono micro-caps to match the
   demo scale pill's editorial voice. */
/* 2026-07-08 (Stephen) — set-aside pill retired from the cards: the
   deferred-ideas surfacing belongs to Vera's verbiage ("I set aside two
   ideas for this category"), not card chrome. The pool itself is
   untouched — Optimize still invests from it and the refresh code keeps
   updating the (hidden) element, so no JS paths change. */
.vxb-aside-pill { display: none !important; font-family: var(--ff-m,'DM Mono',monospace); font-size:.6rem; letter-spacing:.08em; text-transform: uppercase; font-weight: 500; padding: 3px 9px; border-radius: 999px; color: var(--gold-deep,#A07840); background: rgba(200,169,110,.10); border: 1px solid rgba(200,169,110,.28); white-space: nowrap; align-self: center; }
.vxb-section[data-state="skipped"] .vxb-aside-pill { display: none !important; }
.vxb-section.is-locked .vxb-aside-pill { display: none !important; }

/* Manual-section amount input (External Catering / Hotel Block / etc.) */
.vxb-amount-input-wrap { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; background: var(--white,#fff); border: 1px solid var(--border,#eae5dd); border-radius: 8px; font-family: var(--ff-m,'DM Mono',monospace); font-size: .85rem; color: var(--charcoal); }
.vxb-amount-input-wrap:focus-within { border-color: var(--green); }
.vxb-amount-prefix { color: var(--text-muted); }
.vxb-manual-amount { width: 6ch; border: none; outline: none; background: transparent; font: inherit; color: inherit; padding: 0; }

/* Feedback fixed-height slot — clamps verbose streaming so categories below don't shift */
/* 2026-05-04: streaming clamp redesigned. Old behavior used
   -webkit-line-clamp:2 which collapsed the panel to two lines and made
   the page bounce as Claude streamed in (each delta repainted, the line
   measurement reset, the page jolted). New: pre-allocate ~280px so the
   panel reserves vertical space before streaming starts; mask the
   bottom 25% to a fade so partial content reads as intentional rather
   than cut-off; the user expands via the existing button to see the
   full prose. Net: zero page bounce while Claude streams. */
.vx-feedback-slot { position: relative; min-height: 280px; transition: min-height .25s ease; }
.vx-feedback-slot[data-feedback-clamped="true"] .analysis-body {
  max-height: 280px; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 75%, transparent);
  mask-image: linear-gradient(180deg, #000 75%, transparent);
}
.vx-feedback-slot[data-feedback-clamped="false"] { min-height: 0; }
.vx-feedback-slot[data-feedback-clamped="false"] .analysis-body {
  max-height: none; overflow: visible;
  -webkit-mask-image: none; mask-image: none;
}
.vx-feedback-expand { background: transparent; border: none; font-family:var(--ff-b,'DM Sans',sans-serif); font-size:.8rem; letter-spacing:normal; color: var(--green); padding: 8px 28px 14px; cursor: pointer; display: block; width: 100%; text-align: left; }
.vx-feedback-slot[data-feedback-clamped="false"] .vx-feedback-expand::after { content: " — collapse ↑"; }
.vx-feedback-slot[data-feedback-clamped="false"] .vx-feedback-expand { color: var(--text-muted); }

/* Slice 5.7 polish: inline Areas-to-Save cards, rendered directly under
   their target category section so the prescription sits next to the
   thing it's prescribing. The top panel keeps a slim summary + guest-
   count cards, with a one-line note pointing to the inline cards. */
.vx-cut-card.is-inline { margin: 0 0 14px; padding: 14px 18px; background: rgba(201,123,58,.06); border: 1px solid rgba(201,123,58,.22); border-radius: 12px; box-shadow: 0 1px 3px rgba(201,123,58,.08); }
.vx-cut-card.is-inline .vx-cut-card-cat { font-family: var(--ff-m,'DM Mono',monospace); font-size: .65rem; letter-spacing: .12em; text-transform: uppercase; color: var(--amber-risk); }
.vx-cut-card.is-inline.is-applied { background: rgba(58,107,89,.06); border-color: rgba(58,107,89,.25); }
.vx-cut-card.is-inline.is-applied .vx-cut-card-cat { color: var(--green-mid,#3a6b59); }
.vx-cut-card.is-inline.is-dismissed { display: none; }
.vx-cut-inline-note { font-family: var(--ff-m,'DM Mono',monospace); font-size: .65rem; letter-spacing: .04em; color: var(--text-muted,#88928d); font-style: italic; padding: 6px 24px 10px; }

/* Slice 5.7 polish: budget toolbar (Collapse All + Print/PDF) */
.vxb-toolbar { display: flex; justify-content: flex-end; gap: 8px; margin-bottom: 12px; }
.vxb-toolbar-btn { background: transparent; border: 1px solid var(--border-g,#cdc5b6); color: var(--text-mid,#4A4A4A); font-family:var(--ff-b,'DM Sans',sans-serif); font-size:.8rem; font-weight:500; letter-spacing:normal; padding: 7px 14px; border-radius: 100px; cursor: pointer; transition: all .15s ease; }
.vxb-toolbar-btn:hover { background: var(--cream-warm,#F0EBE1); border-color: rgba(44,74,62,.3); color: var(--charcoal); }
/* 2026-05-27 — Unified Budget toolbar v2 (single action row consolidates
   Resize + Optimize + Save PDF + Collapse all). Differences from v1:
   - Left-aligned anchor (primary actions Resize/Optimize lead-left)
   - Spacer pushes utility actions (Save PDF / Collapse all) to the right
   - Primary button (Resize) has terracotta border for visual lead
   - Mobile: row collapses to a 2-column grid (Resize+Optimize on top,
     Save PDF+Collapse on bottom) with full-width buttons */
.vxb-toolbar-v2 { justify-content: flex-start; flex-wrap: wrap; gap: 6px; align-items: center; }
/* 2026-07-26 — Collapsible budget controls ("Adjust budget"). The account/subscriber
   budget opens on the clean ledger; the toolbar + Budget band + Reception format tuck
   behind one quiet <details> toggle so the first view matches the read-only demo (which
   hides these outright — §2 ~1743/1760). Optimize is promoted by Vera contextually
   (post contract-scan), so it needs no permanent chrome. Default CLOSED; session-
   persisted (IIFE ~30197). Hidden in demo; shown in the try-yourself sandbox. */
#vxBudgetControls { margin: 0 0 18px; }
#vxBudgetControls > summary.vxb-controls-toggle {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  width: max-content; user-select: none; -webkit-user-select: none;
  font-family: var(--ff-m,'DM Mono',monospace); font-size: 11.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--green,#2C4A3E);
  padding: 9px 15px; border: 1px solid rgba(44,74,62,.18); border-radius: 100px;
  background: rgba(44,74,62,.03); transition: background .18s ease, border-color .18s ease;
}
#vxBudgetControls > summary.vxb-controls-toggle::-webkit-details-marker { display: none; }
#vxBudgetControls > summary.vxb-controls-toggle:hover { background: rgba(44,74,62,.07); border-color: rgba(44,74,62,.32); }
.vxb-controls-toggle-chev { font-size: 1rem; line-height: 1; transition: transform .2s ease; }
#vxBudgetControls[open] > summary.vxb-controls-toggle { margin-bottom: 14px; }
#vxBudgetControls[open] > summary .vxb-controls-toggle-chev { transform: rotate(180deg); }
.vxb-controls-body { animation: vxb-expand-in .2s ease-out; }
body.vx-demo-active #vxBudgetControls,
body.vx-marquee-demo #vxBudgetControls { display: none !important; }
body.vx-try-yourself-active #vxBudgetControls { display: block !important; }
/* 2026-08-03 (Stephen) — Real accounts open on the clean, Zola-like ledger. The
   "Adjust budget" controls feel un-premium, so hide them in accounts (no demo
   class) until the unified pill set + Vera-adjust replace them. Demo and
   try-yourself flows are unchanged (they set their own body classes). */
body:not(.vx-demo-active):not(.vx-marquee-demo):not(.vx-try-yourself-active) #vxBudgetControls { display: none !important; }
/* 2026-07-26 — "Pro tips" disclosure inside an expanded demo category. The rich,
   category-specific guidance (was an always-on note that ate mobile height) tucks
   behind a compact gold toggle: "Expand for Pro tips ›" collapsed → "Pro tips ⌄" open.
   Demo-only (built by _decorateSections). */
.vxDemoProTips{margin:2px 0 10px}
.vxDemoProTips>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px;width:max-content;max-width:100%;user-select:none;-webkit-user-select:none;font-family:var(--ff-m,'DM Mono',monospace);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;color:var(--gold-deep,#A07840);padding:7px 12px;border:1px solid rgba(200,169,110,.32);border-radius:100px;background:rgba(200,169,110,.07);transition:background .15s ease}
.vxDemoProTips>summary::-webkit-details-marker{display:none}
.vxDemoProTips>summary:hover{background:rgba(200,169,110,.14)}
.vxDemoProTips .vxpt-chev{font-size:.95rem;line-height:1;transition:transform .2s ease}
.vxDemoProTips[open]>summary{margin-bottom:8px}
.vxDemoProTips[open]>summary .vxpt-chev{transform:rotate(90deg)}
.vxDemoProTips[open]>summary .vxpt-verb{display:none}
.vxDemoProTips-body{margin:0;padding:10px 13px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;line-height:1.55;color:#5b625a;background:rgba(44,74,62,.035);border:1px solid rgba(44,74,62,.06);border-radius:8px}
/* 2026-07-27 (Stephen) — C free-explore: the slim Vera bar is now the demo's SURFACE NAV.
   On mobile the top step-bar is display:none, so a free-explorer had no way to reach
   Vendor+/Chat/Contracts+ — these pills ARE that nav. The pill row mirrors the desktop
   nav (Chat · Budget · Vendor+ · Contracts+) as a consistent bottom row; Vera stays the
   clickable avatar (opens the assistant). A "what's different" line (Vera's voice) swaps
   with the active surface. Built by the quick-start submit in free-explore mode; demo-only. */
/* 2026-08-05 (Stephen, on-device) — the footer sat at a FLAT bottom:16px with no
   safe-area handling, so on an iPhone its bottom row (the Vera|Chat|Budget|Vendor+|
   Contracts+ nav) was clipped behind Safari's bottom toolbar and unreadable without
   scrolling. Two separate insets have to be cleared and they are not the same thing:
     · env(safe-area-inset-bottom) — the home indicator. Non-zero in standalone /
       add-to-home-screen, which we actively promote; zero in normal Safari.
     · --vx-vv-bottom — Safari's own toolbar. NOT a safe-area inset: it overlays the
       layout viewport, so env() reports nothing for it. The only reliable measure is
       the gap between the layout viewport and the visual viewport, which the
       VisualViewport listener below keeps in this variable (0 where unsupported).
   max() on the first, plus the second, so the card clears whichever is present. */
#vxDemoVeraIntro{position:fixed;left:16px;right:16px;bottom:calc(max(16px, env(safe-area-inset-bottom, 0px)) + var(--vx-vv-bottom, 0px));z-index:9000;display:flex;flex-direction:column;gap:9px;max-width:720px;margin:0 auto;padding:12px 15px 11px;background:#FAF7F2;border:1px solid rgba(44,74,62,.16);border-radius:16px;box-shadow:0 12px 36px rgba(44,74,62,.20);font-family:var(--ff-b,'DM Sans',sans-serif)}
/* 2026-07-30 (Stephen #7) — when the Vera concierge / walkthrough is active it owns the
   bottom of the screen (its own footer). Hide the free-explore demo footer so it never
   overlaps Vera or shows a stale surface caption behind her; it returns when she exits. */
body.vx-concierge-active #vxDemoVeraIntro{display:none!important}
/* 2026-07-30 (Stephen) — HARD GUARD: the demo footer belongs ONLY to a live demo
   session. It must NEVER appear on the account-only home screen (or any authenticated
   surface). This binds its visibility to body.vx-demo-active so that even a stray
   footer node (e.g. left mid-teardown, or wrongly created) is structurally hidden the
   instant demo mode is off. _vxEnsureDemoFooter also refuses to build one off-demo. */
body:not(.vx-demo-active) #vxDemoVeraIntro{display:none!important}
/* 2026-07-31 (Stephen) — the demo footer is MOBILE-ONLY. On desktop/tablet (≥601px) the
   real top step-bar (.step-bar-fixed) is already shown and functional, so the footer's
   pill nav is a redundant, confusing SECOND nav. The footer exists purely to give mobile
   demo visitors navigation (mobile hides the step-bar). At ≥601px it's hidden entirely;
   its jobs move to the exposed menu bar (hero call-outs re-anchor to the step-bar nodes)
   and to a "Save my plan" pill in the header. _vxEnsureDemoFooter also refuses to BUILD
   one at ≥601px (clean-campsite) — this CSS is the backstop for a mobile→desktop resize. */
@media (min-width:601px){ #vxDemoVeraIntro{display:none!important} }
/* 2026-07-30 (Stephen #9) — in the demo, the general "✦ Help" slide-out tab is redundant
   with the demo footer (nav + the "?" tips + the footer's own "✦ Explore" reopen) and the
   two ✦ pills stack/overlap bottom-right. Hide the general Help tab in the demo; the demo's
   own footer is its help + navigation. */
body.vx-demo-active #vxHelpTab{display:none!important}
#vxDemoVeraIntro .vxdv-top{display:flex;align-items:center;gap:11px}
#vxDemoVeraIntro .vxdv-avatar{flex:0 0 auto;width:30px;height:30px;border-radius:50%;object-fit:cover;cursor:pointer;border:1.5px solid transparent;transition:border-color .15s ease,box-shadow .15s ease}
#vxDemoVeraIntro .vxdv-avatar:hover{border-color:rgba(200,169,110,.7);box-shadow:0 0 0 3px rgba(200,169,110,.18)}
#vxDemoVeraIntro .vxdv-msg{flex:1 1 auto;min-width:0;font-size:.83rem;line-height:1.4;color:#4a4a4a;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.8em}
#vxDemoVeraIntro .vxdv-msg strong{color:#2C4A3E;font-weight:600}
#vxDemoVeraIntro .vxdv-save{flex:0 0 auto;background:#2C4A3E;color:#FAF7F2;border:none;border-radius:40px;padding:8px 15px;font-family:inherit;font-size:.78rem;font-weight:600;cursor:pointer;white-space:nowrap;transition:background .15s ease}
#vxDemoVeraIntro .vxdv-save:hover{background:#24413a}
#vxDemoVeraIntro .vxdv-close{flex:0 0 auto;width:26px;height:26px;padding:0;background:transparent;border:none;border-radius:50%;color:#8a908a;font-size:1.15rem;line-height:1;cursor:pointer;transition:background .15s ease,color .15s ease}
#vxDemoVeraIntro .vxdv-close:hover{background:rgba(44,74,62,.07);color:#2C4A3E}
/* 2026-07-30 (Stephen) — "?" re-launches Vera's tips (relaunchable coach-marks). */
#vxDemoVeraIntro .vxdv-tips{flex:0 0 auto;width:23px;height:23px;padding:0;background:rgba(44,74,62,.06);border:none;border-radius:50%;color:#5b6a64;font-family:inherit;font-size:.82rem;font-weight:700;line-height:1;cursor:pointer;transition:background .15s ease,color .15s ease}
#vxDemoVeraIntro .vxdv-tips:hover{background:rgba(200,169,110,.22);color:#2C4A3E}
/* Divider-bar menu, matching the desktop nav (.sn-name + .step-divider '|') for
   uniformity — text labels, muted→green when active, thin '|' between each. */
#vxDemoVeraIntro .vxdv-nav{display:flex;align-items:center;justify-content:center;gap:0}
#vxDemoVeraIntro .vxdv-pill{flex:0 1 auto;min-width:0;position:relative;background:transparent;border:none;border-radius:0;color:var(--text-muted,#8a8f88);padding:6px 10px;font-family:inherit;font-size:clamp(.72rem,2.9vw,.82rem);font-weight:500;line-height:1;letter-spacing:.03em;white-space:nowrap;cursor:pointer;transition:color .15s ease}
#vxDemoVeraIntro .vxdv-pill:not(:first-child)::before{content:'|';position:absolute;left:-1px;top:50%;transform:translateY(-50%);color:rgba(44,74,62,.3);font-weight:300;font-size:.85rem;pointer-events:none}
#vxDemoVeraIntro .vxdv-pill:hover{color:var(--green,#2C4A3E)}
#vxDemoVeraIntro .vxdv-pill.is-active{color:var(--green,#2C4A3E);font-weight:600}
/* Minimized → a small persistent chip, bottom-right, that re-opens the nav. */
#vxDemoVeraIntro.is-min{left:auto;right:16px;max-width:none;width:max-content;flex-direction:row;padding:0;background:transparent;border:none;box-shadow:none;gap:0}
#vxDemoVeraIntro.is-min .vxdv-top,#vxDemoVeraIntro.is-min .vxdv-nav{display:none}
#vxDemoVeraIntro .vxdv-reopen{display:none}
#vxDemoVeraIntro.is-min .vxdv-reopen{display:inline-flex;align-items:center;gap:7px;background:#2C4A3E;color:#FAF7F2;border:none;border-radius:40px;padding:9px 16px;font-family:inherit;font-size:.78rem;font-weight:600;cursor:pointer;box-shadow:0 8px 24px rgba(44,74,62,.30)}
@media (max-width:560px){
  #vxDemoVeraIntro{bottom:calc(max(12px, env(safe-area-inset-bottom, 0px)) + var(--vx-vv-bottom, 0px));left:10px;right:10px;gap:8px;padding:11px 12px 10px}
  /* 2026-07-29 (Stephen) — on mobile the full-width "Save my plan" pill dropped to
     its OWN row so the "what's different" caption gets the entire first row and reads
     in full. Beside the button it was squeezed to ~2 lines of ~18 chars and truncated
     to "…read of…" on every surface (the wrapping bug from the Pinterest demo). Now:
     row 1 = avatar + caption + close; row 2 = Save (full width); row 3 = pill nav.
     flex-basis:0 keeps the caption on row 1 next to the avatar instead of wrapping
     beneath it; line-clamp:3 lets the longest captions run to 3 lines on the
     narrowest phones (~320px) rather than clip (2 lines fit at 360px+). */
  #vxDemoVeraIntro .vxdv-top{gap:8px 9px;flex-wrap:wrap}
  #vxDemoVeraIntro .vxdv-msg{font-size:.8rem;flex:1 1 0;-webkit-line-clamp:3;line-clamp:3}
  #vxDemoVeraIntro .vxdv-save{order:9;flex:1 0 100%;padding:9px 14px;font-size:.78rem}
  #vxDemoVeraIntro .vxdv-pill{padding:6px 7px}
}
/* 2026-05-28 — Phase 3 Memorability Lens bulk affordances toolbar.
   Lighter row under the main toolbar; subtler chrome. */
.vxb-toolbar-lens { display: flex; justify-content: flex-start; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; padding-top: 8px; border-top: 1px dashed rgba(200,169,110,.25); }
.vxb-lens-btn { font-size: .58rem; letter-spacing: .08em; padding: 6px 12px; }
.vxb-lens-trim { color: #a23030; border-color: rgba(220,80,80,.32); }
.vxb-lens-trim:hover { background: rgba(220,80,80,.08); color: #a23030; }
.vxb-lens-filter { color: var(--green); }
.vxb-lens-filter[aria-pressed="true"] { background: var(--green); color: var(--white,#fff); border-color: var(--green); }
/* When the Memory Maker filter is active, hide categories that don't
   contain at least one Memory Maker / Required / Personal Priority item.
   Class applied to the budget mount via JS. */
.vx-lens-mm-filter .vxb-section:not([data-has-mm="true"]) { display: none; }
/* Lens trim modal (Phase 3) */
.vx-lens-modal-backdrop { position: fixed; inset: 0; background: rgba(28,28,28,.32); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); display: flex; align-items: center; justify-content: center; z-index: 1100; padding: 24px; opacity: 0; pointer-events: none; transition: opacity .2s ease; }
.vx-lens-modal-backdrop.is-visible { opacity: 1; pointer-events: auto; }
.vx-lens-modal-card { background: var(--cream,#FAF7F2); border-radius: 14px; padding: 28px 32px; max-width: 560px; width: 100%; box-shadow: 0 24px 64px rgba(28,28,28,.18); max-height: 80vh; overflow-y: auto; }
.vx-lens-modal-eyebrow { font-family: var(--ff-m); font-size:var(--fs-eyebrow,.62rem); letter-spacing:.14em; text-transform: uppercase; color: var(--gold-deep,#A07840); margin-bottom: 6px; }
.vx-lens-modal-title { font-family: var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif); font-style: italic; font-size: 1.6rem; color: var(--green); margin: 0 0 8px; line-height: 1.2; }
.vx-lens-modal-sub { font-size: .9rem; color: var(--text-mid,#4A4A4A); line-height: 1.5; margin-bottom: 18px; }
.vx-lens-item-list { display: flex; flex-direction: column; gap: 4px; margin: 0 -8px 18px; padding: 0; list-style: none; }
.vx-lens-item-list li { display: flex; align-items: baseline; gap: 12px; padding: 8px 8px; border-bottom: 1px dotted rgba(0,0,0,.05); font-size: .86rem; color: var(--charcoal,#3a342b); }
.vx-lens-item-list li .vx-lens-item-amt { margin-left: auto; font-family: var(--ff-b,'DM Sans',sans-serif); font-size: var(--fs-amount,.9rem); color: var(--money-ink,#33352f); font-weight: 500; font-variant-numeric: tabular-nums; }
.vx-lens-item-list li .vx-lens-item-cat { font-family: var(--ff-m); font-size: .58rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted,#88928d); }
.vx-lens-modal-total { display: flex; justify-content: space-between; align-items: baseline; padding: 12px 0; border-top: 1px solid rgba(44,74,62,.16); font-family: var(--ff-b,'DM Sans',sans-serif); font-size: var(--fs-body,1rem); color: var(--charcoal,#3a342b); }
.vx-lens-modal-total .vx-lens-total-val { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: var(--fs-amount,.9rem); color: var(--money-ink,#33352f); font-weight: 500; font-variant-numeric: tabular-nums; }
.vx-lens-modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }
.vx-lens-modal-btn { font-family:var(--ff-b,'DM Sans',sans-serif); font-size:.8rem; letter-spacing:normal; padding: 9px 18px; border-radius: 999px; cursor: pointer; border: 1px solid var(--border-g); background: transparent; color: var(--charcoal,#3a342b); transition: all .15s ease; }
.vx-lens-modal-btn:hover { border-color: var(--green); color: var(--green); }
.vx-lens-modal-btn.is-primary { background: var(--green); color: var(--white,#fff); border-color: var(--green); }
.vx-lens-modal-btn.is-primary:hover { background: var(--green-mid,#3a6b59); border-color: var(--green-mid,#3a6b59); color: var(--white,#fff); }
.vx-lens-empty { font-family: var(--ff-d); font-style: italic; color: var(--text-muted); padding: 20px 0; text-align: center; }
.vxb-toolbar-spacer { flex: 1 1 auto; min-width: 8px; }
.vxb-tb-primary { border-color: rgba(200,146,58,.55); color: #C8923A; }
.vxb-tb-primary:hover { background: #FBF3E5; border-color: #C8923A; color: #8B6420; }
@media (max-width: 600px) {
  .vxb-toolbar-v2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
  .vxb-toolbar-spacer { display: none; }
  .vxb-toolbar-v2 .vxb-toolbar-btn { width: 100%; text-align: center; padding: 9px 8px; font-size: .60rem; }
}
/* 2026-06-26 (Tier Estimator, Phase 2) — Quality row: segmented $/$$/$$$/$$$$ pill
   beneath the budget toolbar. Editorial-restraint chrome to match the toolbar. */
.vxb-quality-row { margin: 4px 0 16px; padding-top: 10px; border-top: 1px dashed rgba(200,169,110,.25); }
.vxb-quality-head { font-family: var(--ff-m,'DM Mono',monospace); font-size: .62rem; letter-spacing: .1em; text-transform: uppercase; color: var(--gold-deep,#A07840); margin-bottom: 8px; }
.vxb-quality-pill { display: inline-flex; flex-wrap: wrap; gap: 0; border: 1px solid var(--border-g,#cdc5b6); border-radius: 100px; overflow: hidden; background: var(--white,#fff); }
.vxb-quality-seg { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; padding: 7px 16px; cursor: pointer; border-left: 1px solid var(--border-g,#cdc5b6); transition: background .15s ease, color .15s ease; line-height: 1.1; }
.vxb-quality-seg:first-child { border-left: none; }
.vxb-quality-seg input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.vxb-quality-sym { font-family: var(--ff-m,'DM Mono',monospace); font-size: .8rem; font-weight: 600; color: var(--text-mid,#4A4A4A); letter-spacing: .02em; }
.vxb-quality-lbl { font-family: var(--ff-m,'DM Mono',monospace); font-size: .52rem; letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted,#88928d); }
.vxb-quality-seg:hover { background: var(--cream-warm,#F0EBE1); }
.vxb-quality-seg:has(input:checked) { background: var(--green,#2C4A3E); }
.vxb-quality-seg:has(input:checked) .vxb-quality-sym,
.vxb-quality-seg:has(input:checked) .vxb-quality-lbl { color: var(--white,#fff); }
.vxb-quality-seg:has(input:focus-visible) { outline: 2px solid var(--gold,#C8A96E); outline-offset: 2px; }
.vxb-quality-micro { margin: 9px 0 0; font-size: .78rem; font-style: italic; line-height: 1.45; color: var(--text-muted,#88928d); max-width: 60ch; }
@media (max-width: 600px) {
  .vxb-quality-pill { display: flex; width: 100%; }
  .vxb-quality-seg { flex: 1 1 0; padding: 8px 4px; }
}

/* Areas-to-Save empty state */
.vx-cut-empty { padding: 22px 28px; border-top: 1px solid var(--border-g,#cdc5b6); }
.vx-cut-empty-eyebrow { font-family: var(--ff-d); font-size: 1rem; color: var(--amber-risk); letter-spacing: .01em; }
.vx-cut-empty-eyebrow em { font-style: italic; }
.vx-cut-empty-msg { margin: 6px 0 0; font-size: .9rem; color: var(--text-muted); font-style: italic; }

.calc-section { background: var(--white); border-radius: var(--radius-lg); border: 1px solid var(--border); margin-bottom: 20px; padding: 32px 36px; box-shadow: 0 2px 16px rgba(44,74,62,.04); }
.eyebrow { font-family: var(--ff-m); font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: var(--green); font-weight: 500; margin-bottom: 6px; display: block; }
.section-h2 { font-family: var(--ff-d); font-size: clamp(1.6rem,3vw,2.4rem); font-weight: 400; line-height: 1.1; letter-spacing: -.01em; margin-bottom: 6px; color: var(--green); }
.section-h2 em { color: var(--gold); font-style: italic; }
.section-desc { font-size: .88rem; color: var(--text-muted); margin-bottom: 24px; }

.group-head { display: flex; justify-content: space-between; align-items: baseline; margin: 28px 0 12px; border-top: 1px solid var(--border); padding-top: 20px; }
.group-head-first { margin-top: 0; border-top: none; padding-top: 0; }
.group-name { font-family: var(--ff-d); font-size: 1.15rem; font-style: italic; color: var(--charcoal); }
.group-total { font-family: var(--ff-b); font-size: .75rem; color: var(--text-muted); }   /* 2026-07-28 money: DM Sans (was DM Mono) */

.vrow { display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto; gap: 0 16px; align-items: start; padding: 14px 0; border-bottom: 1px solid var(--border); transition: opacity .2s; }
.vrow.is-skipped { opacity: .4; }
/* 2026-05-31 — further dim the dollar column on skipped rows so couples
   don't misread a faded "$500" as "$500 is in my budget" when the row
   is actually skipped. Compounded with the row's .4 opacity → ~.12. */
.vrow.is-skipped .vrow-amt { opacity: .3; }
.vrow:last-child { border-bottom: none; }
.vrow-left { min-width: 0; }
.vrow-name { font-size: .9rem; font-weight: 500; color: var(--charcoal); display: flex; align-items: center; gap: 7px; margin-bottom: 3px; }
.vrow-hint { font-size: .78rem; color: var(--text-muted); line-height: 1.45; }
.vrow-amt { font-family: var(--ff-d); font-size: 1.25rem; font-weight: 400; color: var(--charcoal); text-align: right; white-space: nowrap; }
.vrow-amt.is-zero { color: var(--text-muted); }
.vrow-slider { grid-area: 2/1/auto/-1; padding-top: 10px; }

.tag { font-family: var(--ff-m); font-size: .6rem; letter-spacing: .06em; text-transform: uppercase; padding: 2px 7px; border-radius: 6px; font-weight: 400; }
.tag-fixed { background: var(--gold-pale); color: var(--gold); border: 1px solid rgba(200,169,110,.25); }
.tag-skip { background: rgba(44,74,62,.05); color: var(--text-muted); border: 1px solid var(--border); }
.tag-added { background: var(--green-pale); color: var(--green); border: 1px solid rgba(44,74,62,.2); }

.status-pip { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; transition: background .3s; }
.pip-ok { background: var(--green-lt); }
.pip-warn { background: var(--gold); }
.pip-low { background: var(--rose); }
.pip-off { background: rgba(44,74,62,.2); }

.range-labels { display: flex; justify-content: space-between; margin-top: 4px; }
.range-labels span { font-family: var(--ff-m); font-size: .6rem; color: var(--text-muted); letter-spacing: .04em; }
input[type=range] { -webkit-appearance: none; width: 100%; height: 3px; background: linear-gradient(to right, var(--green) 0%, var(--green) var(--pct,50%), rgba(44,74,62,.15) var(--pct,50%), rgba(44,74,62,.15) 100%); border-radius: 2px; outline: none; cursor: pointer; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; background: var(--green); border-radius: 50%; border: 2px solid var(--white); box-shadow: 0 1px 6px rgba(44,74,62,.25); cursor: pointer; transition: transform .15s; }
input[type=range]::-webkit-slider-thumb:hover { transform: scale(1.2); }

.toggle-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.sw { position: relative; width: 34px; height: 20px; flex-shrink: 0; }
.sw input { opacity: 0; width: 0; height: 0; }
.sw-track { position: absolute; inset: 0; border-radius: 10px; background: rgba(44,74,62,.15); cursor: pointer; transition: background .2s; }
.sw-track::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--white); box-shadow: 0 1px 4px rgba(0,0,0,.15); transition: transform .2s; }
.sw input:checked~.sw-track { background: var(--green); }
.sw input:checked~.sw-track::after { transform: translateX(14px); }
.toggle-label { font-family: var(--ff-m); font-size: .65rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); }

.budget-field { border: 1.5px solid var(--border); border-radius: var(--radius); background: var(--cream); display: flex; align-items: center; padding: 10px 16px; gap: 6px; max-width: min(280px,100%); transition: border-color .2s; }
.budget-field:focus-within { border-color: var(--green-lt); }
.budget-symbol { font-family: var(--ff-d); font-size: 1.2rem; color: var(--text-muted); }
.budget-field input { font-family: var(--ff-d); font-size: 1.3rem; color: var(--charcoal); background: none; border: none; outline: none; width: 100%; }
.budget-field input::-webkit-inner-spin-button { -webkit-appearance: none; }

.guest-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.input-label { font-family: var(--ff-m); font-size: .65rem; letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }
.input-val { font-family: var(--ff-d); font-size: 1.2rem; color: var(--charcoal); }
.foundation-sub-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 18px; }
.foundation-sub-field label { display: block; font-family: var(--ff-m); font-size: .6rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 5px; }
.foundation-sub-field input { width: 100%; padding: 8px 10px; border: 1.5px solid var(--border); border-radius: 8px; font-family: var(--ff-mono,monospace); font-size: .92rem; color: var(--charcoal); background: var(--cream); transition: border-color .15s; }
.foundation-sub-field input:focus { outline: none; border-color: var(--green); }
.foundation-sub-field input::-webkit-outer-spin-button, .foundation-sub-field input::-webkit-inner-spin-button { opacity: .4; }
.baseline-hint { font-family: var(--ff-m); font-size: .68rem; letter-spacing: .04em; color: var(--text-muted); text-transform: none; font-weight: 400; margin-left: 8px; }

.foundation-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 4px; }
.foundation-exclude { display: flex; align-items: center; gap: 8px; flex-shrink: 0; padding-top: 4px; }
.foundation-exclude .toggle-label { font-family: var(--ff-m); font-size: .72rem; letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.day-btns { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.day-btn { font-family: var(--ff-b); font-size: .82rem; padding: 8px 18px; border-radius: 8px; border: 1.5px solid var(--border); background: transparent; color: var(--text-mid); cursor: pointer; transition: all .15s; display: flex; align-items: center; gap: 6px; }
.day-disc { font-family: var(--ff-m); font-size: .6rem; letter-spacing: .06em; background: rgba(200,169,110,.15); color: var(--gold); padding: 1px 5px; border-radius: 4px; }
.day-btn.active { background: var(--green); border-color: var(--green); color: var(--white); }
.day-btn.active .day-disc { background: rgba(255,255,255,.2); color: var(--white); }
.day-btn:not(.active):hover { border-color: var(--green-lt); }
.callout-box { background: var(--gold-pale); border: 1px solid var(--border-g); border-radius: 10px; padding: 12px 16px; margin-top: 16px; font-size: .84rem; color: var(--text-mid); display: flex; align-items: flex-start; gap: 10px; }
.callout-icon { color: var(--gold); font-size: 1rem; flex-shrink: 0; }

.sidebar { position: sticky; top: 220px; }
.sb-card { background: var(--green); border-radius: var(--radius-lg); padding: 28px; margin-bottom: 16px; color: var(--white); box-shadow: 0 4px 24px rgba(44,74,62,.2); }
.sb-card-left { display: block; }
.sb-card-rows { display: block; }
.sb-card .sb-bar-wrap { display: block; height: 3px; background: rgba(255,255,255,.15); border-radius: 2px; margin: 12px 0 14px; overflow: hidden; }
.sb-label { font-family: var(--ff-m); font-size: .62rem; letter-spacing: .12em; text-transform: uppercase; color: rgba(255,255,255,.55); margin-bottom: 10px; }
.sb-total { font-family: var(--ff-d); font-size: 2.8rem; font-weight: 400; line-height: 1; margin-bottom: 12px; }
.sb-bar { height: 100%; border-radius: 2px; background: var(--gold); transition: width .3s; max-width: 100%; }
.sb-bar.over { background: var(--rose); }
.sb-row { display: flex; justify-content: space-between; align-items: baseline; font-size: .85rem; color: rgba(255,255,255,.7); }
.sb-row strong { color: var(--white); }
.sb-delta { font-family: var(--ff-m); font-size: .75rem; }
.sb-delta.over { color: var(--rose); }
.sb-delta.under { color: var(--gold-lt); }
.sb-breakdown { background: var(--white); border-radius: var(--radius-lg); border: 1px solid var(--border); padding: 22px 24px; margin-bottom: 16px; }
.sb-bd-title { font-family: var(--ff-d); font-size: 1rem; color: var(--charcoal); margin-bottom: 14px; }
.bd-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.bd-name { font-size: .8rem; color: var(--text-mid); }
.bd-bar-bg { flex: 1; height: 3px; background: rgba(44,74,62,.1); border-radius: 2px; margin: 0 10px; overflow: hidden; }
.bd-bar-fill { height: 100%; background: var(--green-lt); border-radius: 2px; }
.bd-val { font-family: var(--ff-b); font-size: .72rem; color: var(--text-mid); white-space: nowrap; }   /* 2026-07-28 money: DM Sans (was DM Mono) */
.action-btn { width: 100%; font-family: var(--ff-b); font-size: .82rem; padding: 9px 18px; border-radius: 8px; cursor: pointer; transition: all .15s; border: 1.5px solid var(--border); background: transparent; color: var(--text-mid); margin-bottom: 8px; box-sizing: border-box; }
.action-btn:hover { border-color: var(--green-lt); color: var(--green); }

#vendor-readiness { background: var(--white); border-radius: var(--radius-lg); border: 1px solid var(--border); padding: 32px 36px; margin-bottom: 20px; box-shadow: 0 2px 16px rgba(44,74,62,.04); overflow: hidden; }
.vr-title { font-family: var(--ff-d); font-size: clamp(1.6rem,3vw,2.2rem); font-weight: 400; color: var(--green); margin-bottom: 4px; }
.vr-title em { color: var(--gold); font-style: italic; }
.vr-subtitle { font-size: .85rem; color: var(--text-muted); margin-bottom: 24px; }
#stale-banner { display: none; align-items: center; gap: 10px; background: rgba(200,169,110,.08); border: 1px solid var(--border-g); border-radius: 8px; padding: 10px 14px; margin-bottom: 20px; font-family: var(--ff-m); font-size: .65rem; letter-spacing: .06em; text-transform: uppercase; color: var(--gold); }
#stale-banner.visible { display: flex; }
#stale-banner.current { background: rgba(90,140,122,.08); border-color: rgba(90,140,122,.25); color: var(--green-lt); }
.stale-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; animation: blink-dot 1.6s ease-in-out infinite; }
#stale-banner.current .stale-dot { animation: none; }
@keyframes blink-dot { 0%,100%{opacity:1}50%{opacity:.25} }
.readiness-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(140px,1fr)); gap: 6px; margin-bottom: 24px; }
.rg-item { background: var(--cream); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; display: flex; align-items: flex-start; gap: 8px; }
.rg-name { font-size: .78rem; font-weight: 500; color: var(--charcoal); line-height: 1.2; }
.rg-note { font-family: var(--ff-m); font-size: .62rem; color: var(--text-muted); margin-top: 2px; }
/* 2026-05-01 Slice 8: legacy #btn-review / #btn-cut rules retired —
   the buttons moved to Insights and are now styled by .ss-hero-btn.
   .review-wrap / .review-btn-row stay because the Save-as-PDF button
   on Budget still uses them. */
.review-wrap { margin-bottom: 24px; }
.review-btn-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
#btn-pdf { font-family: var(--ff-b); font-size: .78rem; font-weight: 500; padding: 9px 18px; border-radius: 100px; border: 1.5px solid rgba(44,74,62,.22); background: var(--white); color: var(--ink-faint); cursor: not-allowed; display: inline-flex; align-items: center; gap: 7px; transition: all .25s; white-space: nowrap; }
#btn-pdf.ready { border-color: var(--green-lt); color: var(--green); cursor: pointer; }
#btn-pdf.ready:hover { background: var(--green-pale); border-color: var(--green); }
.pdf-btn-label { display: inline; }
@keyframes spin { to { transform: rotate(360deg); } }
.spin-icon { width: 13px; height: 13px; border: 2px solid rgba(255,255,255,.25); border-top-color: #fff; border-radius: 50%; animation: spin .7s linear infinite; }
.cut-spin-icon { width: 13px; height: 13px; border: 1.5px solid rgba(201,123,58,.25); border-top-color: var(--amber-risk); border-right-color: var(--amber-risk); border-radius: 50%; animation: spin .7s linear infinite; flex-shrink: 0; }
#analysis-result { display: none; border-top: 1px solid var(--border); padding-top: 24px; margin-top: 4px; }
#analysis-result.visible { display: block; }
.analysis-meta { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.analysis-chip { font-family: var(--ff-m); font-size: .6rem; letter-spacing: .1em; text-transform: uppercase; padding: 3px 10px; border-radius: 6px; background: var(--green-pale); color: var(--green); border: 1px solid rgba(44,74,62,.15); }
.analysis-ts { font-family: var(--ff-m); font-size: .62rem; color: var(--text-muted); }
.analysis-body { font-family: var(--ff-b); font-size: .9rem; color: var(--text-mid); line-height: 1.75; }
.analysis-body h3 { font-family: var(--ff-d); font-size: 1.2rem; font-weight: 400; font-style: italic; color: var(--green); margin: 20px 0 8px; }
.analysis-body h3:first-child { margin-top: 0; }
.analysis-body strong { color: var(--charcoal); font-weight: 600; }
.analysis-body em { color: var(--gold); font-style: italic; }
.analysis-body ul { margin: 8px 0 8px 18px; }
.analysis-body li { margin-bottom: 5px; }
.analysis-cursor { display: inline-block; width: 2px; height: 14px; background: var(--green); vertical-align: middle; margin-left: 2px; animation: blink .85s step-end infinite; }
@keyframes blink { 50%{opacity:0} }

/* 2026-05-19 — Unified "in-flight" pattern. Stephen's UX rule:
   any subscriber or demo query that triggers an AI call / search
   should show the SAME cue in two synchronized places:
     1) The originating button greys + flashes "Refreshing…"
        (attribution: "I clicked this, it's working")
     2) A thin gold bar pinned at the viewport top runs an
        indeterminate animation (time: "is it still going?")
   The cue dismisses on response. Replaces the prior split between
   the bottom-right enrichment card (demo) and the legacy status
   crawler (subscriber). One pattern, every entry point. */
#vx-global-progress {
  position: fixed; top: 0; left: 0; right: 0;
  height: 3px;
  background: rgba(200,169,110,.15);
  z-index: 9999;
  overflow: hidden;
  opacity: 0;
  transition: opacity .22s ease;
  pointer-events: none;
}
#vx-global-progress.is-active { opacity: 1; }
#vx-global-progress::before {
  content:''; position: absolute; top:0; left:-30%; height:100%; width:30%;
  background: linear-gradient(90deg, transparent, var(--gold, #C8A96E), transparent);
  animation: vxGlobalProgress 1.4s linear infinite;
}
@keyframes vxGlobalProgress { to { left: 100%; } }

.vx-btn-loading {
  pointer-events: none !important;
  cursor: not-allowed !important;
  position: relative;
  animation: vxBtnLoadingPulse 1.5s ease-in-out infinite;
}
@keyframes vxBtnLoadingPulse {
  0%, 100% { opacity: .55; }
  50%      { opacity: .9; }
}

#vx-processing-banner{position:fixed;top:60px;left:50%;transform:translateX(-50%) translateY(-12px);z-index:9999;display:flex;align-items:center;gap:12px;background:var(--white);border:1px solid var(--border-g);border-radius:40px;padding:8px 20px 8px 12px;box-shadow:0 4px 24px rgba(44,74,62,.13),0 1px 4px rgba(44,74,62,.06);opacity:0;pointer-events:none;transition:opacity .2s ease,transform .2s ease;white-space:nowrap}
#vx-processing-banner.visible{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.vx-banner-ring{width:18px;height:18px;border:1.5px solid rgba(200,169,110,.2);border-top-color:var(--gold);border-right-color:var(--gold);border-radius:50%;animation:spin .75s linear infinite;flex-shrink:0}
.vx-banner-text{font-family:var(--ff-d);font-size:.92rem;font-style:italic;color:var(--green);letter-spacing:.01em;line-height:1}
.vx-banner-dots{display:flex;gap:3px;align-items:center;margin-left:2px}
.vx-banner-dots span{width:3px;height:3px;border-radius:50%;background:var(--gold);animation:blink-dot 1.1s ease-in-out infinite}
.vx-banner-dots span:nth-child(2){animation-delay:.18s}
.vx-banner-dots span:nth-child(3){animation-delay:.36s}
.analysis-error { background: rgba(201,123,106,.08); border: 1px solid rgba(201,123,106,.25); border-radius: 8px; padding: 14px 18px; font-family: var(--ff-m); font-size: .72rem; color: var(--rose); }
.mobile-actions { display: none; gap: 8px; margin-top: 16px; margin-bottom: 4px; }
.mobile-action-btn { flex: 1; margin-bottom: 0!important; text-align: center; }
.data-note { text-align: center; padding: 12px 48px; font-family: var(--ff-m); font-size: .62rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); position: relative; z-index: 1; }
/* What-if simulator — idea #2 (2026-04-29). Lives in the budget sidebar. */
.sb-whatif{margin:14px 0;padding:14px 14px 12px;background:linear-gradient(135deg,rgba(200,169,110,.1),rgba(90,140,122,.06));border:1px solid rgba(200,169,110,.28);border-radius:10px}
.sb-whatif-head{display:flex;align-items:center;gap:7px;margin-bottom:10px}
.sb-whatif-icon{color:var(--gold);font-size:.9rem}
.sb-whatif-title{font-family:var(--ff-d);font-size:1rem;font-weight:500;color:var(--green);font-style:italic}
.sb-whatif-sub{flex:1;text-align:right;font-family:var(--ff-m);font-size:.62rem;color:var(--text-muted);letter-spacing:.04em;text-transform:uppercase}
.sb-whatif-body{display:flex;flex-direction:column;gap:8px}
.sb-whatif-row{display:flex;align-items:center;gap:8px}
.sb-whatif-lbl{font-family:var(--ff-m);font-size:.7rem;color:var(--text-mid);text-transform:uppercase;letter-spacing:.05em;flex-shrink:0}
.sb-whatif-select{flex:1;padding:6px 10px;border:1px solid rgba(44,74,62,.15);border-radius:6px;font-family:var(--ff-b);font-size:.82rem;color:var(--ink);background:#fff;cursor:pointer}
.sb-whatif-select:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.2)}
.sb-whatif-prefix{font-family:var(--ff-d);color:var(--text-mid);font-size:1rem}
.sb-whatif-input{flex:1;padding:6px 10px;border:1px solid rgba(44,74,62,.15);border-radius:6px;font-family:var(--ff-b);font-size:.86rem;color:var(--ink);background:#fff}
.sb-whatif-input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.2)}
.sb-whatif-out{margin-top:4px;padding:10px 12px;background:#fff;border-radius:8px;border:1px solid rgba(44,74,62,.08)}
.sb-whatif-out-line{font-size:.78rem;color:var(--text-mid);line-height:1.55;margin-bottom:6px}
.sb-whatif-out-line:last-child{margin-bottom:0}
.sb-whatif-out-line strong{color:var(--green);font-weight:600}
.sb-whatif-out-delta{font-family:var(--ff-d);font-size:1rem;color:var(--green)}
.sb-whatif-out-delta.over{color:var(--rose,#C97B6A)}
.sb-whatif-out-delta.under{color:var(--gold-deep,#A07840)}
.sb-whatif-out-suggest{margin-top:8px;padding-top:8px;border-top:1px dashed rgba(44,74,62,.15)}
.sb-whatif-suggest-label{font-family:var(--ff-m);font-size:.6rem;color:var(--text-soft);text-transform:uppercase;letter-spacing:.06em;margin-bottom:4px}
.sb-whatif-suggest-list{list-style:none;padding:0;margin:0;font-size:.74rem;line-height:1.55;color:var(--text-mid)}
.sb-whatif-suggest-list li{padding:1px 0}
.sb-whatif-suggest-list strong{color:var(--green)}
.sb-whatif-actions{display:flex;gap:6px;margin-top:6px}
.sb-whatif-apply{flex:1;padding:7px 10px;background:var(--green);color:#fff;border:none;border-radius:6px;font-family:var(--ff-b);font-size:.74rem;font-weight:500;cursor:pointer;transition:background .15s}
.sb-whatif-apply:hover{background:#1f3a30}
.sb-whatif-cancel{padding:7px 10px;background:transparent;color:var(--text-mid);border:1px solid rgba(255,255,255,.2);border-radius:6px;font-family:var(--ff-b);font-size:.74rem;cursor:pointer}
.sb-whatif-cancel:hover{color:#fff;border-color:rgba(255,255,255,.4)}

/* "Why these numbers?" lineage disclosure — idea #6 (2026-04-29) */
.data-lineage{max-width:1100px;margin:1.25rem auto 0;padding:0 1.5rem}
.data-lineage-toggle{width:100%;display:flex;align-items:center;gap:10px;padding:10px 14px;background:rgba(200,169,110,.08);border:1px solid rgba(200,169,110,.22);border-radius:10px;font-family:var(--ff-b);font-size:.78rem;color:var(--text-mid);cursor:pointer;text-align:left;transition:background .15s}
.data-lineage-toggle:hover{background:rgba(200,169,110,.13)}
.data-lineage-toggle[aria-expanded="true"] .data-lineage-chevron{transform:rotate(90deg)}
.data-lineage-icon{flex-shrink:0;color:var(--gold-deep,#A07840);font-size:.95rem}
.data-lineage-label{flex-shrink:0;font-weight:600;color:var(--green)}
.data-lineage-status{flex:1;min-width:0;color:var(--text-mid);font-style:italic}
.data-lineage-status.is-personalized{color:var(--green);font-style:normal;font-weight:500}
.data-lineage-chevron{flex-shrink:0;font-family:var(--ff-d);color:var(--gold-deep);font-size:1rem;transition:transform .15s}
.data-lineage-body{margin-top:8px;padding:1rem 1.25rem;background:#fff;border:1px solid rgba(200,169,110,.2);border-radius:10px;font-size:.82rem;line-height:1.6;color:var(--text-mid)}
.data-lineage-body[hidden]{display:none}
.data-lineage-section{margin-bottom:.85rem}
.data-lineage-section:last-child{margin-bottom:0}
.data-lineage-section strong{display:block;color:var(--green);margin-bottom:3px;font-family:var(--ff-b);font-size:.84rem;font-weight:600}
.data-lineage-section p{margin:0 0 .35rem}
.data-lineage-section ul{margin:.35rem 0 0;padding-left:1.2rem}
.data-lineage-section li{margin-bottom:3px}
.data-lineage-section em{color:var(--gold-deep);font-style:italic}
@media(max-width:700px){
 .data-lineage{padding:0 1rem}
 .data-lineage-toggle{flex-wrap:wrap;font-size:.74rem}
 .data-lineage-status{flex-basis:100%;font-size:.7rem;padding-left:24px}
 .data-lineage-chevron{margin-left:auto}
}

/* 2026-05-04: hero alignment sweep. Chat / Vendor IQ / Contract IQ all
   share .page-title — bumping the heading + sub scale here moves the
   three pages in lockstep. Container width drops to 820px to match
   Insights .ss-wrap so the page transition rhymes visually. Body
   widths on the operational tools below the hero stay at 960px (the
   timeline / compare grids / category accordion all need room). */
.page-title {
 position: relative; z-index: 1; max-width: 820px; margin: 0 auto;
 padding: 1rem clamp(1rem,4vw,2rem) 1.4rem;
 display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.pt-heading { font-family: var(--ff-d); font-size: clamp(2rem,5vw,3rem); font-weight: 400; color: var(--green); line-height: 1.05; margin: 0 0 .75rem; }
.pt-heading em { font-style: italic; color: var(--gold); }
.pt-sub { font-size: .88rem; color: var(--text-muted); margin-top: 0; line-height: 1.65; max-width: 580px; }
.pt-count { font-family: var(--ff-m); font-size: .56rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); white-space: nowrap; padding-top: 4px; }
/* 2026-05-27 Stephen polish: match Vendor+ intro card chrome exactly.
   Earlier 0.4rem padding-bottom was a Budget-specific squeeze; now that
   the intro lives next to the toolbar (not a paragraph stack), the
   standard 1.4rem bottom + a tight top reads the same as Vendor+ and
   Contracts+. The advisor-note + gap-headline overrides below stay for
   the (still-rendered) kicker line and the hidden advisor slot. */
.vx-budget-page-title { padding-top: 0.5rem; padding-bottom: 1.4rem; }
/* 2026-07-28 (Stephen) — put the budget CONTENT (ⓘ assumptions, Adjust-budget controls, and the
   category list) in the SAME max-width:820 centered column as the .page-title H1, so the H1 sits
   directly over the content and the whole page reads as one column like Vendor+ (was: content filled
   the full .main-col ~896px, so the H1 looked indented and the rows ran wide, opening a big
   title↔status-pill gap). The totals strip stays full-width by design. */
#section-budget #vxBudgetAssume,
#section-budget #vxBudgetControls,
#section-budget .vxb-root { max-width: 820px; margin-left: auto; margin-right: auto; }
#section-budget .vx-advisor-note { padding-top: 0.25rem; }
#section-budget .vx-gap-headline { margin-top: 0; }
/* 2026-05-28 (Stephen "gap between strip and H1"): the document-flow
   stack between the totals strip and the page-title H1 used to add
   ~72px of empty padding (profile-card 1rem + divider 1.25rem +
   tool-grid 1.75rem + page-title 0.5rem) — all from empty/hidden
   elements that pre-date the Insights/Budget split. Zero them out on
   Budget so the strip sits flush above the H1. */
#section-budget .profile-card { margin-top: 0; }
#section-budget #profileCard:not(:has(.pc-applied:not([style*="display:none"]))) { display: none; }
#section-budget > .divider { display: none; }
#section-budget .tool-grid { padding-top: 0.5rem; }
/* The hidden advisor-note slot must NOT claim space (it had min-height
   set elsewhere); enforce display:none when hidden so the gap above
   the page-title collapses. */
#section-budget #vxBudgetAdvisorNote[hidden] { display: none; min-height: 0; }
/* Same for the lock-redistribution slot and the legacy hero-actions
   stub — they're permanently hidden post-cleanup but the [hidden]
   attribute can lose to other display rules. */
#section-budget #vxLockRedistribution[hidden],
#section-budget #vxBudgetHeroActions[hidden] { display: none; }

/* 2026-05-19 (v6) — Persistent budget totals bar tuned to match the
   tab-nav row above. Stephen's notes: "gap between itself and the
   navigation menu" + "data fonts to be the same size as the navigation
   menu and the new budget menu height the same as the other two for
   visual consistency." v6: top dropped 188 → 173px to close the gap
   (matches chrome bottom with drawer open), inline label-then-value
   layout instead of stacked so the row sits at the same ~50px height
   as the tab nav, and both label + value use the same DM Sans / .92rem
   size the tab nav text uses. Cormorant kept for the dollar values
   to preserve brand voice but at .98rem so it visually matches the
   nav weight. Remaining cell color-coded via .is-under / .is-tight /
   .is-over. */
.vx-budget-totals-strip {
  /* 2026-06-04 (Stephen) — locked third menu row, flush under the Vera nav.
     The fixed header stack is: header (0–74) + .vx-profile-bar (74–128) +
     .step-bar-fixed / Vera nav (129–183). The strip pins at the nav's BOTTOM
     (183px) so it reads as a locked third menu, not a bar that floats up and
     overlaps the nav. z-index sits just under the nav (70) so any 1px seam
     tucks behind it. If the header heights ever change, update this to match
     the step-bar's bottom edge (its top + min-height). */
  position: sticky;
  /* Was a hardcoded 183px whose own comment said to update it when the
     header heights change. They change at three breakpoints and it never
     did — 6px of gap at 700, 11px of the strip clipped under the header
     at 560. See --vx-chrome-bottom above. */
  top: var(--vx-chrome-bottom);
  z-index: 25;
  left: 0;
  right: 0;
  margin: 0 calc(-1 * clamp(1rem, 4vw, 2rem));
  background: #FAF7F2;
  border-bottom: 1px solid rgba(44,74,62,.14);
  border-top: 1px solid rgba(44,74,62,.08);
}
.vx-bt-inner {
  max-width: 820px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2rem);
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0;
  min-height: 50px;
  align-items: center;
}
.vx-bt-cell {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  padding: 0 8px;
  min-width: 0;
}
.vx-bt-cell + .vx-bt-cell {
  border-left: 1px solid rgba(44,74,62,.10);
}
.vx-bt-eyebrow {
  font-family: var(--ff-b, 'DM Sans', sans-serif);
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(44,74,62,.62);
  font-weight: 500;
  white-space: nowrap;
}
.vx-bt-value {
  font-family: 'Cormorant Garamond','Cormorant Fallback',Georgia, serif;
  font-size: clamp(.95rem, 1.6vw, 1.05rem);
  font-weight: 500;
  color: #2C4A3E;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  transition: color .35s ease;
  white-space: nowrap;
}
.vx-bt-remaining.is-under { color: #2C4A3E; }
.vx-bt-remaining.is-tight { color: #C8923A; }
/* ⚑ 2026-08-13 — OVER PLAN IS NOT A DANGER STATE (reduce-stress-never-alarm).
   This was #B94040, which is the literal value of the --danger token: the same
   red as a failed sign-in, a network error and a delete button. A couple whose
   plan runs past their budget has not hit an error; under Gen9 they may have
   chosen it deliberately (Stephen: "Go over plan"), and above-estimate is a
   refinement, not a bust. --rose is the palette's designed attention tone, and
   it is what this state should have been using all along. --danger stays exactly
   where it belongs: real failures. */
.vx-bt-remaining.is-over  { color: var(--rose,#C97B6A); }
/* 2026-05-27 — Tips-reserve sub-label under the Remaining cell.
   2026-05-28 (Stephen): retired in favor of a visible Tips block at the
   bottom of the Budget page (under Misc). Couples now make an intentional
   Must/Skip decision on gratuity rather than reading the reserve as a
   passive sublabel. Element stays in DOM as a no-op so legacy renderer
   can null-deref-free; CSS hides it. */
.vx-bt-sublabel { display: none !important; }
/* The model line under the totals strip — see the markup comment. Sits OUTSIDE
   .vx-bt-inner, so it is a block in the strip rather than a fourth cell: adding
   a cell would have re-thirded Allocated / Budget / Remaining. */
.vx-bt-model {
  margin: 6px 0 2px;
  text-align: center;
  font-family: 'DM Mono', ui-monospace, monospace;
  font-size: var(--fs-eyebrow, .62rem);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted, #7A7A7A);
  opacity: .85;
  line-height: 1.5;
}
.vx-bt-model[hidden] { display: none; }
.vx-bt-flash {
  animation: vxBtFlash 1.05s ease-out 1;
}
@keyframes vxBtFlash {
  0%   { transform: scale(1);    text-shadow: 0 0 0 transparent; }
  35%  { transform: scale(1.07); text-shadow: 0 0 18px rgba(200,169,110,.55); }
  100% { transform: scale(1);    text-shadow: 0 0 0 transparent; }
}
@media (max-width: 600px) {
  .vx-bt-cell { gap: 4px; padding: 0 4px; }
  .vx-bt-eyebrow { font-size: .58rem; letter-spacing: .04em; }
  .vx-bt-value { font-size: .92rem; }
  /* 2026-05-28 (Stephen mobile gap): profile-bar + step-bar are display:none
     under 600px (see ~line 5042), so the strip's sticky offset has to match
     the main header alone (74px) instead of the desktop 3-row chrome. */
  /* 2026-07-21 — offset must clear the fixed header's REAL height, which
     grows with env(safe-area-inset-top) on notched/standalone devices; a
     bare 80px pinned the strip behind the header (only visible on overscroll).
     2026-08-04 (Stephen, on-device) — the 80px was 19px BELOW the header, and
     that slot is a window: scrolling text slides through the gap between the
     header and the pinned strip, which reads as broken. The pin is now the
     header's own height expressed exactly — same padding formula as the header
     rule, plus its measured content height (35px here, 33px at ≤480) — so the
     strip butts flush against the header at every inset. IF THE HEADER PADDING
     EVER CHANGES, CHANGE THESE TOO; they mirror it deliberately rather than
     guessing a round number, which is what drifted the last three times. */
  .vx-budget-totals-strip { top: var(--vx-chrome-bottom); }
  /* (2026-08-04 — #section-budget's padding-top:env(safe-area-inset-top) is
     GONE. It existed because .bridge reserved a flat 88px that did not grow
     with the inset, so the budget page needed its own nudge to keep the strip's
     natural position at or below its pin. .bridge now carries the inset itself
     (see the rule near line 6150), so this padding double-counted it — costing
     a second inset-height of dead band in standalone / add-to-home-screen mode.
     The invariant it protected still holds: .bridge is the strip's pin + 3px.) */
  /* 2026-05-28 (Stephen "drop Budget on mobile for space"): three cells
     collide at narrow widths. Budget is the input the couple set themselves
     (visible in Wedding Details + Resize modal) — Allocated + Remaining are
     the two computed values worth surfacing. Remaining = Budget − Allocated,
     so the math is recoverable. */
  .vx-bt-inner { grid-template-columns: 1fr 1fr; }
  .vx-bt-cell:nth-child(2) { display: none; }
  /* 2026-06-24 (estimate-led demo §7 / #189 risk guard) — in the demo the
     strip is ESTIMATE-mode: the JS hides cells 1 (Allocated) + 3 (Remaining)
     and shows ONLY the headline (cell 2 = the estimate). The subscriber rule
     above hides cell 2 on mobile, which would leave the demo strip empty. So
     in demo, force the estimate cell visible and single-column. Scoped to
     body.vx-demo-active → subscribers are byte-identical. */
  body.vx-demo-active .vx-bt-inner { grid-template-columns: 1fr; }
  body.vx-demo-active .vx-bt-cell:nth-child(2) { display: flex; }
}
@media (max-width: 480px) {
  /* Header here is max(10px, inset+8px) + 33px content + 10px — see the ≤600 note. */
  .vx-budget-totals-strip { top: var(--vx-chrome-bottom); }
  .vx-bt-inner { min-height: 44px; }
}

/* ════════════════════════════════════════════════════════════════════════
   Feature D — Resize-to-fit affordance + modal (2026-05-26)
   Sits below the Allocated/Budget/Remaining strip. Single-row CTA on
   desktop; stacks on mobile. The modal uses the same brand language as
   the rest of Verdeaux: DM Mono eyebrow, Cormorant italic title, calm
   editorial body, green primary button.
   ════════════════════════════════════════════════════════════════════════ */
.vx-resize-mount {
  max-width: 960px;
  margin: 10px auto 8px;
  padding: 0 22px;
}
.vx-resize-mount[hidden] { display: none; }
.vx-resize-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 18px;
  background: rgba(248, 246, 241, 0.5);
  border: 1px solid rgba(0, 0, 0, 0.05);
  border-radius: 8px;
}
.vx-resize-eyebrow {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  color: var(--gold-deep,#A07840);
  white-space: nowrap;
}
.vx-resize-copy {
  flex: 1;
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-style: italic;
  font-size: 1rem;
  color: var(--charcoal, #3a342b);
}
.vx-resize-cta {
  padding: 8px 16px;
  background: var(--green, #2C4A3E);
  color: #fff;
  border: none;
  border-radius: 6px;
  font-family: var(--ff-b, 'DM Sans', sans-serif);
  font-size: 0.88rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease;
}
.vx-resize-cta:hover { background: #1f3b30; }

/* Modal backdrop + sheet */
.vx-resize-modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(28, 28, 28, 0.45);
  z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.vx-resize-modal-backdrop[hidden] { display: none; }
.vx-resize-modal {
  position: relative;
  max-width: 560px;
  width: 100%;
  max-height: 85vh; overflow-y: auto;
  background: var(--cream, #FAF7F2);
  border-radius: 12px;
  padding: 28px 32px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
}
.vx-resize-x {
  position: absolute; top: 12px; right: 12px;
  background: transparent; border: none;
  font-size: 24px; line-height: 1; color: var(--charcoal-soft, #7a7468);
  cursor: pointer; padding: 4px 8px;
}
.vx-resize-x:hover { color: var(--charcoal, #3a342b); }
.vx-resize-modal .vx-resize-eyebrow { margin-bottom: 6px; }
.vx-resize-title {
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-style: italic;
  font-size: 1.6rem;
  font-weight: 400;
  color: var(--charcoal, #3a342b);
  margin: 0 0 10px;
}
.vx-resize-body {
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--charcoal-soft, #4a4a4a);
  margin: 0 0 18px;
}
.vx-resize-input-wrap {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 18px;
  background: #fff;
  border: 2px solid var(--gold, #C8A96E);
  border-radius: 8px;
  margin-bottom: 18px;
}
.vx-resize-input-prefix {
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-size: 1.5rem;
  color: var(--gold-deep,#A07840);
}
.vx-resize-input {
  flex: 1;
  border: none; background: transparent; outline: none;
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-size: 1.5rem;
  color: var(--charcoal, #3a342b);
}
.vx-resize-preview {
  margin-bottom: 18px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 8px;
}
.vx-resize-preview[hidden] { display: none; }
.vx-resize-preview-summary {
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-style: italic;
  font-size: 1rem;
  color: var(--charcoal, #3a342b);
  margin-bottom: 10px;
}
.vx-resize-locked-note {
  font-size: 0.8rem; color: var(--charcoal-soft, #7a7468); font-style: normal;
}
.vx-resize-rows { display: flex; flex-direction: column; gap: 6px; }
.vx-resize-row-line {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 0.85rem;
  padding: 4px 0;
  border-bottom: 1px dotted rgba(0, 0, 0, 0.05);
}
.vx-resize-row-line:last-child { border-bottom: none; }
/* 2026-05-27 (Stephen "wow would be data..."): preference-downgrade
   "why" line sits under the dollar numbers. Italic Cormorant for the
   editorial tone, muted color so it reads as supporting context
   (not a primary action).
   2026-05-28 (Stephen "comments would be better under the venue
   category so all of the changes look the same on a visual scan"):
   forced full-width so the line wraps below the label + dollar cols,
   preserving column alignment across rows that do vs don't have a
   why line. */
.vx-resize-row-why {
  font-family: 'Cormorant Garamond','Cormorant Fallback',Georgia, serif;
  font-style: italic;
  font-size: .78rem;
  color: var(--charcoal-soft, #7a7468);
  line-height: 1.45;
  margin-top: 2px;
  flex-basis: 100%;
  width: 100%;
}
.vx-resize-row-label { color: var(--charcoal, #3a342b); font-weight: 500; }
.vx-resize-row-prior { color: var(--charcoal-soft, #7a7468); text-decoration: line-through; }
.vx-resize-row-arrow { color: var(--charcoal-soft, #7a7468); }
.vx-resize-row-new { font-weight: 600; }
.vx-resize-row-delta { font-family: var(--ff-m, 'DM Mono', monospace); font-size: 0.72rem; letter-spacing: 0.04em; }
.vx-resize-empty,
.vx-resize-preview-infeasible {
  font-size: 0.9rem; color: var(--charcoal-soft, #7a7468); padding: 8px 0;
}
.vx-resize-preview-infeasible strong { color: var(--charcoal, #3a342b); }
/* Residual-gap callout for when locks + scaled non-lock still exceed target.
   2026-05-26 — Stephen flagged that Mara's locked contracts made the resize
   infeasible to fully fit; this surface owns the editorial moment of
   "tough decisions ahead." Vera handoff is the offered next move. */
.vx-resize-residual {
  margin-top: 14px; padding: 14px 16px;
  background: rgba(200, 169, 110, 0.08);
  border: 1px solid rgba(200, 169, 110, 0.30);
  border-left: 3px solid var(--gold-deep,#A07840);
  border-radius: 8px;
}
.vx-resize-residual-eyebrow {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.62rem; letter-spacing: 0.12em;
  color: var(--gold-deep,#A07840);
  margin-bottom: 6px;
}
.vx-resize-residual-copy {
  font-size: 0.9rem; line-height: 1.55;
  color: var(--charcoal-soft, #4a4a4a);
  margin-bottom: 12px;
}
.vx-resize-vera-handoff {
  padding: 8px 16px;
  background: var(--gold-deep,#A07840);
  color: #fff; border: none; border-radius: 6px;
  font-family: var(--ff-b, 'DM Sans', sans-serif);
  font-size: 0.88rem; font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease;
}
.vx-resize-vera-handoff:hover { background: #6f5510; }

/* ════════════════════════════════════════════════════════════════════════
   Feature F — Lock-aware priority redistribution card (2026-05-27)
   Sits below the advisor-note paragraph. Brand-aligned: gold-accented
   left border, Cormorant italic headline, calm rebalance row strip.
   ════════════════════════════════════════════════════════════════════════ */
.vx-lock-redistribution { max-width: 820px; margin: 0 auto 1.2rem; padding: 0 2rem; }
.vx-lock-redistribution[hidden] { display: none; }
.vx-lr-card {
  background: rgba(248, 246, 241, 0.7);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-left: 3px solid var(--gold-deep,#A07840);
  border-radius: 8px;
  padding: 16px 20px;
}
.vx-lr-eyebrow {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  color: var(--gold-deep,#A07840);
  margin-bottom: 6px;
}
.vx-lr-headline {
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-style: italic;
  font-size: 1.05rem;
  line-height: 1.4;
  color: var(--charcoal, #3a342b);
  margin-bottom: 12px;
}
.vx-lr-rows { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.vx-lr-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px;
  padding: 6px 10px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.04);
  border-radius: 6px;
  font-size: 0.88rem;
}
.vx-lr-row-label { color: var(--charcoal, #3a342b); font-weight: 500; }
.vx-lr-row-nums { display: flex; align-items: center; gap: 8px; }
.vx-lr-row-prior { color: var(--charcoal-soft, #7a7468); text-decoration: line-through; }
.vx-lr-row-arrow { color: var(--charcoal-soft, #7a7468); }
.vx-lr-row-new { font-weight: 600; color: var(--green-mid, #3a6b59); }
.vx-lr-row-delta {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--gold-deep,#A07840);
}
.vx-lr-residual {
  margin: 8px 0 12px;
  font-size: 0.85rem;
  color: var(--charcoal-soft, #7a7468);
  font-style: italic;
}
.vx-lr-cta-row { display: flex; justify-content: flex-end; gap: 10px; }
.vx-lr-secondary, .vx-lr-primary {
  padding: 8px 16px;
  border-radius: 6px;
  font-family: var(--ff-b, 'DM Sans', sans-serif);
  font-size: 0.88rem; font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease;
}
.vx-lr-secondary {
  background: transparent;
  color: var(--charcoal-soft, #4a4a4a);
  border: 1px solid rgba(0, 0, 0, 0.18);
}
.vx-lr-secondary:hover { border-color: var(--charcoal, #3a342b); color: var(--charcoal, #3a342b); }
.vx-lr-primary {
  background: var(--green, #2C4A3E);
  color: #fff; border: none;
}
.vx-lr-primary:hover { background: #1f3b30; }
@media (max-width: 600px) {
  .vx-lock-redistribution { padding: 0 1rem; }
  .vx-lr-card { padding: 14px 16px; }
  .vx-lr-row { flex-direction: column; gap: 4px; align-items: flex-start; }
  .vx-lr-cta-row { flex-direction: column-reverse; }
  .vx-lr-secondary, .vx-lr-primary { width: 100%; }
}
.vx-resize-foot {
  display: flex; justify-content: flex-end; gap: 10px;
}
.vx-resize-secondary,
.vx-resize-primary {
  padding: 9px 18px;
  border-radius: 6px;
  font-family: var(--ff-b, 'DM Sans', sans-serif);
  font-size: 0.9rem; font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease;
}
.vx-resize-secondary {
  background: transparent;
  color: var(--charcoal-soft, #4a4a4a);
  border: 1px solid rgba(0, 0, 0, 0.18);
}
.vx-resize-secondary:hover { border-color: var(--charcoal, #3a342b); color: var(--charcoal, #3a342b); }
.vx-resize-primary {
  background: var(--green, #2C4A3E);
  color: #fff;
  border: none;
}
.vx-resize-primary:hover { background: #1f3b30; }
.vx-resize-primary[disabled] { opacity: 0.5; cursor: not-allowed; }
@media (max-width: 600px) {
  .vx-resize-mount { padding: 0 12px; }
  .vx-resize-row { flex-wrap: wrap; gap: 10px; padding: 12px 14px; }
  .vx-resize-copy { flex: 1 1 100%; font-size: 0.95rem; }
  .vx-resize-cta { width: 100%; }
  .vx-resize-modal { padding: 22px 20px; }
  .vx-resize-input-wrap { padding: 12px 14px; }
  .vx-resize-input { font-size: 1.3rem; }
  .vx-resize-foot { flex-direction: column-reverse; }
  .vx-resize-secondary, .vx-resize-primary { width: 100%; }
}

/* ════════════════════════════════════════════════════════════════════════
   Feature C — Cross-category pressure dashboard (2026-05-26)
   Sits below the Allocated/Budget/Remaining strip. Two-column-feeling
   panel: an editorial header on top, then a stack of pressure rows
   below, then a CTA. Brand-aligned: Cormorant italic headline, DM Mono
   eyebrows, gold/green/charcoal accents matched to verdict.
   ════════════════════════════════════════════════════════════════════════ */
.vx-pressure-dashboard {
  max-width: 960px;
  margin: 14px auto 22px;
  padding: 0 22px;
}
.vx-pressure-dashboard[hidden] { display: none; }
.vx-pd-inner {
  background: rgba(248, 246, 241, 0.7);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 10px;
  padding: 18px 22px;
}
.vx-pd-header { margin-bottom: 12px; }
.vx-pd-eyebrow {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  color: var(--gold-deep,#A07840);
  margin-bottom: 4px;
}
.vx-pd-headline {
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-style: italic;
  font-size: 1.15rem;
  line-height: 1.35;
  color: var(--charcoal, #3a342b);
}
.vx-pd-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}
.vx-pd-row {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 14px;
  align-items: center;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.05);
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.15s ease;
}
.vx-pd-row:hover { background: rgba(255, 255, 255, 0.95); transform: translateX(2px); }
.vx-pd-row[data-verdict="underfunded"]   { border-left: 3px solid var(--gold-deep,#A07840); }
.vx-pd-row[data-verdict="no_target"]     { border-left: 3px solid var(--gold-deep,#A07840); }
.vx-pd-row[data-verdict="no_priorities"] { border-left: 3px solid var(--gold-deep,#A07840); }
.vx-pd-row[data-verdict="overfunded"]    { border-left: 3px solid var(--green, #2C4A3E); }
.vx-pd-row-eyebrow {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  font-weight: 500;
}
.vx-pd-row-copy {
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--charcoal-soft, #4a4a4a);
}
.vx-pd-cta-row { margin-top: 14px; display: flex; justify-content: flex-end; }
.vx-pd-cta {
  padding: 9px 18px;
  background: var(--green, #2C4A3E);
  color: #fff;
  border: none;
  border-radius: 6px;
  font-family: var(--ff-b, 'DM Sans', sans-serif);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.18s ease;
}
.vx-pd-cta:hover { background: #1f3b30; }
/* Click-through flash so the eye lands on the right section when a row
   is tapped. Brief gold pulse, ~700ms, no layout shift. */
@keyframes vxPdTargetFlash {
  0%   { box-shadow: 0 0 0 0 rgba(200, 169, 110, 0); }
  35%  { box-shadow: 0 0 0 4px rgba(200, 169, 110, 0.35); }
  100% { box-shadow: 0 0 0 0 rgba(200, 169, 110, 0); }
}
.vxb-section.vx-pd-target-flash { animation: vxPdTargetFlash 0.85s ease-out 1; border-radius: 8px; }
@media (max-width: 600px) {
  .vx-pressure-dashboard { padding: 0 12px; }
  .vx-pd-inner { padding: 14px 16px; }
  .vx-pd-row { grid-template-columns: 1fr; gap: 4px; padding: 10px 12px; }
  .vx-pd-row-eyebrow { font-size: 0.54rem; }
  .vx-pd-cta-row { justify-content: stretch; }
  .vx-pd-cta { width: 100%; }
}

.timeline-wrap { position: relative; z-index: 1; max-width: 900px; margin: 0 auto; padding: 0 2rem 4rem; }
/* ⚑ NO RAIL, NO GUTTER. Stephen 2026-08-17, from his iPhone: "the guides should
   all align left like the Budget page for consistency."
   He is right, and removing the numerals this morning is what exposed it — a
   56px column holding one 9px dot is a gutter earning nothing, and on a 402px
   phone it is 14% of the width taken from the card that has the content in it.
   The dates in each band already carry the sequence the rail was drawing. */
.timeline-rail { position: relative; }
.phase { display: flex; gap: 0; margin-bottom: 1.4rem; position: relative; }
.phase-content { flex: 1; min-width: 0; }
.phase-card { background: white; border: 1px solid var(--border-g); border-radius: 16px; overflow: hidden; box-shadow: 0 2px 12px rgba(44,74,62,.04); }
.phase-band { padding: 1rem 1.5rem; border-bottom: 1px solid var(--border-g); display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.phase:nth-child(1) .phase-band { background: #F8F3EA; }
.phase:nth-child(2) .phase-band { background: #EDF4F0; }
.phase:nth-child(3) .phase-band { background: #F3EFF7; }
.phase:nth-child(4) .phase-band { background: #FAF3EC; }
.phase:nth-child(5) .phase-band { background: #F5EDEE; }
.band-left { flex: 1; display: flex; align-items: center; gap: 9px; }
.phase-dot-sm { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.phase:nth-child(1) .phase-dot-sm { background: var(--gold); }
.phase:nth-child(2) .phase-dot-sm { background: var(--sage); }
.phase:nth-child(3) .phase-dot-sm { background: #7B5EA8; }
.phase:nth-child(4) .phase-dot-sm { background: var(--gold-deep); }
.phase:nth-child(5) .phase-dot-sm { background: var(--rose); }
.phase-title { font-family: var(--ff-d); font-size: 1.1rem; font-weight: 500; color: var(--green); line-height: 1.1; }
.phase-title em { font-style: italic; }
.phase:nth-child(1) .phase-title em { color: var(--gold); }
.phase:nth-child(2) .phase-title em { color: var(--sage); }
/* 2026-05-14 — Tokenized to --plum (defined in :root as #7B5EA8). The
   other four phases already used tokens (--gold, --sage, --gold-deep,
   --rose); this was the lone raw-hex outlier. */
.phase:nth-child(3) .phase-title em { color: var(--plum, #7B5EA8); }
.phase:nth-child(4) .phase-title em { color: var(--gold-deep); }
.phase:nth-child(5) .phase-title em { color: var(--rose); }
.band-right { flex-shrink: 0; text-align: right; font-family: var(--ff-m); font-size: .54rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); line-height: 1.6; white-space: nowrap; }
.band-time { font-family: var(--ff-d); font-size: 1rem; font-weight: 400; color: var(--green); display: block; letter-spacing: 0; }
.phase-body { padding: .9rem 1.5rem 1.1rem; }
/* 2026-08-08 (Stephen) — THREE ACROSS, not auto-fill. auto-fill packed four
   185px cards onto a wide screen and squeezed each name to ~61px, which is what
   started the mid-word breaks. Three fixed columns give every name room for its
   longest word on one or two whole-word lines, and mobile is unaffected because
   it collapses to two columns at 900px and one at 640px. */
.guides-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: .38rem;
  /* 2026-08-08 (Stephen) — "if anything needs more than one row then every box
     is made the same height for visual consistency." Grid items already stretch
     within their own row; 1fr rows make every ROW match the tallest too, so one
     two-line name lifts the whole section rather than leaving a ragged block.
     It costs nothing when everything fits on one line. */
  grid-auto-rows: 1fr; }
.guide-link { display: flex; align-items: center; gap: 9px; padding: .5rem .75rem; border: 1px solid var(--border-g); border-radius: 9px; text-decoration: none; color: var(--ink); background: white; transition: all .15s; }
.guide-link:hover { background: var(--green-pale); border-color: rgba(44,74,62,.2); transform: translateY(-1px); box-shadow: 0 3px 10px rgba(44,74,62,.07); }
.guide-name { font-size: .8rem; font-weight: 500; color: var(--ink); line-height: 1.25; flex: 1;
  /* 2026-08-07 (Stephen, reported as "font issues on the Vendor+ table of
     contents") — the clipped BOOKED pill was a flex overflow, not a font.

     A flex item defaults to min-width:auto, so this span could not shrink
     below its longest UNBREAKABLE word. The status pills correctly carry
     flex-shrink:0 — they are badges and must never squash — so at the grid's
     185px minimum column there is 117px for name plus pill, and a 13-letter
     word like "Entertainment" needs ~91px against the pill's 62px. The row's
     min-content came to ~153px and the surplus pushed the pill straight out
     past the card's right edge, where the next grid cell cut it.

     min-width:0 lets the name shrink; overflow-wrap lets a single long word
     break rather than setting the floor itself. Standard flex sizing, so this
     was never Chrome-specific — Safari and Firefox clip it identically.

     2026-08-08 — `anywhere` was too strong and Stephen caught it on the table
     of contents: "Separate Ceremon / y Site", "Destinati / on Specialist".
     `anywhere` also shrinks MIN-CONTENT to a single character, so the browser
     breaks inside a word even when wrapping at the spaces would have fitted.
     `break-word` breaks a word only as a genuine last resort and leaves normal
     wrapping alone — and it is min-width:0, not the overflow-wrap value, that
     actually fixed the clipped pill, so nothing regresses by softening it. */
  /* 2026-08-08 — break-word alone was not enough: the name had only 61px and
     "Destination" needs ~72px, so it still broke as a last resort. Stephen:
     "we can delete the leading icons — they are not a theme carried to any
     other pages." That returns 35px (26px icon + 9px gap) to every name, which
     is more than a floor-and-wrap hack bought and costs no second line.
     min-width:0 stays — it is what keeps the status pill inside the card. */
  min-width: 0; overflow-wrap: break-word; }
.guide-arrow { font-size: .68rem; color: var(--ink-faint); flex-shrink: 0; transition: transform .12s; }
.guide-link:hover .guide-arrow { transform: translateX(2px); color: var(--green-mid); }
.guide-budgeted { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 4px; background: var(--green); color: white; font-family: var(--ff-m); font-size: .58rem; font-weight: 600; flex-shrink: 0; letter-spacing: 0; cursor: pointer; transition: transform .12s ease; }
.guide-partial { display: inline-flex; align-items: center; justify-content: center; padding: 0 5px; height: 18px; border-radius: 4px; background: var(--gold-pale); border: 1px solid var(--border-g); color: var(--gold-deep); font-family: var(--ff-m); font-size: .5rem; font-weight: 600; flex-shrink: 0; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; cursor: pointer; transition: transform .12s ease; }
.guide-skipped { font-family: var(--ff-m); font-size: .56rem; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); flex-shrink: 0; opacity: .7; cursor: pointer; transition: opacity .12s ease, transform .12s ease; }
/* 2026-04-30: badges double as Plan/Skip toggles. Hover lifts and a
   tooltip clarifies the affordance — click the badge to flip a
   category between planned and skipped. */
.guide-budgeted:hover, .guide-partial:hover { transform: scale(1.12); }
.guide-skipped:hover { opacity: 1; transform: scale(1.05); }
/* 2026-09-07 (Stephen) — DEMO: all vendor interview guide tiles are open now (was: dimmed +
   🔒 for every card except Venue & Catering). See the matching openInterview() gate removal
   above for the functional side of this change. */
/* Phase 3 follow-up — Interview tiles auto-dim when their Budget category
   is fully skipped (0 items checked / manual target = 0). Hover reveals
   a small "Add to plan" affordance that scrolls Budget to the matching
   section so the couple can reverse the decision in one click. */
.guide-link.is-budget-skipped { opacity: .55; background: rgba(255,255,255,.55); }
.guide-link.is-budget-skipped:hover { opacity: .92; }
.guide-link.is-budget-skipped .guide-name { color: var(--ink-faint, #88928d); }
.guide-link.is-budget-skipped::after {
  content: "+ Add to plan";
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  background: var(--green, #2C4A3E); color: #fff;
  font-family: var(--ff-m,'DM Mono',monospace); font-size: .54rem; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 100px;
  opacity: 0; pointer-events: none; transition: opacity .18s ease;
}
.guide-link.is-budget-skipped { position: relative; }
.guide-link.is-budget-skipped:hover::after { opacity: 1; }

#section-reviews .hero { position: relative; z-index: 1; text-align: center; padding: 1rem 2rem 1.25rem; max-width: 680px; margin: 0 auto; }
.hero-eyebrow { display: inline-flex; align-items: center; background: rgba(200,169,110,.1); border: 1px solid rgba(200,169,110,.35); border-radius: 40px; padding: 6px 18px; font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: var(--green-mid); font-weight: 500; margin-bottom: 1.5rem; }
#section-reviews .hero h1 { font-family: var(--ff-d); font-size: clamp(2.4rem,5vw,3.8rem); font-weight: 400; line-height: 1.08; color: var(--green); margin-bottom: 1.25rem; letter-spacing: -.02em; }
#section-reviews .hero h1 em { font-style: italic; color: var(--gold); }
#section-reviews .hero p { font-size: 1rem; line-height: 1.8; color: var(--text-mid); font-weight: 300; max-width: 480px; margin: 0 auto 2.5rem; }
.privacy-strip { display: inline-flex; align-items: center; gap: 20px; background: rgba(107,143,113,0.08); border: 1px solid rgba(107,143,113,0.25); border-radius: 2px; padding: 10px 20px; font-size: 0.72rem; color: var(--sage); letter-spacing: 0.05em; margin-bottom: 1.25rem; }
.privacy-strip .dot { width: 5px; height: 5px; background: var(--sage); border-radius: 50%; flex-shrink: 0; }
.disclaimer-box { background: rgba(185,64,64,0.04); border: 1.5px solid rgba(185,64,64,0.28); border-radius: var(--radius-lg); padding: 22px 28px; margin-bottom: 1.25rem; }
.disclaimer-box h4 { font-family: var(--ff-m); font-size: 0.65rem; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--danger); margin-bottom: 10px; display: flex; align-items: center; gap: 8px; }
.disclaimer-box p { font-size: 0.82rem; color: var(--text-mid); line-height: 1.7; }
.disclaimer-check { display: flex; align-items: flex-start; gap: 12px; margin-top: 16px; cursor: pointer; }
.disclaimer-check input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--green); flex-shrink: 0; margin-top: 2px; cursor: pointer; }
.disclaimer-check label { font-size: 0.8rem; font-weight: 500; color: var(--charcoal); line-height: 1.55; cursor: pointer; }
.upload-wrapper { position: relative; z-index: 1; max-width: 660px; margin: 0 auto 4rem; padding: 0 1.5rem; }
.upload-zone { border: 1.5px dashed var(--border-strong); border-radius: var(--radius-lg); background: rgba(242,235,224,0.4); padding: 3rem 2rem; text-align: center; cursor: pointer; transition: all 0.3s ease; position: relative; }
.upload-zone:hover,.upload-zone.drag-over { border-color: var(--gold); background: rgba(201,169,110,0.06); transform: translateY(-1px); }
.upload-zone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
.upload-icon { margin: 0 auto 1rem; }
.upload-zone h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.35rem; font-weight: 400; color: var(--ink); margin-bottom: 0.4rem; }
.upload-zone p { font-size: 0.8rem; color: var(--ink-faint); margin-bottom: 1rem; }
.upload-btn { display: inline-flex; align-items: center; gap: 8px; font-family: var(--ff-b); font-size: .82rem; color: var(--green); background: transparent; border: 1.5px solid rgba(44,74,62,.28); padding: 10px 22px; border-radius: 40px; cursor: pointer; transition: all .25s ease; pointer-events: none; }
.upload-zone:hover .upload-btn { border-color: var(--green); background: rgba(44,74,62,.06); }
/* 2026-06-19 — Three-row stack: row 1 = file info / photo thumbnails,
   row 2 = full-width disclosure, row 3 = action buttons. Replaces the
   side-by-side layout that wrapped badly as more photos were added. */
.file-selected { display: none; flex-direction: column; align-items: stretch; gap: 12px; background: rgba(107,143,113,0.08); border: 1px solid rgba(107,143,113,0.3); border-radius: var(--radius); padding: 12px 16px; margin-top: 1rem; }
.file-selected.visible { display: flex; }
/* Row 2 — photo disclosure: full-width, hairline divider above it. */
.file-photo-note { margin: 0; padding-top: 12px; border-top: 1px solid rgba(107,143,113,0.18); }
/* Row 3 — actions anchored at the bottom, right-aligned. */
.file-selected .file-actions { justify-content: flex-end; }
.file-info { display: flex; align-items: center; gap: 10px; font-size: 0.82rem; }
.file-info[hidden] { display: none; }
.file-name { font-weight: 500; color: var(--ink); }
/* 2026-05-30 multi-photo upload — count badge + thumbnail strip + page-N labels.
   Layout: vertical when there are thumbnails (they need horizontal scroll
   room); single-row when there's just one file. */
.file-info-multi { flex-direction: column; align-items: flex-start; gap: 10px; flex: 0 0 auto; min-width: 0; }
.file-multi-summary { display: flex; align-items: center; gap: 8px; font-size: 0.82rem; }
.file-multi-count { font-weight: 500; color: var(--ink); }
.file-multi-total { color: var(--text-muted, #88928d); font-size: .78rem }
.file-multi-thumbs {
  display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 2px; width: 100%;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.file-multi-thumb {
  flex-shrink: 0; width: 56px; display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.file-multi-thumb img {
  width: 56px; height: 72px; object-fit: cover;
  border: 1px solid rgba(44,74,62,.15); border-radius: 6px;
  background: rgba(44,74,62,.04);
}
.file-multi-thumb-label {
  font-family: var(--ff-m, 'DM Mono', monospace); font-size: .58rem;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted, #88928d);
}
.file-multi-hint {
  font-size: .72rem; font-style: italic; color: var(--text-muted, #88928d); line-height: 1.4;
}
@media (max-width: 480px) {
  .file-multi-thumb { width: 48px }
  .file-multi-thumb img { width: 48px; height: 60px }
}
.file-size { color: var(--ink-muted); }
.btn-analyze { font-family: var(--ff-b); font-size: .85rem; font-weight: 500; letter-spacing: .02em; color: var(--cream); background: var(--green); border: none; padding: 11px 26px; border-radius: 40px; cursor: pointer; transition: all .25s ease; white-space: nowrap; box-shadow: 0 4px 20px rgba(44,74,62,.2); }
.btn-analyze:hover { background: var(--green-mid); transform: translateY(-2px); }
.btn-analyze:disabled { opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: none; }
.processing { display: none; flex-direction: column; align-items: center; gap: 1rem; padding: 3rem; text-align: center; }
.processing.visible { display: flex; }
.spinner-ring { width: 48px; height: 48px; border: 1.5px solid var(--border); border-top-color: var(--gold); border-radius: 50%; animation: spin 1.2s linear infinite; }
.processing-text { font-family: var(--ff-d); font-size: 1.2rem; font-style: italic; color: var(--green-mid); }
.processing-sub { font-size: 0.75rem; color: var(--ink-faint); letter-spacing: 0.05em; }
#results { display: none; position: relative; z-index: 1; max-width: 900px; margin: 0 auto 6rem; padding: 0 1.5rem; animation: fadeUp 0.6s ease both; }
#results.visible { display: block; }
@keyframes fadeUp { from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)} }
.summary-bar { display: grid; grid-template-columns: repeat(3,1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 2.5rem; }
.summary-cell { background: var(--cream); padding: 1.25rem 1.5rem; text-align: center; }
.summary-cell .label { font-size: 0.65rem; font-weight: 500; letter-spacing: 0.15em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.4rem; }
.summary-cell .value { font-family: 'Cormorant Garamond', serif; font-size: 2rem; font-weight: 500; line-height: 1; }
.val-critical { color: var(--danger); }
.val-warning { color: var(--amber-risk); }
.val-caution { color: var(--gold); }
.val-ok { color: var(--sage); }
/* 2026-05-22 — Gauge bleed fix per Stephen's screenshot. The "MODERATE
   RISK" label inside the gauge SVG was overlapping body prose on
   certain viewports — gauge-wrap had no width constraint, gauge-info
   had no min-width-0, so flex squeezed the text column. Added explicit
   max-width on gauge-wrap + min-width:0 on gauge-info so flex resolves
   cleanly across viewports. */
/* 2026-06-19 — Stephen: stack the gauge centered on top with the assessment
   full-width below, instead of a 160px gauge beside a cramped text column that
   forced the summary + "risk pattern depth" header to wrap. */
.gauge-section { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; background: var(--parchment); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 1.5rem 2rem; margin-bottom: 2.5rem; }
/* 2026-06-19 — tight meter block: the min-height/padding-bottom were leftovers
   from the old absolutely-positioned label and wasted vertical space (worst on
   tablet/mobile). Size to content now. */
.gauge-wrap { position: relative; flex-shrink: 0; width: 160px; max-width: 160px; padding-bottom: 2px; display: flex; flex-direction: column; align-items: center; }
.gauge-wrap svg { display: block; max-width: 100%; height: auto; }
.gauge-info { width: 100%; min-width: 0; padding-top: 0; }
.gauge-info > h3 { text-align: center; margin-top: 0; }
.gauge-info > p { text-align: left; }
.gauge-label { margin-top: 4px; text-align: center; position: static; transform: none; }
.gauge-score { font-family: 'Cormorant Garamond', serif; font-size: 2.2rem; font-weight: 600; display: block; line-height: 1; }
.gauge-word { font-size: 0.65rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--ink-muted); }
.gauge-info h3 { font-family: var(--ff-d); font-size: 1.4rem; font-weight: 400; color: var(--green); margin-bottom: 0.5rem; }
.gauge-info p { font-size: 0.85rem; line-height: 1.65; color: var(--ink-muted); }
.section-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; }
.section-header h2 { font-family: var(--ff-d); font-size: 1.6rem; font-weight: 400; color: var(--green); letter-spacing: -.01em; }
.section-line { flex: 1; height: 1px; background: var(--border); }
.risks-grid { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 3rem; }
.risk-card { border-radius: var(--radius-lg); border: 1px solid; overflow: hidden; animation: fadeUp 0.5s ease both; transition: transform 0.2s, box-shadow 0.2s; }
.risk-card:hover { transform: translateY(-2px); box-shadow: 0 8px 32px rgba(28,24,16,0.08); }
.risk-card.critical { border-color: rgba(185,64,64,0.3); background: rgba(185,64,64,0.03); }
.risk-card.warning { border-color: rgba(201,123,58,0.3); background: rgba(201,123,58,0.03); }
.risk-card.caution { border-color: rgba(201,169,110,0.3); background: rgba(201,169,110,0.03); }
.risk-card-header { display: flex; align-items: flex-start; gap: 1rem; padding: 1.25rem 1.5rem 0.75rem; }
.severity-pill { flex-shrink: 0; font-size: 0.58rem; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase; padding: 3px 9px; border-radius: 2px; margin-top: 3px; }
.critical .severity-pill { background: rgba(185,64,64,0.12); color: var(--danger); }
.warning .severity-pill { background: rgba(201,123,58,0.12); color: var(--amber-risk); }
.caution .severity-pill { background: rgba(201,169,110,0.15); color: var(--gold-deep); }
.risk-title { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 500; flex: 1; line-height: 1.3; }
.risk-body { padding: 0 1.5rem 1.25rem; }
.risk-desc { font-size: 0.83rem; line-height: 1.65; color: var(--ink-muted); margin-bottom: 0.75rem; }
.risk-meta { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.risk-tag { font-size: 0.68rem; letter-spacing: 0.06em; color: var(--ink-muted); background: rgba(28,24,16,0.05); border-radius: 2px; padding: 2px 8px; }
.risk-fee { font-size: 0.75rem; font-weight: 500; color: var(--danger); background: rgba(185,64,64,0.08); border-radius: 2px; padding: 2px 8px; }
/* 2026-07-28 — hidden-fees table: scroll, never clip. `overflow:hidden` (kept
   for the rounded corners) was cutting off the right-most "Trigger Condition"
   column whenever the report column was narrower than the 4-column table
   (desktop viewports but a constrained content column). `overflow-x:auto` lets
   the body scroll horizontally instead of clipping, matching the report/
   DocCompare table treatment; on a wide column it fits and shows no scrollbar. */
.fee-table-wrap { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 3rem; }
.fee-table td:last-child { min-width: 160px; }
.fee-table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
.fee-table thead { background: var(--parchment); }
.fee-table th { font-size: 0.62rem; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); padding: 0.85rem 1.25rem; text-align: left; border-bottom: 1px solid var(--border); }
.fee-table td { padding: 0.9rem 1.25rem; border-bottom: 1px solid var(--border); color: var(--ink); vertical-align: top; }
.fee-table tr:last-child td { border-bottom: none; }
.fee-table tr:hover td { background: rgba(201,169,110,0.04); }
.fee-amount { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: var(--fs-amount,.9rem); font-weight: 500; font-variant-numeric: tabular-nums; color: var(--danger); white-space: nowrap; }
.fee-likelihood { display: inline-block; font-size: 0.65rem; font-weight: 500; letter-spacing: 0.08em; padding: 2px 7px; border-radius: 2px; }
.likelihood-high { background: rgba(185,64,64,0.1); color: var(--danger); }
.likelihood-med { background: rgba(201,123,58,0.1); color: var(--amber-risk); }
.likelihood-low { background: rgba(107,143,113,0.1); color: var(--sage); }
/* 2026-07-29 — DocCompare side-by-side in the fee-table style. Equal-width
   columns, values wrap. ONE best-fit call-out on the winning column's header
   (not per cell), with a soft tint down that column. */
.vx-cmp-fee-table { table-layout: fixed; }
.vx-cmp-fee-table th, .vx-cmp-fee-table td { overflow-wrap: anywhere; word-break: break-word; font-variant-numeric: tabular-nums; vertical-align: top; }
.vx-cmp-fee-table .vx-cmp-ft-dim { font-weight: 500; color: var(--ink); }
.vx-cmp-fee-table td.vx-cmp-ft-empty { color: var(--ink-faint); }
.vx-cmp-fee-table th.vx-cmp-ft-bestcol { color: var(--green,#2C4A3E); }
.vx-cmp-ft-bestbadge { display: block; margin-top: 4px; font-size: 0.54rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--green,#2C4A3E); }
.vx-cmp-fee-table td.vx-cmp-ft-bestcell { background: rgba(44,74,62,0.05); }
/* 2026-07-29 — calm Quick-Read lead on the compare result (editorial, like DocCheck). */
.vx-cmp-quickread { max-width: 720px; margin: 0 auto 1.4rem; text-align: center; }
.vx-cmp-qr-headline { font-family: var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif); font-size: 1.35rem; font-weight: 500; line-height: 1.32; color: var(--ink); margin: 0 0 0.5rem; }
.vx-cmp-qr-note { font-size: 0.88rem; color: var(--ink-mid,#4A4A4A); margin: 0; }
/* 2026-07-29 (Stephen) — on Compare, collapse the upload zones so the analysis
   is immediately viewable; the H1/H2 header stays. "Compare other quotes" restores. */
.upload-wrapper.vx-cmp-collapsed .vx-cmp-meta,
.upload-wrapper.vx-cmp-collapsed #vxCmpZones,
.upload-wrapper.vx-cmp-collapsed .vx-cmp-actions,
.upload-wrapper.vx-cmp-collapsed .vx-cmp-mode,
.upload-wrapper.vx-cmp-collapsed #vxCmpAsksWrap { display: none; }
/* DocCheck-style stacked action row on the compare result — flex row on desktop;
   the buttons go full-width and stack on mobile via .vx-cr-ab-btn{width:100%}. */
.vx-cmp-result-actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; max-width: 640px; margin: 0 auto 1.6rem; }
/* the compare fee-table fits the mobile width (both quotes fully visible — no clip) */
.fee-table-wrap .vx-cmp-fee-table { min-width: 0; }
/* Vera Quick-Read pop-up modal content (DocCheck parity) */
.vx-cmp-qr-best { margin-top: 12px; font-size: 0.9rem; color: var(--ink); line-height: 1.5; }
.vx-cmp-qr-best-label { display: inline-block; font-size: 0.58rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--green,#2C4A3E); background: rgba(44,74,62,0.08); padding: 2px 7px; border-radius: 3px; margin-right: 8px; vertical-align: middle; }
.vx-cmp-qr-pts { margin-top: 14px; }
.vx-cmp-qr-pts-label { font-size: 0.58rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px; }
.vx-cmp-qr-pts ul { margin: 0; padding-left: 18px; }
.vx-cmp-qr-pts li { font-size: 0.86rem; color: var(--ink-mid,#4A4A4A); margin-bottom: 6px; line-height: 1.5; }
.rec-list { display: flex; flex-direction: column; gap: 0.75rem; margin-bottom: 3rem; }
.rec-item { display: flex; gap: 1rem; padding: 1rem 1.25rem; background: rgba(107,143,113,0.05); border: 1px solid rgba(107,143,113,0.2); border-radius: var(--radius); font-size: 0.84rem; line-height: 1.6; color: var(--ink-muted); animation: fadeUp 0.5s ease both; }
.rec-num { flex-shrink: 0; width: 22px; height: 22px; background: var(--sage); color: white; border-radius: 50%; font-size: 0.65rem; font-weight: 600; display: flex; align-items: center; justify-content: center; margin-top: 1px; }
/* 2026-07-28 — .results-footer / .cta-row / .btn-cta* removed with the retired
   report footer (Save as PDF / Analyze Another moved into the action row). */
.error-box { display: none; margin-top: 1rem; padding: 1rem 1.25rem; background: rgba(185,64,64,0.06); border: 1px solid rgba(185,64,64,0.25); border-radius: var(--radius); font-size: 0.82rem; color: var(--danger); line-height: 1.6; }
.error-box.visible { display: block; }
.divider-ornament { display: flex; align-items: center; gap: 1rem; margin: 0 auto 2.5rem; max-width: 300px; color: var(--gold); font-size: 1rem; }
.divider-ornament::before,.divider-ornament::after { content: ''; flex: 1; height: 1px; background: var(--border-strong); }

/* 2026-07-28 — Contracts+ unified action row (replaces the standalone Quick-Read
   pill). Lives in the upload card, with the Analyze control: ONE primary button
   that reads "Analyze" before a read and swaps to "Scan another" after (re-arming
   the upload), plus a "Quick-Read" control that opens Vera's pop-up (the reused
   .vxc-lock-modal + .vx-vera-confirm-head persona header) and "Save as PDF" — both
   greyed until the analysis completes, then enabled. Post-analysis the green
   highlight shifts onto Quick-Read so it reads as the couple's next step.
   Everything in the pop-up comes from the analysis already run (no second model
   call). Reuses surface tokens; invents no new colors. The
   .vx-qr-cov-* / .vxda-* classes power the screen-only coverage list in ④. */
/* 2026-07-29 — post-analysis scroll lands the reviewed document card just below the
   fixed header stack (header 0–74 + profile bar 74–128 + Vera nav 129–183), not tucked
   underneath it. Mirrors the .vxb-section scroll-margin convention. */
#fileSelected { scroll-margin-top: 195px; }
.vx-cr-actionbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; justify-content: flex-start; flex-basis: 100%; }
/* 2026-07-28 — buttons start at the left (under the document icon) and are all one uniform size. */
.vx-cr-actionbar .btn-analyze, .vx-cr-actionbar .vx-cr-ab-btn { display: inline-flex; align-items: center; justify-content: center; min-width: 132px; min-height: 42px; box-sizing: border-box; }
.vx-cr-ab-sep { color: var(--gold,#C8A96E); align-self: center; }
/* Secondary controls (Quick-Read / Save as PDF) — the surface's white-outline
   secondary token, sized to sit beside .btn-analyze, with a clear GREY disabled
   state until the analysis completes. */
.vx-cr-ab-btn { font-family: var(--ff-b); font-size: .85rem; font-weight: 500; letter-spacing: .02em; color: var(--green); background: var(--white); border: 1.5px solid var(--green-lt); padding: 10px 20px; border-radius: 40px; cursor: pointer; transition: all .25s ease; white-space: nowrap; display: inline-flex; align-items: center; gap: 7px; }
.vx-cr-ab-btn:hover:not(:disabled) { background: var(--green-pale); border-color: var(--green); transform: translateY(-1px); }
.vx-cr-ab-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.vx-cr-ab-btn:disabled { color: var(--ink-faint,#9a948a); background: var(--parchment,#F0EBE1); border-color: var(--border,#eae5dd); cursor: not-allowed; box-shadow: none; transform: none; }
/* 2026-07-28 — Post-analysis the highlighted (green) button shifts to Quick-Read,
   so it reads as the couple's next step: "Scan another" de-emphasizes to the
   secondary ghost token and Save as PDF stays ghost. Pre-analysis the primary
   (Analyze) keeps the green; Quick-Read stays greyed until the read exists. */
.vx-cr-actionbar .btn-analyze[data-mode="reset"] { color: var(--green); background: var(--white); border: 1.5px solid var(--green-lt); box-shadow: none; }
.vx-cr-actionbar .btn-analyze[data-mode="reset"]:hover { background: var(--green-pale); border-color: var(--green); }
.vx-cr-actionbar .vx-cr-ab-btn.vx-cr-ab-primary { color: var(--cream); background: var(--green); border-color: var(--green); box-shadow: 0 4px 20px rgba(44,74,62,.2); }
.vx-cr-actionbar .vx-cr-ab-btn.vx-cr-ab-primary:hover:not(:disabled) { background: var(--green); border-color: var(--green); transform: translateY(-1px); }

/* Vera pop-up body (rendered inside the reused .vxc-lock-modal shell). */
.vx-qr-modal { max-width: 480px; }
.vx-qr-modal-close { margin-left: auto; }
.vx-qr-modal-title { font-family: var(--ff-d,'Cormorant Garamond',serif); font-size: 1.5rem; font-style: italic; color: var(--green,#2C4A3E); margin: 0 0 6px; line-height: 1.2; }
.vx-qr-modal-meta { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .78rem; line-height: 1.5; color: var(--ink-mid,#4A4A4A); margin: 0 0 12px; }
.vx-qr-modal-meta .vx-qr-meta-sep { color: var(--gold,#C8A96E); margin: 0 7px; }
.vx-qr-modal-meta strong { color: var(--green,#2C4A3E); font-weight: 600; }
.vx-qr-modal-lead { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .92rem; line-height: 1.6; color: var(--ink,#2C2C2C); margin: 0 0 4px; }
.vx-qr-section { margin: 15px 0 0; padding: 14px 0 0; border-top: 1px solid rgba(44,74,62,.09); }
.vx-qr-sec-eyebrow { font-family: var(--ff-m,'DM Mono',monospace); font-size: .6rem; letter-spacing: .13em; text-transform: uppercase; color: var(--gold-deep,#A07840); margin: 0 0 7px; }
.vx-qr-sec-num { color: var(--gold,#C8A96E); margin-right: 6px; }
.vx-qr-sec-body { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .86rem; line-height: 1.55; color: var(--ink,#2C2C2C); margin: 0; }
.vx-qr-sec-body strong { color: var(--green,#2C4A3E); font-weight: 600; }
.vx-qr-sec-hint { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .8rem; line-height: 1.5; color: var(--ink-mid,#4A4A4A); margin: 7px 0 0; }
.vx-qr-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.vx-qr-list > li { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .85rem; line-height: 1.45; color: var(--ink,#2C2C2C); padding-left: 15px; position: relative; }
.vx-qr-list > li::before { content: '·'; position: absolute; left: 3px; color: var(--gold,#C8A96E); font-weight: 600; }
.vx-qr-list > li strong { color: var(--green,#2C4A3E); font-weight: 600; }
.vx-qr-li-sub { display: block; font-size: .77rem; color: var(--ink-muted,#7A7A7A); margin-top: 2px; font-style: italic; }
.vx-qr-counsel { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .8rem; line-height: 1.55; color: var(--ink-muted,#7A7A7A); margin: 16px 0 0; padding-top: 12px; border-top: 1px solid rgba(44,74,62,.09); }
/* Budget-coverage advisory — soft gold sub-band (never rose). Screen-only. */
.vx-qr-coverage { margin: 12px 0 0; padding: 14px 16px; border: 1px solid rgba(200,169,110,.4); border-radius: 12px; background: var(--cream-warm,#F0EBE1); }
.vx-qr-cov-summary { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .86rem; line-height: 1.5; color: var(--ink,#2C2C2C); margin: 0; }
.vx-qr-cov-summary .vx-qr-cov-glyph { color: var(--gold-deep,#A07840); font-weight: 600; margin-right: 5px; }
.vx-qr-cov-toggle { margin-top: 9px; }
.vx-qr-cov-toggle .vxda-chev { font-size: 1rem; line-height: 1; color: #9a948a; transition: transform .18s ease; display: inline-block; }
.vx-qr-cov-toggle.is-open .vxda-chev { transform: rotate(90deg); }
.vx-qr-cov-group { margin: 0 0 10px; }
.vx-qr-cov-group:last-of-type { margin-bottom: 0; }
.vx-qr-cov-group-label { font-family: var(--ff-m,'DM Mono',monospace); font-size: .58rem; letter-spacing: .12em; text-transform: uppercase; color: var(--gold-deep,#A07840); margin: 0 0 7px; }
.vx-qr-cov-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.vx-qr-cov-list li { font-size: .84rem; line-height: 1.4; color: var(--green,#2C4A3E); padding-left: 15px; position: relative; }
.vx-qr-cov-list li::before { content: '·'; position: absolute; left: 3px; color: var(--gold,#C8A96E); }
/* On-surface paid + confidential Contracts+ strip (part d). Static, in-flow,
   distinct from the #sn-3 nav premium-lock. Gold soft-chip + confidential line. */
.vx-cr-paid-band { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 .85rem; padding: 10px 14px; border: 1px solid rgba(200,169,110,.35); border-radius: 10px; background: rgba(200,169,110,.08); }
.vx-cr-paid-pill { flex: 0 0 auto; font-family: var(--ff-m,'DM Mono',monospace); font-size: .56rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--gold-deep,#A07840); background: rgba(200,169,110,.18); border: 1px solid rgba(200,169,110,.4); border-radius: 100px; padding: 5px 11px; }
.vx-cr-paid-txt { flex: 1 1 240px; font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .78rem; line-height: 1.5; color: var(--ink-mid,#4A4A4A); font-weight: 300; }
.vx-cr-paid-txt strong { color: var(--green,#2C4A3E); font-weight: 600; }
@media (max-width: 680px) { .vx-qr-modal-title { font-size: 1.32rem; } .vx-cr-actionbar { justify-content: center; } }

.site-footer { position: relative; z-index: 1; text-align: center; padding: 1.5rem 2rem 1.75rem; font-family: var(--ff-m); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); border-top: 1px solid var(--border-g); background: var(--cream-d); }

.profile-card{position:relative;z-index:1;max-width:900px;margin:1rem auto 0;padding:0 2rem}
/* 2026-05-06 — Personalized banner retired from Budget. Wedding Details
 *   is reachable from the top Account-modal nav, so this strip on Budget
 *   is redundant. Keeping the markup so the JS toggles in 8868 / 9274 /
 *   9493 / 21281 / 21897 don't error on a null queried element; the
 *   !important hide neutralizes their style writes. Remove the markup
 *   when one of those code paths is next refactored. */
.pc-applied{display:none !important}
.pc-applied--legacy{background:var(--green);border-radius:14px;padding:.85rem 1.4rem;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.pc-applied-label{font-family:var(--ff-m);font-size:.54rem;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.4);margin-bottom:2px}
.pc-applied-summary{font-size:.84rem;color:white;flex:1;min-width:0}
.pc-edit-btn{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.18);color:rgba(255,255,255,.65);border-radius:20px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:4px 12px;cursor:pointer;transition:all .18s;flex-shrink:0}
.pc-edit-btn:hover{background:rgba(255,255,255,.2);color:white}
.pc-form{background:white;border:1px solid var(--border-g);border-radius:18px;overflow:hidden;box-shadow:0 2px 20px rgba(44,74,62,.05)}
.pc-form-head{padding:1.2rem 1.75rem 1rem;border-bottom:1px solid var(--border-g);background:#F8F3EA;display:flex;align-items:baseline;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.pc-form-title{font-family:var(--ff-d);font-size:1.25rem;font-weight:500;color:var(--green);letter-spacing:-.01em}
.pc-form-title em{font-style:italic;color:var(--gold)}
.pc-form-sub{font-size:.76rem;color:var(--ink-faint);margin-top:2px;font-weight:300}
.pc-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);white-space:nowrap}

button.pc-eyebrow.pc-hide-btn{
 background:transparent;border:1px solid rgba(200,169,110,.3);border-radius:20px;
 padding:5px 12px;cursor:pointer;transition:all .15s;
}
button.pc-eyebrow.pc-hide-btn:hover{background:var(--gold-pale);border-color:var(--gold);color:var(--green)}
button.pc-eyebrow.pc-hide-btn:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.pc-body{padding:1.25rem 1.75rem;display:flex;flex-direction:column;gap:1rem}
.pc-row{display:grid;gap:.7rem}
.pc-row-3{grid-template-columns:1fr 1fr 1fr}
.pc-row-2{grid-template-columns:1fr 1fr}
.pc-field{display:flex;flex-direction:column;gap:5px}
.pc-lbl{font-family:var(--ff-m);font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:var(--green-mid)}
.pc-input{font-family:var(--ff-b);font-size:.86rem;color:var(--ink);background:var(--cream);border:1px solid var(--border-g);border-radius:8px;padding:8px 12px;outline:none;transition:border-color .18s, box-shadow .18s;width:100%;-webkit-appearance:none}
.pc-input:focus{border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,169,110,.12)}
.pc-input::placeholder{color:var(--ink-faint)}
.pc-input--ro{background:var(--cream-d);color:var(--green-mid);cursor:default}
.pc-textarea{resize:vertical;min-height:68px;line-height:1.45;padding:10px 12px;font-family:var(--ff-b)}
.pc-row-1{grid-template-columns:1fr}
.pc-freeform-row{margin-top:6px}
.pc-hint{font-family:var(--ff-b);font-size:.68rem;color:var(--ink-faint);margin-top:2px;line-height:1.35}
.pc-guest-row{display:grid;grid-template-columns:1fr 14px 1fr;align-items:center;gap:4px}
.pc-guest-sep{text-align:center;color:var(--ink-faint);font-size:.8rem}
.pc-pills-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.pc-pills-lbl{font-family:var(--ff-m);font-size:.54rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-faint);white-space:nowrap;flex-shrink:0;min-width:72px}
.pc-pills{display:flex;flex-wrap:wrap;gap:6px}
.pc-pill{position:relative}
.pc-pill input{position:absolute;opacity:0;width:0;height:0}
.pc-pill label{display:inline-flex;align-items:center;padding:5px 13px;border:1px solid var(--border-g);border-radius:40px;font-family:var(--ff-b);font-size:.78rem;color:var(--ink-mid);cursor:pointer;transition:all .15s;background:white;user-select:none;white-space:nowrap}
.pc-pill label:hover{border-color:var(--green);color:var(--green)}
.pc-pill input:checked+label{background:var(--green);border-color:var(--green);color:white}
.pc-footer{padding:.9rem 1.75rem 1.25rem;border-top:1px solid var(--border);display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.pc-apply-btn{display:inline-flex;align-items:center;gap:8px;background:var(--green);color:white;border:none;border-radius:40px;font-family:var(--ff-b);font-size:.83rem;font-weight:500;padding:10px 20px;cursor:pointer;transition:all .2s;box-shadow:0 3px 14px rgba(44,74,62,.2)}
.pc-apply-btn:hover{background:var(--green-mid);transform:translateY(-1px)}
.pc-apply-btn:disabled{opacity:.55;cursor:not-allowed;transform:none;box-shadow:none}
.pc-spinner{width:11px;height:11px;border-radius:50%;border:1.5px solid rgba(255,255,255,.3);border-top-color:white;animation:pcSpin .65s linear infinite;flex-shrink:0}
@keyframes pcSpin{to{transform:rotate(360deg)}}
.pc-status{font-size:.76rem;color:var(--ink-faint);font-style:italic}
.pc-status.ok{color:var(--green-mid);font-style:normal}
@keyframes slFlash{0%{box-shadow:0 0 0 5px rgba(200,169,110,.45)}100%{box-shadow:none}}
.sl-flash{animation:slFlash .9s ease both;border-radius:2px}

.ai-tools-section{max-width:900px;margin:0 auto 3rem;padding:0 2rem}
.ai-tools-header{margin-bottom:1.5rem;padding-bottom:1rem;border-bottom:1px solid var(--border-g)}
.ai-tools-title{font-family:var(--ff-d);font-size:clamp(1.4rem,3vw,2rem);font-weight:400;color:var(--green);line-height:1.1}
.ai-tools-title em{font-style:italic;color:var(--gold)}
.ai-tools-subtitle{font-size:.85rem;color:var(--text-muted);margin-top:6px}
.ai-tool-tabs{display:flex;gap:6px;margin-bottom:1.5rem;flex-wrap:wrap}
.ai-tab-btn{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:8px 18px;border-radius:40px;border:1px solid var(--border-g);background:white;color:var(--ink-mid);cursor:pointer;transition:all .18s;white-space:nowrap}
.ai-tab-btn:hover{border-color:var(--green);color:var(--green)}
.ai-tab-btn.active{background:var(--green);border-color:var(--green);color:white}
.ai-tool-panel{display:none;background:var(--white);border:1px solid var(--border-g);border-radius:var(--radius-lg);padding:28px 32px;box-shadow:0 2px 16px rgba(44,74,62,.04)}
.ai-tool-panel.active{display:block}
.ai-tool-panel h3{font-family:var(--ff-d);font-size:1.4rem;font-weight:400;color:var(--green);margin-bottom:4px}
.ai-tool-panel h3 em{font-style:italic;color:var(--gold)}
.ai-tool-panel .tool-desc{font-size:.84rem;color:var(--text-muted);margin-bottom:20px;line-height:1.55}
.ai-field-row{display:grid;gap:14px;margin-bottom:16px}
.ai-field-row-2{grid-template-columns:1fr 1fr}
.ai-field-row-3{grid-template-columns:1fr 1fr 1fr}
.ai-field{display:flex;flex-direction:column;gap:5px}
.ai-lbl{font-family:var(--ff-m);font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:var(--green-mid)}
.ai-input,.ai-select,.ai-textarea{font-family:var(--ff-b);font-size:.86rem;color:var(--ink);background:var(--cream);border:1px solid var(--border-g);border-radius:8px;padding:9px 13px;outline:none;transition:border-color .18s,box-shadow .18s;width:100%}
.ai-input:focus,.ai-select:focus,.ai-textarea:focus{border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,169,110,.12)}
.ai-textarea{resize:vertical;min-height:90px;line-height:1.55}
.ai-btn{display:inline-flex;align-items:center;gap:8px;background:var(--green);color:white;border:none;border-radius:40px;font-family:var(--ff-b);font-size:.83rem;font-weight:500;padding:11px 22px;cursor:pointer;transition:all .2s;box-shadow:0 3px 14px rgba(44,74,62,.2);margin-top:4px}
.ai-btn:hover{background:var(--green-mid);transform:translateY(-1px)}
.ai-btn:disabled{opacity:.55;cursor:not-allowed;transform:none;box-shadow:none}
.ai-btn-ghost{background:transparent;color:var(--green);border:1px solid var(--border-g);box-shadow:none}
.ai-btn-ghost:hover{background:var(--green-pale);transform:none}
.ai-result-box{margin-top:20px;background:var(--cream);border:1px solid var(--border-g);border-radius:12px;overflow:hidden;display:none}
.ai-result-box.visible{display:block}
.ai-result-head{background:var(--green);color:white;padding:10px 18px;display:flex;align-items:center;justify-content:space-between;gap:10px}
.ai-result-head-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.6)}
.ai-result-head-actions{display:flex;gap:8px}
.ai-copy-btn{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;background:rgba(255,255,255,.12);color:white;border:1px solid rgba(255,255,255,.2);border-radius:6px;padding:4px 10px;cursor:pointer;transition:background .15s}
.ai-copy-btn:hover{background:rgba(255,255,255,.22)}
.ai-result-body{padding:18px 20px;font-size:.87rem;color:var(--ink-mid);line-height:1.7}
.ai-result-body h3{font-family:var(--ff-d);font-size:1.1rem;color:var(--green);margin:14px 0 4px}
.ai-result-body h3:first-child{margin-top:0}
.ai-result-body ul{margin:6px 0 12px 18px}
.ai-result-body li{margin-bottom:4px}
.ai-result-body strong{color:var(--ink);font-weight:600}
.ai-spinner{width:11px;height:11px;border-radius:50%;border:1.5px solid rgba(255,255,255,.3);border-top-color:white;animation:pcSpin .65s linear infinite;flex-shrink:0}
.ai-note{font-size:.76rem;color:var(--ink-faint);font-style:italic;margin-top:10px;padding:8px 12px;background:rgba(200,169,110,.06);border-radius:6px;border-left:2px solid var(--gold-lt)}

.quote-vendor-row{display:grid;gap:10px;margin-bottom:14px}
.quote-vendor-row-2{grid-template-columns:1fr 1fr}
.quote-add-btn{display:inline-flex;align-items:center;gap:6px;font-family:var(--ff-b);font-size:.8rem;color:var(--green);background:var(--green-pale);border:1px dashed rgba(44,74,62,.25);border-radius:8px;padding:7px 14px;cursor:pointer;transition:all .15s;margin-bottom:14px}
.quote-add-btn:hover{background:rgba(44,74,62,.1)}
.quote-vendor-block{background:var(--cream);border:1px solid var(--border-g);border-radius:10px;padding:14px 16px}
.quote-vendor-block .vendor-num{font-family:var(--ff-m);font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:8px}

#section-timeline{padding-bottom:80px}
.timeline-ai-wrap{max-width:720px;margin:0 auto;padding:0 2rem}
.timeline-ai-hero{padding:3.5rem 0 2rem}
.timeline-ai-hero h1{font-family:var(--ff-d);font-size:clamp(2rem,5vw,3rem);font-weight:400;line-height:1.05;color:var(--green);margin-bottom:.75rem}
.timeline-ai-hero h1 em{font-style:italic;color:var(--gold)}
.timeline-ai-hero p{font-size:.88rem;color:var(--text-muted);line-height:1.6;max-width:560px}
.tl-form-card{background:var(--white);border:1px solid var(--border-g);border-radius:var(--radius-lg);padding:28px 32px;margin-bottom:20px;box-shadow:0 2px 16px rgba(44,74,62,.04)}
.tl-form-card .eyebrow{display:block;margin-bottom:8px}
.tl-section-title{font-family:var(--ff-d);font-size:1.2rem;font-weight:400;color:var(--green);margin-bottom:16px}
.tl-section-title em{font-style:italic;color:var(--gold)}
.tl-vendors-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:16px}
.tl-vendor-check{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--cream);border:1px solid var(--border-g);border-radius:8px;cursor:pointer;transition:all .15s}
.tl-vendor-check:hover{border-color:var(--green)}
.tl-vendor-check input[type=checkbox]{accent-color:var(--green);width:14px;height:14px;flex-shrink:0}
.tl-vendor-check label{font-size:.84rem;color:var(--ink-mid);cursor:pointer;line-height:1.2}
.tl-generate-btn{display:flex;align-items:center;gap:10px;background:var(--green);color:white;border:none;border-radius:40px;font-family:var(--ff-b);font-size:.9rem;font-weight:500;padding:14px 28px;cursor:pointer;transition:all .2s;box-shadow:0 4px 18px rgba(44,74,62,.25);width:100%;justify-content:center;margin-top:4px}
.tl-generate-btn:hover{background:var(--green-mid);transform:translateY(-1px)}
.tl-generate-btn:disabled{opacity:.55;cursor:not-allowed;transform:none}
.tl-result{margin-top:24px;display:none}
.tl-result.visible{display:block}
.tl-result-header{background:var(--green);border-radius:14px 14px 0 0;padding:18px 24px;display:flex;align-items:center;justify-content:space-between}
.tl-result-title{font-family:var(--ff-d);font-size:1.3rem;font-weight:400;color:white}
.tl-result-title em{font-style:italic;color:var(--gold-lt)}
.tl-result-meta{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.5)}
.tl-result-body{background:var(--white);border:1px solid var(--border-g);border-top:none;border-radius:0 0 14px 14px;padding:0}
.tl-event-row{display:grid;grid-template-columns:80px 1fr;gap:0;border-bottom:1px solid var(--border);transition:background .15s}
.tl-event-row:last-child{border-bottom:none}
.tl-event-row:hover{background:var(--warm)}
.tl-event-time{padding:14px 16px;font-family:var(--ff-m);font-size:.72rem;color:var(--gold-deep);letter-spacing:.04em;border-right:1px solid var(--border-g);display:flex;align-items:flex-start;padding-top:16px;background:rgba(200,169,110,.04)}
.tl-event-content{padding:12px 18px}
.tl-event-title{font-size:.9rem;font-weight:500;color:var(--ink);margin-bottom:2px}
.tl-event-note{font-size:.78rem;color:var(--text-muted);line-height:1.45}
.tl-event-tag{display:inline-block;font-family:var(--ff-m);font-size:.52rem;letter-spacing:.08em;text-transform:uppercase;padding:2px 6px;border-radius:4px;margin-bottom:4px}
.tl-tag-ceremony{background:rgba(123,94,168,.1);color:var(--plum)}
.tl-tag-photos{background:rgba(90,140,122,.1);color:var(--green-mid)}
.tl-tag-reception{background:rgba(200,169,110,.12);color:var(--gold-deep)}
.tl-tag-logistics{background:rgba(28,28,28,.06);color:var(--ink-faint)}
.tl-download-row{display:flex;gap:10px;margin-top:16px;flex-wrap:wrap}
.tl-save-btn{display:inline-flex;align-items:center;gap:7px;background:white;color:var(--green);border:1px solid var(--border-g);border-radius:40px;font-family:var(--ff-b);font-size:.8rem;font-weight:500;padding:9px 18px;cursor:pointer;transition:all .18s}
.tl-save-btn:hover{background:var(--green-pale);border-color:var(--green)}
.tl-disclaimer{font-size:.75rem;color:var(--ink-faint);margin-top:14px;padding:10px 14px;background:rgba(200,169,110,.05);border:1px solid var(--border-g);border-radius:8px;line-height:1.55}

.compare-upload-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
.compare-upload-box{background:var(--cream);border:2px dashed var(--border-g);border-radius:10px;padding:18px;text-align:center;cursor:pointer;transition:all .18s;position:relative}
.compare-upload-box:hover{border-color:var(--green);background:var(--green-pale)}
.compare-upload-box.has-file{border-style:solid;border-color:rgba(44,74,62,.25);background:var(--green-pale)}
.compare-upload-box input[type=file]{position:absolute;inset:0;opacity:0;cursor:pointer;width:100%;height:100%}
.compare-upload-label{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--green-mid);display:block;margin-bottom:4px}
.compare-upload-name{font-size:.8rem;color:var(--ink-mid);margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

@media print{
 body>*:not(#print-area){display:none!important}
 #print-area{display:block!important;font-family:'DM Sans',sans-serif;background:#FAF7F2;color:#1C1C1C;max-width:100%;padding:0;margin:0}
 @page{margin:16mm}
}

/* 2026-05-04: page-title + vx-gap-headline + vx-advisor-note removed from
   the body-width groups below. Hero strips clamp to 820px (matching
   Insights .ss-wrap) per their own rules; body containers stay 960/900
   so operational tools have room. */
@media(min-width:1280px){
 .bridge,.profile-card,.budget-intro,.timeline-wrap,.tool-grid{max-width:960px}
 .tool-grid{padding-left:2rem;padding-right:2rem}
 .upload-wrapper,#results{max-width:720px}
}

@media(min-width:1024px) and (max-width:1279px){
 .bridge,.profile-card,.budget-intro,.timeline-wrap,.tool-grid{max-width:900px}
 .tool-grid{padding-left:2rem;padding-right:2rem}
 .guides-grid{grid-template-columns:repeat(3,1fr)}
}

@media(max-width:900px){
 .tool-grid{grid-template-columns:1fr;padding:1.5rem 2rem 60px}
 .sidebar{order:-1;position:static;max-height:none;overflow:visible}
 .sb-breakdown{display:none}
 .sidebar-actions{display:none}
 .sb-card{padding:16px 20px;margin-bottom:0;display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}
 .sb-card-left{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
 .sb-total{font-size:1.9rem;margin-bottom:0}
 .sb-label{margin-bottom:0}
 .sb-bar-wrap{display:none}
 .sb-card-rows{display:flex;gap:0 18px;align-items:center;flex-wrap:wrap}
 .sb-card-rows .sb-row{margin-top:0!important;padding-top:0!important;border-top:none!important;white-space:nowrap}
 .sb-card-rows .sb-row:last-child{border-left:1px solid rgba(255,255,255,.15);padding-left:18px}
 .mobile-actions{display:flex;flex-wrap:wrap}
 .readiness-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
 .range-labels span{font-size:.58rem}
 .guides-grid{grid-template-columns:repeat(2,1fr)}
 .guide-link{min-height:44px}
 .pt-sub{max-width:620px}
}

@media(max-width:768px){
 /* 2026-05-20 — Mobile header overrides must preserve safe-area
    handling. The plain `padding:13px 20px` was clobbering the
    base rule's env(safe-area-inset-top) value, causing the SPA's
    "verdeaux" logo + avatar to bleed into the iOS Dynamic Island.
    Stephen's iOS Safari test surfaced this — the landing page was
    fixed yesterday; the SPA chrome had the same shape of bug
    because its mobile breakpoints didn't replicate the safe-area
    math. */
 header{
   padding: max(13px, calc(env(safe-area-inset-top, 0px) + 10px))
            max(20px, env(safe-area-inset-right, 20px))
            13px
            max(20px, env(safe-area-inset-left, 20px));
 }
 .logo{font-size:1.25rem}
 .bridge{padding:5.5rem 1.25rem 0}
 .step-bar{grid-template-columns:1fr auto 1fr auto 1fr auto 1fr auto 1fr}
 .step-divider{width:1px;height:auto}
 .step-node{padding:.7rem .9rem;gap:8px;min-height:52px}
 .sn-name{font-size:.82rem}
 .sn-num{width:24px;height:24px}
 .handoff{border-radius:0 0 12px 12px;padding:.7rem 1rem;gap:8px;flex-wrap:wrap}
 .handoff-label{font-size:.5rem}
 .h-pill{font-size:.68rem;padding:2px 7px}

 .profile-card{padding:0 1.25rem;margin-top:1rem}
 .pc-form-head,.pc-body,.pc-footer{padding-left:1.25rem;padding-right:1.25rem}
 .pc-form-title{font-size:1.15rem}
 .pc-form-sub{font-size:.72rem}
 .pc-eyebrow{font-size:.5rem}
 .pc-row-3{grid-template-columns:1fr 1fr}
 .pc-row-3 .pc-field:first-child{grid-column:1/-1}
 .pc-pills-lbl{min-width:56px}
 .pc-input{min-height:44px;padding:10px 12px}
 .pc-applied{padding:.75rem 1.25rem;gap:10px}
 .pc-applied-summary{font-size:.8rem}
 .pc-edit-btn{font-size:.52rem;padding:3px 10px}

 .budget-intro{padding:0 1.25rem;margin-top:1.25rem}
 .budget-intro-meta{gap:10px}

 .tool-grid{padding:1.25rem 1.25rem 60px}
 .calc-section,#vendor-readiness{padding:22px 20px}
 .section-desc{font-size:.84rem;margin-bottom:20px}
 .group-head{margin:22px 0 10px;padding-top:18px}
 .callout-box{font-size:.82rem;padding:10px 14px}
 .day-btns{flex-wrap:wrap;gap:6px}
 .day-btn{min-height:44px}
 .range-labels span{font-size:.56rem}
 .vrow-hint{font-size:.76rem}
 .review-btn-row{flex-direction:column;gap:8px}
 #btn-pdf{width:100%;justify-content:center;min-height:44px}
 .action-btn{min-height:44px}
 .toggle-row{padding:10px 0;min-height:44px}
 .readiness-grid{grid-template-columns:repeat(3,1fr)}

 .page-title{padding:1rem 1.25rem 1.25rem;display:block}
 .pt-heading{font-size:clamp(1.4rem,4vw,1.9rem)}
 .pt-sub{font-size:.8rem;margin-top:8px;line-height:1.65;max-width:100%}
 .pt-count{display:none}
 .timeline-wrap{padding:0 1.25rem 3rem}
 .phase-band{flex-direction:column;align-items:flex-start;gap:.3rem;padding:.85rem 1.25rem}
 .band-right{text-align:left}
 .phase-body{padding:.75rem 1.1rem .9rem}
 .guides-grid{grid-template-columns:repeat(2,1fr);gap:.35rem}
 .guide-link{padding:.5rem .65rem;min-height:44px;gap:8px}
 .guide-name{font-size:.78rem}
 .guide-budgeted{width:17px;height:17px}
 .guide-partial{height:17px;font-size:.48rem}
 .guide-skipped{font-size:.54rem}

 #section-reviews .hero{padding:1rem 1.25rem 1.25rem}
 #section-reviews .hero h1{font-size:clamp(2rem,7vw,2.8rem)}
 .privacy-strip{gap:12px;padding:9px 14px;font-size:.68rem;flex-wrap:wrap;justify-content:center}
 .upload-wrapper{padding:0 1.25rem}
 .disclaimer-box{padding:18px 20px}
 .upload-zone{padding:2rem 1.25rem}
 .btn-analyze{min-height:44px;width:100%;justify-content:center}
 /* 2026-07-28 — the unified action row stacks full-width on mobile so the
    three controls wrap gracefully (separators hidden). */
 .vx-cr-actionbar{flex-direction:column;align-items:stretch;width:100%;gap:8px}
 .vx-cr-actionbar .btn-analyze{width:100%}
 .vx-cr-ab-btn{width:100%;min-height:44px;justify-content:center}
 .vx-cr-ab-sep{display:none}
 .file-selected{flex-direction:column;align-items:stretch;gap:10px}
 #results{padding:0 1.25rem;margin-bottom:4rem}
 .summary-bar{grid-template-columns:repeat(2,1fr)}
 .summary-cell{padding:1rem}
 .gauge-section{flex-direction:column;align-items:center;padding:1.25rem;gap:.4rem}
 .gauge-wrap{margin:0 auto}
 .gauge-info h3{font-size:1.2rem}
 .fee-table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
 .fee-table{min-width:480px}
 .site-footer{padding:1.25rem 1rem 1.5rem}
 .data-note{padding:10px 20px}
}

@media(max-width:640px){
 .tool-grid{padding:1rem 1rem 60px;gap:14px}
 .calc-section,#vendor-readiness{padding:18px 15px;border-radius:14px}
 .section-h2{font-size:1.45rem!important}
 .section-desc{font-size:.82rem;margin-bottom:18px}
 .eyebrow{font-size:.65rem;margin-bottom:4px}
 .group-name{font-size:1.05rem}
 .callout-box{font-size:.8rem;padding:9px 12px;gap:8px}
 .tag{font-size:.56rem;padding:1px 6px}
 .range-labels span{font-size:.54rem}
 .vrow-hint{font-size:.74rem}
 .vrow-name{font-size:.86rem}
 .vr-title{font-size:1.5rem}
 .group-head{margin:22px 0 10px;padding-top:18px}
 .sb-card{padding:14px 16px;gap:10px}
 .sb-total{font-size:1.7rem}
 .readiness-grid{grid-template-columns:repeat(3,1fr)}
 .step-node--done .sn-name,.step-node--next .sn-name{display:none}
 .step-node--current .sn-name{display:block;font-size:.78rem}
 .step-node{padding:.65rem .75rem;gap:6px;min-height:48px}
 .sn-num{width:22px;height:22px}
 .page-title{padding:1rem 1rem 1rem}
 .pt-heading{font-size:clamp(1.3rem,5vw,1.65rem)}
 .pt-sub{font-size:.78rem;line-height:1.6}
 .timeline-wrap{padding:0 1rem 2.5rem}
 .phase-card{border-radius:12px}
 .phase-band{padding:.7rem 1rem;gap:.25rem}
 .phase-title{font-size:1rem}
 .band-time{font-size:.9rem}
 .phase-body{padding:.65rem .9rem .8rem}
 .guides-grid{grid-template-columns:1fr;gap:.3rem}
 .guide-link{padding:.55rem .75rem;min-height:44px;gap:8px}
 .guide-name{font-size:.8rem}
 .guide-budgeted{width:16px;height:16px;font-size:.52rem;border-radius:3px}
 .guide-partial{height:16px;font-size:.46rem;border-radius:3px}
 .guide-skipped{font-size:.52rem}
}

@media(max-width:480px){
 /* 2026-05-20 — Same safe-area preservation as the ≤768px rule above.
    Tighter base padding (10px vs 13px) because phones are space-tight,
    but the env(safe-area-inset-top) floor still wins on notched
    devices so the chrome never bleeds behind the Dynamic Island. */
 header{
   padding: max(10px, calc(env(safe-area-inset-top, 0px) + 8px))
            max(15px, env(safe-area-inset-right, 15px))
            10px
            max(15px, env(safe-area-inset-left, 15px));
 }
 .header-pill{font-size:.56rem;padding:4px 10px}
 .bridge{padding-top:5rem;padding-left:1rem;padding-right:1rem}
 .sn-name{display:none!important}
 .sn-num{width:26px;height:26px;font-size:.62rem}
 .step-node{justify-content:center;padding:.65rem .5rem;min-height:44px}
 .handoff{padding:.6rem 1rem;flex-wrap:wrap}
 .h-pill{font-size:.64rem}

 .profile-card{padding:0 1rem;margin-top:1rem}
 .pc-form-head,.pc-body,.pc-footer{padding-left:1rem;padding-right:1rem}
 .pc-form-title{font-size:1.05rem}
 .pc-form-sub{font-size:.68rem}
 .pc-eyebrow{display:none}
 .pc-row-2,.pc-row-3{grid-template-columns:1fr}
 .pc-row-3 .pc-field:first-child{grid-column:unset}
 .pc-pills-row{flex-direction:column;align-items:flex-start;gap:7px}
 .pc-pills-lbl{min-width:unset;width:100%}
 .pc-apply-btn{width:100%;justify-content:center;min-height:44px}
 .pc-input{min-height:44px}
 .pc-guest-sep{font-size:.7rem}
 .pc-applied{padding:.65rem 1rem;gap:8px;flex-wrap:wrap}
 .pc-applied-summary{font-size:.74rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
 .pc-edit-btn{flex-shrink:0;font-size:.5rem;padding:3px 9px}

 .budget-intro{flex-direction:column;gap:.4rem;padding:0 1rem;margin-top:1rem}
 .budget-intro-meta{gap:8px}
 .budget-intro-sep{height:16px}
 .budget-intro-heading{font-size:1.3rem}

 .tool-grid{padding:.75rem .75rem 60px;gap:12px}
 .calc-section,#vendor-readiness{padding:16px 14px;border-radius:12px}
 .section-desc{font-size:.8rem;margin-bottom:16px}
 .eyebrow{font-size:.62rem}
 .group-name{font-size:1rem}
 .callout-box{font-size:.76rem;padding:8px 12px}
 .tag{font-size:.54rem;padding:1px 5px}
 .range-labels span{font-size:.52rem}
 .vrow{gap:0 10px}
 .vrow-amt{font-size:1.05rem;min-width:5ch}
 .vrow-name{font-size:.84rem}
 .vrow-hint{font-size:.72rem;line-height:1.45}
 .day-btns{gap:6px}
 .day-btn{font-size:.78rem;padding:7px 12px;min-height:44px}
 .budget-field{max-width:100%}
 .budget-field input{font-size:1.1rem}
 #btn-pdf{min-height:44px}
 .pdf-btn-label{display:none}
 .readiness-grid{grid-template-columns:repeat(2,1fr)}
 input[type=range]::-webkit-slider-thumb{width:22px;height:22px}
 .toggle-row{min-height:44px;padding:10px 0}
 .sw{width:36px;height:22px}
 .sw-track::after{width:18px;height:18px}
 .action-btn{min-height:44px}

 .page-title{padding:1rem .75rem .9rem}
 .pt-heading{font-size:clamp(1.2rem,5.5vw,1.5rem)}
 .pt-sub{font-size:.76rem;margin-top:6px}
 .timeline-wrap{padding:0 .75rem 2rem}
 .phase-band{padding:.65rem .85rem}
 .phase-title{font-size:.95rem}
 .band-time{font-size:.85rem}
 .phase-body{padding:.55rem .8rem .7rem}
 .guide-link{padding:.5rem .7rem;gap:7px}
 .guide-name{font-size:.76rem}
 .guide-budgeted{width:15px;height:15px;font-size:.5rem}
 .guide-partial{height:15px;font-size:.44rem}

 #section-reviews .hero{padding:1rem 1rem 1rem}
 #section-reviews .hero h1{font-size:clamp(1.75rem,8vw,2.4rem);margin-bottom:1rem}
 #section-reviews .hero p{font-size:.88rem;margin-bottom:1.75rem}
 .privacy-strip{font-size:.64rem;gap:8px;padding:8px 12px}
 .privacy-strip .dot{display:none}
 .upload-wrapper{padding:0 1rem}
 .disclaimer-box{padding:14px 16px}
 .disclaimer-box p{font-size:.78rem}
 .disclaimer-check label{font-size:.75rem}
 .upload-zone{padding:1.75rem 1rem}
 .upload-zone h3{font-size:1.1rem}
 .summary-bar{grid-template-columns:repeat(2,1fr)}
 .summary-cell{padding:.85rem .6rem}
 .summary-cell .label{font-size:.58rem}
 .summary-cell .value{font-size:1.5rem}
 .gauge-section{padding:1rem}
 .fee-table{min-width:420px;font-size:.78rem}
 .fee-table th{font-size:.55rem;padding:.65rem .9rem}
 .fee-table td{padding:.75rem .9rem}
 .section-header h2{font-size:1.35rem}
 .rec-item{padding:.85rem 1rem;font-size:.8rem}
}

@media(max-width:360px){
 .bridge{padding-left:.75rem;padding-right:.75rem}
 .profile-card,.budget-intro{padding-left:.75rem;padding-right:.75rem}
 .pc-form-head,.pc-body,.pc-footer{padding-left:.75rem;padding-right:.75rem}
 .pc-form-title{font-size:.98rem}
 .pc-form-sub{font-size:.64rem}
 .pc-pill label{font-size:.72rem;padding:4px 10px}
 .pc-applied{padding:.6rem .75rem;gap:7px}
 .pc-applied-summary{font-size:.7rem}
 .budget-intro-heading{font-size:1.15rem}
 .section-h2{font-size:1.25rem!important}
 .section-desc{font-size:.76rem;margin-bottom:14px}
 .eyebrow{font-size:.6rem;letter-spacing:.1em}
 .group-name{font-size:.95rem}
 .group-total{font-size:.7rem}
 .callout-box{font-size:.72rem;padding:7px 10px;gap:6px}
 .tag{font-size:.5rem;padding:1px 5px}
 .range-labels span{font-size:.5rem}
 .vrow-amt{font-size:.95rem;min-width:4.5ch}
 .vrow-name{font-size:.8rem}
 .vrow-hint{font-size:.68rem;line-height:1.45}
 .sb-card{padding:12px 14px}
 .sb-total{font-size:1.5rem}
 #btn-pdf{font-size:.72rem}
 .page-title{padding:1rem .75rem .75rem}
 .pt-heading{font-size:1.1rem}
 .pt-sub{font-size:.72rem;line-height:1.55}
 .timeline-wrap{padding:0 .5rem 1.75rem}
 .phase-band{padding:.6rem .75rem}
 .phase-title{font-size:.9rem}
 .phase-body{padding:.5rem .7rem .6rem}
 .guide-link{padding:.45rem .6rem;gap:6px;min-height:42px}
 .guide-name{font-size:.72rem}
 .guide-budgeted{width:14px;height:14px;font-size:.48rem;border-radius:3px}
 .guide-partial{height:14px;font-size:.42rem;border-radius:3px}
 .guide-skipped{font-size:.48rem}
}

.ai-tools-section{padding:0 clamp(1rem,4vw,3rem) 3rem}
.ai-tool-panel{padding:24px 28px}
.ai-field-row-2,.ai-field-row-3{gap:12px}

#combined-results-panel{margin:8px clamp(0px,1vw,0px)}

.timeline-ai-wrap{padding:0 clamp(1rem,4vw,2rem)}
.tl-form-card{padding:22px 24px}
.tl-vendors-grid{grid-template-columns:repeat(2,1fr)}

@media(max-width:900px){

 .ai-tools-section{padding:0 2rem 2.5rem}
 .ai-tool-panel{padding:20px 22px}
 .ai-field-row-3{grid-template-columns:1fr 1fr}
 .ai-field-row-3 .ai-field:last-child{grid-column:1/-1}
 .compare-upload-row{grid-template-columns:1fr 1fr}

 .review-btn-row{flex-wrap:wrap;gap:8px}

 .timeline-ai-wrap{padding:0 2rem}
 .tl-form-card{padding:20px 22px}
 .ai-field-row-3.tl-row{grid-template-columns:1fr 1fr}
 .tl-vendors-grid{grid-template-columns:repeat(2,1fr)}
}

@media(max-width:768px){

 .ai-tools-section{padding:0 1.25rem 2rem}
 .ai-tools-title{font-size:clamp(1.3rem,4vw,1.8rem)}
 .ai-tool-tabs{gap:5px}
 .ai-tab-btn{font-size:.58rem;padding:7px 14px}
 .ai-tool-panel{padding:18px 18px}
 .ai-tool-panel h3{font-size:1.2rem}
 .ai-tool-panel .tool-desc{font-size:.8rem;margin-bottom:16px}
 .ai-field-row-2{grid-template-columns:1fr}
 .ai-field-row-3{grid-template-columns:1fr}
 .ai-btn{width:100%;justify-content:center;min-height:44px}
 .ai-note{font-size:.72rem}
 .ai-result-body{font-size:.84rem;padding:14px 16px}

 .quote-vendor-block{padding:12px 14px}

 #combined-results-panel{border-radius:12px}
 .review-btn-row{flex-direction:column;gap:8px}
 #btn-pdf{width:100%;justify-content:center;min-height:44px}

 .timeline-ai-hero{padding:2.5rem 0 1.5rem}
 .timeline-ai-hero h1{font-size:clamp(1.8rem,6vw,2.6rem)}
 .timeline-ai-hero p{font-size:.85rem}
 .tl-form-card{padding:16px 18px;margin-bottom:14px}
 .tl-section-title{font-size:1.1rem;margin-bottom:12px}
 .ai-field-row-3{grid-template-columns:1fr 1fr}
 .tl-vendors-grid{grid-template-columns:repeat(2,1fr);gap:8px}
 .tl-vendor-check{padding:7px 10px}
 .tl-vendor-check label{font-size:.8rem}
 .tl-generate-btn{font-size:.85rem;padding:13px 22px;min-height:48px}
 .tl-event-row{grid-template-columns:70px 1fr}
 .tl-event-time{font-size:.68rem;padding:12px 10px}
 .tl-event-content{padding:10px 14px}
 .tl-event-title{font-size:.86rem}
 .tl-event-note{font-size:.75rem}
 .tl-result-header{padding:14px 18px}
 .tl-result-title{font-size:1.1rem}
 .tl-download-row{flex-direction:column;gap:8px}
 .tl-save-btn{justify-content:center;min-height:44px}
}

@media(max-width:640px){

 .ai-tools-section{padding:0 1rem 1.75rem}
 .ai-tool-tabs{flex-wrap:wrap}
 .ai-tab-btn{font-size:.56rem;padding:6px 12px}
 .ai-tool-panel{padding:15px 15px;border-radius:14px}
 .ai-tool-panel h3{font-size:1.1rem;margin-bottom:3px}
 .ai-tool-panel .tool-desc{font-size:.78rem;margin-bottom:14px}
 .ai-input,.ai-select,.ai-textarea{font-size:.84rem;padding:8px 11px}
 .ai-lbl{font-size:.52rem}
 .ai-textarea{min-height:80px}

 .quote-vendor-block{padding:10px 12px}
 .quote-vendor-block .vendor-num{font-size:.52rem;margin-bottom:6px}

 #combined-results-panel{border-radius:10px}
 #combined-results-panel .analysis-body,
 #combined-results-panel .ai-result-body{padding:14px 16px;font-size:.84rem}

 .timeline-ai-wrap{padding:0 1rem}
 .timeline-ai-hero{padding:2rem 0 1.25rem}
 .timeline-ai-hero h1{font-size:clamp(1.6rem,7vw,2.2rem);margin-bottom:.5rem}
 .tl-form-card{padding:14px 14px;border-radius:14px;margin-bottom:10px}
 .tl-form-card .eyebrow{font-size:.62rem;margin-bottom:6px}
 .ai-field-row-3{grid-template-columns:1fr}
 .tl-vendors-grid{grid-template-columns:repeat(2,1fr);gap:6px}
 .tl-vendor-check{padding:6px 9px}
 .tl-vendor-check label{font-size:.76rem}
 .tl-generate-btn{font-size:.82rem;padding:12px 18px;min-height:46px;gap:8px}
 .tl-result-header{padding:12px 14px;flex-direction:column;align-items:flex-start;gap:4px}
 .tl-result-meta{font-size:.54rem}
 .tl-event-row{grid-template-columns:62px 1fr}
 .tl-event-time{font-size:.64rem;padding:10px 8px}
 .tl-event-content{padding:9px 12px}
 .tl-event-title{font-size:.84rem}
 .tl-event-note{font-size:.72rem}
 .tl-event-tag{font-size:.48rem;padding:1px 5px}
 .tl-disclaimer{font-size:.7rem}
}

@media(max-width:480px){

 .ai-tools-section{padding:0 .85rem 1.5rem}
 .ai-tools-subtitle{font-size:.76rem}
 .ai-tab-btn{font-size:.54rem;padding:5px 10px}
 .ai-tool-panel{padding:13px 13px}
 .ai-tool-panel h3{font-size:1rem}
 .ai-tool-panel .tool-desc{font-size:.76rem}
 .ai-input,.ai-select{min-height:44px}
 .quote-add-btn{font-size:.76rem;padding:6px 12px}

 #combined-results-panel .analysis-body,
 #combined-results-panel .ai-result-body{padding:12px 13px;font-size:.82rem}

 .timeline-ai-wrap{padding:0 .85rem}
 .tl-vendors-grid{grid-template-columns:1fr 1fr;gap:5px}
 .tl-vendor-check label{font-size:.73rem}
 .tl-event-row{grid-template-columns:58px 1fr}
 .tl-event-time{font-size:.6rem;padding:9px 7px}
 .tl-event-title{font-size:.82rem}
 .tl-event-note{font-size:.7rem}
}

@media(max-width:360px){
 .ai-tools-section{padding:0 .75rem 1.25rem}
 .ai-tab-btn{font-size:.52rem;padding:5px 9px}
 .ai-tool-panel{padding:12px 12px}
 .tl-vendors-grid{grid-template-columns:1fr}
 .tl-event-row{grid-template-columns:54px 1fr}
 .tl-generate-btn{font-size:.78rem}
}

.ss-wrap{max-width:820px;margin:0 auto;padding:0 clamp(1rem,4vw,2rem) 80px}
.ss-hero{padding:1rem 0 2rem}
.ss-hero-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:.5rem}
.ss-hero h1{font-family:var(--ff-d);font-size:clamp(2rem,5vw,3rem);font-weight:400;color:var(--green);line-height:1.05;margin-bottom:.75rem}
.ss-hero h1 em{font-style:italic;color:var(--gold)}
.ss-hero p{font-size:.88rem;color:var(--text-muted);line-height:1.65;max-width:580px}
.ss-hero-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:1.25rem}
.ss-hero-btn{display:inline-flex;align-items:center;gap:8px;background:var(--green);color:#fff;border:none;border-radius:40px;font-family:var(--ff-b);font-size:.82rem;font-weight:500;padding:11px 22px;cursor:pointer;transition:all .18s;box-shadow:0 2px 12px rgba(44,74,62,.18)}
.ss-hero-btn:hover{background:var(--green-mid);transform:translateY(-1px)}
.ss-hero-btn:disabled{opacity:.55;cursor:not-allowed;transform:none}
.ss-hero-btn-outline{background:transparent;color:var(--green);border:1px solid rgba(44,74,62,.28);box-shadow:none}
.ss-hero-btn-outline:hover{background:var(--green-pale);border-color:var(--green);color:var(--green)}
.ss-hero-btn .ai-spark{font-size:.95rem;line-height:1;display:inline-block;color:inherit}
.ss-vendor-panel{background:var(--white);border:1px solid var(--border-g);border-radius:var(--radius-lg);overflow:hidden;margin-bottom:20px;box-shadow:0 2px 16px rgba(44,74,62,.04)}
.ss-panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:20px 24px 16px;border-bottom:1px solid var(--border-g);flex-wrap:wrap}
.ss-panel-title{font-family:var(--ff-d);font-size:1.2rem;font-weight:400;color:var(--green);margin-bottom:2px}
.ss-panel-sub{font-size:.78rem;color:var(--text-muted);line-height:1.45}
.ss-add-btn{display:inline-flex;align-items:center;gap:7px;background:var(--green);color:white;border:none;border-radius:40px;font-family:var(--ff-b);font-size:.78rem;font-weight:500;padding:9px 18px;cursor:pointer;transition:all .18s;white-space:nowrap;flex-shrink:0}
.ss-add-btn:hover{background:var(--green-mid);transform:translateY(-1px)}
.ss-vendor-row{display:grid;grid-template-columns:28px 1fr 28px;gap:0 12px;align-items:start;padding:14px 20px;border-bottom:1px solid var(--border);transition:background .15s,opacity .15s}
.ss-vendor-row:last-child{border-bottom:none}
.ss-vendor-row:hover{background:rgba(200,169,110,.03)}
.ss-vendor-row.is-complete{background:rgba(44,74,62,.04);opacity:.72}
.ss-vendor-row.is-complete:hover{opacity:.88}
.ss-vrow-num{font-family:var(--ff-m);font-size:.6rem;color:var(--gold-deep);padding-top:28px;text-align:center}
.ss-vrow-fields{display:grid;grid-template-columns:1.3fr 1fr 100px 100px 130px 80px;gap:10px}
.ssv-complete-field{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.ssv-complete-field .sw{margin-top:4px}
.ss-remove-btn{background:transparent;border:none;color:var(--ink-faint);cursor:pointer;padding:4px;border-radius:4px;transition:all .15s;margin-top:24px}
.ss-remove-btn:hover{color:var(--danger);background:rgba(185,64,64,.07)}
.ss-context-row{display:grid;grid-template-columns:160px 160px 1fr;gap:14px;margin-bottom:20px;background:var(--white);border:1px solid var(--border-g);border-radius:var(--radius);padding:16px 20px}
.ss-generate-btn{display:flex;align-items:center;gap:10px;background:var(--green);color:white;border:none;border-radius:40px;font-family:var(--ff-b);font-size:.9rem;font-weight:500;padding:14px 28px;cursor:pointer;transition:all .2s;box-shadow:0 4px 18px rgba(44,74,62,.25);justify-content:center;width:100%;margin-bottom:4px}
.ss-generate-btn:hover{background:var(--green-mid);transform:translateY(-1px)}
.ss-generate-btn:disabled{opacity:.55;cursor:not-allowed;transform:none}
.ss-scorecard-row{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--border-g);border:1px solid var(--border-g);border-radius:14px;overflow:hidden;margin-bottom:20px}
.ss-scorecard{background:var(--white);padding:16px 20px}
.ss-sc-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px}
.ss-sc-value{font-family:var(--ff-d);font-size:1.6rem;font-weight:400;color:var(--ink);line-height:1;margin-bottom:4px}
.ss-sc-sub{font-size:.72rem;color:var(--text-muted)}
.ss-panels{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.ss-panel{border-radius:12px;overflow:hidden;border:1px solid var(--border-g)}
.ss-panel-header{display:flex;align-items:center;gap:9px;padding:11px 16px;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase}
.ss-panel-header span{flex:1}
.ss-panel-body{padding:16px 18px;font-size:.84rem;color:var(--ink-mid);line-height:1.72}
.ss-panel-green .ss-panel-header{background:var(--green);color:white}
.ss-panel-green .ss-panel-header svg{stroke:rgba(255,255,255,.7)}
.ss-panel-green .ai-copy-btn{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.2);color:white}
.ss-panel-gold .ss-panel-header{background:var(--warm);color:var(--gold-deep);border-bottom:1px solid var(--border-g)}
.ss-panel-gold .ss-panel-header svg{stroke:var(--gold-deep)}
.ss-panel-amber .ss-panel-header{background:rgba(201,123,58,.07);color:var(--amber-risk);border-bottom:1px solid rgba(201,123,58,.15)}
.ss-panel-amber .ss-panel-header svg{stroke:var(--amber-risk)}
.ss-panel-risk .ss-panel-header{background:rgba(185,64,64,.06);color:var(--danger);border-bottom:1px solid rgba(185,64,64,.15)}
.ss-panel-risk .ss-panel-header svg{stroke:var(--danger)}
.ss-verify-banner{display:flex;align-items:flex-start;gap:14px;padding:14px 18px;background:rgba(200,169,110,.07);border:1px solid rgba(200,169,110,.3);border-radius:10px;margin-bottom:20px}
.ss-verify-icon{flex-shrink:0;padding-top:1px}
.ss-verify-text{font-size:.83rem;color:var(--ink-mid);line-height:1.6}
.ss-verify-text strong{color:var(--ink);font-weight:600}
.ss-plan-launcher{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:18px 22px;background:var(--white);border:1px solid var(--border-g);border-radius:12px;margin-bottom:20px;flex-wrap:wrap;box-shadow:0 2px 16px rgba(44,74,62,.04)}
.ss-plan-copy{flex:1;min-width:240px}
.ss-plan-launcher .ih-pf-btn{flex-shrink:0}
.ss-plan-actions{display:flex;align-items:center;gap:8px;flex-shrink:0;flex-wrap:wrap}
.ss-refresh-btn{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.ss-refresh-icon{display:inline-block;font-size:1rem;line-height:1;transition:transform .5s ease}
.ss-refresh-btn:hover .ss-refresh-icon{transform:rotate(-180deg)}

.brief-ai-output.just-refreshed{animation:cl-flash .7s ease-out}
@keyframes cl-flash{0%{background:rgba(44,74,62,.14);border-radius:8px}100%{background:transparent}}

@media(max-width:900px){
 .ss-wrap{padding:0 2rem 60px}
 .ss-hero{padding:1rem 0 1.5rem}
 .ss-hero h1{font-size:clamp(1.8rem,5vw,2.6rem)}
 .ss-vrow-fields{grid-template-columns:1fr 1fr 1fr}
 .ss-context-row{grid-template-columns:1fr 1fr}
 .ss-context-row .ai-field:last-child{grid-column:1/-1}
 .ss-scorecard-row{grid-template-columns:repeat(2,1fr)}
 .ss-panels{grid-template-columns:1fr}
 .ss-verify-banner{padding:12px 16px;gap:12px}
 #batch-email-banner{flex-wrap:wrap}
 #batch-email-banner .ss-add-btn{flex-shrink:0}
}

@media(max-width:768px){
 .ss-wrap{padding:0 1.25rem 60px}
 .ss-hero{padding:1rem 0 1.25rem}
 .ss-hero p{font-size:.85rem}
 .ss-vendor-panel{border-radius:14px}
 .ss-panel-head{flex-direction:column;gap:10px;padding:16px 18px 14px}
 .ss-panel-title{font-size:1.1rem}
 .ss-panel-sub{font-size:.76rem}
 .ss-add-btn{width:100%;justify-content:center;min-height:44px}
 .ss-vendor-row{padding:12px 16px}
 .ss-vrow-fields{grid-template-columns:1fr 1fr}
 .ss-vrow-fields .ai-field:nth-child(5),.ss-vrow-fields .ai-field:nth-child(6){grid-column:1/-1}
 .ss-context-row{grid-template-columns:1fr;padding:14px 16px}
 .ss-context-row .ai-field:last-child{grid-column:unset}
 .ss-generate-btn{font-size:.85rem;padding:13px 22px;min-height:48px}
 .ss-scorecard-row{grid-template-columns:repeat(2,1fr);border-radius:10px}
 .ss-scorecard{padding:14px 16px}
 .ss-sc-value{font-size:1.35rem}
 .ss-panels{gap:10px}
 .ss-panel-header{padding:10px 14px;font-size:.58rem}
 .ss-panel-body{padding:14px 16px;font-size:.82rem}
 .ss-verify-banner{padding:11px 14px;gap:10px;border-radius:8px}
 .ss-verify-text{font-size:.8rem}
 #batch-email-banner{flex-wrap:wrap;gap:10px}
 #batch-email-banner .ss-add-btn{width:100%;justify-content:center}
}

@media(max-width:640px){
 .ss-wrap{padding:0 1rem 60px}
 .ss-hero{padding:1rem 0 1.25rem}
 .ss-hero h1{font-size:clamp(1.6rem,7vw,2.2rem);margin-bottom:.5rem}
 .ss-hero p{font-size:.82rem}
 .ss-hero-eyebrow{font-size:.58rem}
 .ss-hero-actions{flex-direction:column;align-items:stretch;gap:8px;margin-top:1rem}
 .ss-hero-btn{justify-content:center;min-height:44px;font-size:.78rem}
 .ss-vendor-row{grid-template-columns:20px 1fr 24px;padding:10px 12px;gap:0 8px}
 .ss-vrow-num{font-size:.56rem;padding-top:24px}
 .ss-vrow-fields{grid-template-columns:1fr 1fr;gap:8px}
 .ss-vrow-fields .ai-field:nth-child(3),.ss-vrow-fields .ai-field:nth-child(4),
 .ss-vrow-fields .ai-field:nth-child(5),.ss-vrow-fields .ai-field:nth-child(6){grid-column:1/-1}
 .ss-remove-btn{margin-top:20px}
 .ss-generate-btn{font-size:.82rem;padding:12px 18px}
 .ss-scorecard{padding:12px 13px}
 .ss-sc-value{font-size:1.25rem}
 .ss-sc-label{font-size:.55rem}
 .ss-sc-sub{font-size:.68rem}
 .ss-panel-header span{font-size:.56rem}
 .ss-panel-body{font-size:.8rem;padding:12px 14px}
 .ss-verify-banner{gap:9px;padding:10px 12px}
 .ss-verify-icon svg{width:14px;height:14px}
 .ss-verify-text{font-size:.78rem}
 #batch-email-results{border-radius:10px}
}

@media(max-width:480px){
 .ss-wrap{padding:0 .85rem 60px}
 .ss-vrow-fields{grid-template-columns:1fr}
 .ss-scorecard-row{grid-template-columns:1fr 1fr}
 .ss-scorecard{padding:10px 12px}
 .ss-sc-value{font-size:1.15rem}
 .ss-panels{gap:8px}
 .ss-panel-body{font-size:.78rem;line-height:1.65}
 .ss-verify-banner{flex-direction:column;gap:8px}
 .ss-verify-icon{display:none}
}

@media(max-width:360px){
 .ss-wrap{padding:0 .75rem 60px}
 .ss-hero h1{font-size:1.5rem}
 .ss-scorecard-row{grid-template-columns:1fr}
 .ss-generate-btn{font-size:.78rem}
 .ss-panel-header{gap:6px;padding:9px 11px}
 .ss-panel-body{padding:10px 12px;font-size:.76rem}
}

.ideas-dropdown{position:relative;display:flex;align-items:center;justify-content:center}
.ideas-btn{
 display:flex;align-items:center;justify-content:center;gap:0;
 padding:0 18px;min-height:38px;
 background:transparent;border:none;cursor:pointer;text-align:center;
 transition:color .18s;
 height:auto;width:auto;
}
.ideas-chevron{display:none}
.ideas-btn:hover{background:transparent}
.ideas-btn.is-open{background:transparent}
.ideas-btn.is-active{background:transparent}
.ideas-btn-icon{display:none}
.ideas-btn-text{display:flex;flex-direction:column}
.ideas-btn-name{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;font-weight:500;line-height:1;letter-spacing:.03em;color:var(--text-muted);display:flex;align-items:center;gap:0;white-space:nowrap}
.ideas-btn.is-active .ideas-btn-name,.ideas-btn.is-open .ideas-btn-name{color:var(--green);font-weight:600}
.ideas-chevron{transition:transform .2s;margin-top:2px}
.ideas-btn.is-open .ideas-chevron{transform:rotate(180deg)}

.ideas-bar{
 margin-top:10px;
 transition:all .2s;
}
.ideas-bar-inner{
 background:linear-gradient(180deg,var(--cream-d) 0%,var(--warm) 100%);
 border:1px solid var(--border-g);
 border-radius:12px;
 padding:8px 14px;
 box-shadow:0 1px 0 rgba(44,74,62,.02), 0 2px 8px rgba(44,74,62,.04);
 transition:background .2s,border-color .2s,padding .2s,box-shadow .2s;
}
.ideas-bar.collapsed .ideas-bar-inner{
 background:transparent;
 border-color:transparent;
 padding:2px 14px;
 box-shadow:none;
}

.ideas-bar-expanded{display:flex;flex-direction:column;gap:10px;min-height:36px}
.ideas-bar-expanded .ideas-bar-top{display:flex;align-items:center;gap:12px;min-height:36px;flex-wrap:wrap}
.ideas-bar-collapsed{display:none;align-items:center;gap:12px;min-height:36px}
.ideas-bar.collapsed .ideas-bar-expanded{display:none}
.ideas-bar.collapsed .ideas-bar-collapsed{display:flex}

/* Saved-preference chips inside the Ideas bar — auto-save on toggle */
.ideas-bar-prefs{display:flex;flex-direction:column;gap:6px;padding-top:4px;border-top:1px dashed rgba(44,74,62,.1)}
.ideas-bar-pref-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ideas-bar-pref-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);font-weight:500;min-width:70px;flex-shrink:0}
.vx-chips-bar{display:flex;flex-wrap:wrap;gap:5px;flex:1;min-width:0}
.vx-chips-bar button{appearance:none;background:transparent;border:1px solid var(--border-g);border-radius:999px;padding:4px 11px;font-family:var(--ff-b);font-size:.76rem;color:var(--text-mid);cursor:pointer;transition:all .15s;line-height:1.4}
.vx-chips-bar button:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-chips-bar button.is-on{background:var(--green);color:var(--white);border-color:var(--green)}
.ideas-bar-save-chip{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:#3d6a58;opacity:0;transition:opacity .3s;flex-shrink:0}
.ideas-bar-save-chip.is-visible{opacity:1}
.ideas-bar-save-chip[hidden]{display:none}
@media (max-width:767px){
 .ideas-bar-pref-row{gap:6px}
 .ideas-bar-pref-label{min-width:56px;font-size:.56rem}
 .vx-chips-bar button{font-size:.72rem;padding:4px 9px}
}

.ideas-bar-label{
 display:inline-flex;align-items:center;gap:6px;
 font-family:var(--ff-m);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;
 color:var(--gold-deep);font-weight:500;flex-shrink:0;white-space:nowrap;
}
.ideas-bar-label-star{color:var(--gold);font-size:.82rem;line-height:1}
.ideas-bar.collapsed .ideas-bar-label{color:var(--ink-faint)}
.ideas-bar.collapsed .ideas-bar-label-star{color:var(--gold);opacity:.6}

.ideas-bar-pills{
 display:flex;gap:6px;flex:1;flex-wrap:wrap;align-items:center;
}
.ideas-pill{
 display:inline-flex;align-items:center;gap:7px;
 padding:6px 13px;
 border-radius:20px;
 background:white;
 border:1px solid var(--border-g);
 font-family:var(--ff-b);font-size:.74rem;
 color:var(--ink-mid);
 cursor:pointer;
 transition:all .14s ease;
 white-space:nowrap;
 outline:none;
}
.ideas-pill:hover{
 background:var(--green-pale);
 border-color:var(--green-lt);
 color:var(--green);
 transform:translateY(-1px);
 box-shadow:0 2px 6px rgba(44,74,62,.08);
}
.ideas-pill:focus-visible{
 outline:2px solid var(--gold);
 outline-offset:2px;
}
.ideas-pill.is-active{
 background:var(--green);
 color:white;
 border-color:var(--green);
 font-weight:500;
 box-shadow:0 1px 0 rgba(0,0,0,.05), 0 2px 4px rgba(44,74,62,.12);
}
.ideas-pill.is-active:hover{
 background:var(--green-mid);
 transform:translateY(-1px);
 box-shadow:0 1px 0 rgba(0,0,0,.05), 0 3px 8px rgba(44,74,62,.18);
}
.ideas-pill-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;transition:transform .14s ease}
.ideas-pill:hover .ideas-pill-icon{transform:scale(1.08)}
/* 2026-05-24 — pill-reddit / pill-pinterest / pill-tiktok color rules
   retired with the IDEAS_PILL_DESCS dead code. No DOM elements with
   these classes exist; the social-platform pills were taken out of
   the Chat surface markup on 2026-04-29. */

.ideas-pill-info{
 display:inline-flex;align-items:center;justify-content:center;
 font-size:.72rem;line-height:1;
 color:inherit;
 margin-left:6px;opacity:.55;
 cursor:pointer;user-select:none;
 transition:opacity .15s,color .15s,transform .15s;
 border-radius:50%;padding:1px;
}
.ideas-pill:hover .ideas-pill-info,
.ideas-pill-info:hover{opacity:1;color:var(--gold-deep);transform:scale(1.12)}
.ideas-pill.is-active .ideas-pill-info{color:rgba(255,255,255,.75);opacity:.85}
.ideas-pill.is-active .ideas-pill-info:hover{color:white;opacity:1}
.ideas-pill-info.is-active-info{
 color:var(--gold);opacity:1;background:rgba(200,169,110,.15);
}
.ideas-pill.is-active .ideas-pill-info.is-active-info{
 color:white;background:rgba(255,255,255,.22);
}

.ideas-bar-desc-strip{
 display:none;
 margin-top:8px;
 background:linear-gradient(180deg,rgba(200,169,110,.10) 0%,rgba(200,169,110,.03) 100%);
 border:1px solid rgba(200,169,110,.3);
 border-radius:10px;
}
.ideas-bar-desc-strip.is-open{
 display:block;
 animation:ideas-desc-slide .2s ease;
}
@keyframes ideas-desc-slide{
 from{opacity:0;transform:translateY(-4px)}
 to{opacity:1;transform:translateY(0)}
}
.ideas-bar-desc-inner{
 padding:.75rem 1rem;
 display:flex;align-items:flex-start;gap:12px;
}
.ideas-bar-desc-body{
 flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;
}
.ideas-bar-desc-label{
 font-family:var(--ff-m);font-size:.58rem;font-weight:600;letter-spacing:.1em;
 text-transform:uppercase;color:var(--gold-deep);
}
.ideas-bar-desc-text{
 font-family:var(--ff-b);font-size:.8rem;color:var(--ink-mid);line-height:1.55;
}
.ideas-bar-desc-text strong{color:var(--green);font-weight:600}
.ideas-bar-desc-close{
 flex-shrink:0;width:22px;height:22px;border-radius:50%;
 border:1px solid rgba(200,169,110,.35);background:transparent;
 color:var(--ink-faint);cursor:pointer;font-size:14px;line-height:1;
 display:flex;align-items:center;justify-content:center;
 transition:all .15s;margin-top:1px;
}
.ideas-bar-desc-close:hover{background:rgba(200,169,110,.15);border-color:var(--gold);color:var(--gold-deep)}
.ideas-bar.collapsed .ideas-bar-desc-strip{display:none !important}

@media(max-width:620px){
 .ideas-bar-desc-inner{padding:.65rem .85rem}
 .ideas-bar-desc-text{font-size:.75rem}
 .ideas-pill-info{font-size:.68rem;margin-left:4px}
}

.ideas-bar-hide{
 display:inline-flex;align-items:center;gap:5px;
 font-family:var(--ff-m);font-size:.6rem;
 letter-spacing:.08em;text-transform:uppercase;
 color:var(--ink-faint);
 background:none;border:none;cursor:pointer;
 padding:5px 10px;border-radius:16px;
 margin-left:auto;
 white-space:nowrap;
 transition:color .15s, background .15s;
 flex-shrink:0;
 font-weight:500;
}
.ideas-bar-hide::before{
 content:"";
 width:11px;height:11px;
 background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 14 14' fill='none' stroke='%237A7A7A' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 7s2-4.5 6-4.5 6 4.5 6 4.5-2 4.5-6 4.5S1 7 1 7z'/%3E%3Ccircle cx='7' cy='7' r='1.8'/%3E%3C/svg%3E");
 background-repeat:no-repeat;background-position:center;
 display:inline-block;
}
.ideas-bar.collapsed .ideas-bar-hide::before{
 background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 14 14' fill='none' stroke='%237A7A7A' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.5 1.5l11 11'/%3E%3Cpath d='M5 3.5C5.6 3.3 6.3 3.2 7 3.2c4 0 6 4.3 6 4.3s-.6 1.2-1.7 2.4'/%3E%3Cpath d='M9.5 9.5c-.7.5-1.6.8-2.5.8-4 0-6-4.3-6-4.3s.8-1.6 2.3-3'/%3E%3C/svg%3E");
}
.ideas-bar-hide:hover{
 color:var(--green);
 background:rgba(44,74,62,.05);
}
.ideas-bar-hide:focus-visible{
 outline:2px solid var(--gold);
 outline-offset:2px;
}

@media(max-width:620px){
 .ideas-bar-pills{gap:4px}
 .ideas-pill{font-size:.7rem;padding:5px 11px}
 .ideas-bar-inner{padding:7px 10px}
}
@media(max-width:420px){
 .ideas-bar-label-text{display:none}
}

.ideas-hero{position:relative;z-index:1;max-width:1100px;margin:1.25rem auto 0;padding:0 clamp(20px,6vw,80px)}
.ideas-eyebrow{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;font-weight:500;margin-bottom:.4rem}
.ideas-eyebrow.ie-reddit{color:#A07840}
.ideas-eyebrow.ie-pinterest{color:#2C4A3E}
.ideas-h1{font-family:var(--ff-d);font-size:clamp(1.6rem,3.5vw,2.4rem);font-weight:400;color:var(--green);letter-spacing:-.01em;line-height:1.1;margin-bottom:.5rem}
.ideas-h1 em{font-style:italic;color:var(--gold)}
.ideas-h1-sub{font-size:.95rem;color:var(--ink-mid);line-height:1.5;max-width:640px}

.ideas-page{padding:1rem clamp(20px,6vw,80px) 80px;max-width:1100px;margin:0 auto;position:relative;z-index:1}

.ih-section-head{display:flex;justify-content:space-between;align-items:flex-start;margin:1rem 0 .75rem;gap:1rem;flex-wrap:wrap;padding:0 48px}
.ih-section-title{font-family:var(--ff-d);font-size:clamp(1.5rem,3vw,2rem);font-weight:500;color:var(--green);line-height:1.15}
.ih-section-title em{font-style:italic;color:var(--gold);font-weight:400}
.ih-section-desc{font-family:var(--ff-b);font-size:.88rem;color:var(--text-muted);line-height:1.6;margin-top:.65rem;max-width:560px}
.ih-section-desc em{font-style:italic;color:var(--ink)}
.ih-section-sub{font-family:var(--ff-m);font-size:.68rem;letter-spacing:.04em;color:var(--ink-faint);margin-top:3px}
.ih-refresh-btn{display:flex;align-items:center;gap:6px;padding:.45rem .85rem;font-family:var(--ff-m);font-size:.66rem;letter-spacing:.06em;font-weight:500;color:var(--green);background:white;border:1px solid var(--border-g);border-radius:20px;cursor:pointer;white-space:nowrap;transition:background .15s}
.ih-refresh-btn:hover{background:var(--green-pale)}
.ih-refresh-btn.spinning svg{animation:ih-spin .7s linear infinite}
@keyframes ih-spin{to{transform:rotate(360deg)}}

.reddit-page-grid-wrap{position:relative;margin-bottom:.75rem}
.reddit-carousel-row{display:flex;align-items:stretch;gap:8px}
/* Carousel arrows — restyled 2026-04-25 to match the vsbmodule pattern:
   round 40px buttons with a soft shadow, centered vertically beside the
   card row instead of stretching its full height. Reads more "premium
   editorial" than rectangular borders, and the lift-on-hover gives the
   click target a tactile feel on touch devices. */
.reddit-carousel-arrow{
 flex-shrink:0;width:40px;height:40px;background:#fff;border:1px solid var(--border-g);border-radius:50%;
 cursor:pointer;display:inline-flex;align-items:center;justify-content:center;color:var(--green);
 align-self:center;box-shadow:0 1px 3px rgba(44,74,62,.08);transition:all .18s ease;
}
.reddit-carousel-arrow:hover{background:#fff;border-color:var(--green);color:var(--green);box-shadow:0 3px 10px rgba(44,74,62,.14);transform:translateY(-1px)}
.reddit-carousel-arrow:active{transform:translateY(0);box-shadow:0 1px 3px rgba(44,74,62,.08)}
.reddit-carousel-arrow:disabled{opacity:.35;cursor:default;box-shadow:none;transform:none}
.reddit-carousel-arrow:disabled:hover{background:#fff;border-color:var(--border-g);transform:none;box-shadow:none}
.reddit-carousel-viewport{flex:1;overflow:hidden;position:relative}
.reddit-grid{display:flex;gap:12px;transition:transform .3s ease;will-change:transform}
.reddit-grid.is-auto-scrolling{transition:none}

.reddit-carousel-viewport::after{
 content:"";position:absolute;top:8px;right:8px;width:6px;height:6px;
 border-radius:50%;background:var(--gold);opacity:0;transition:opacity .25s;
 pointer-events:none;
}
.reddit-page-grid-wrap.rd-paused .reddit-carousel-viewport::after{opacity:.75}
.reddit-card{
 background:white;border:1px solid var(--border-g);border-radius:14px;overflow:hidden;
 box-shadow:0 2px 10px rgba(44,74,62,.04);
 transition:box-shadow .2s,border-color .2s,transform .2s;
 width:260px;flex-shrink:0;display:flex;flex-direction:column;cursor:pointer;
}
.reddit-card:hover{box-shadow:0 6px 24px rgba(44,74,62,.1);transform:translateY(-2px);border-color:var(--gold)}
.rc-head{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--cream-d);border-bottom:1px solid var(--border);flex-wrap:nowrap;gap:6px;overflow:hidden}
.sub-badge{font-family:var(--ff-m);font-size:.6rem;font-weight:500;padding:3px 9px;border-radius:20px;color:white;background:var(--green,#2C4A3E);letter-spacing:.02em}
.upvote-badge{font-family:var(--ff-m);font-size:.62rem;color:var(--ink-faint);display:flex;align-items:center;gap:4px}

.rc-source-badge{
 display:inline-flex;align-items:center;gap:4px;
 font-family:var(--ff-m);font-size:.56rem;font-weight:600;
 padding:2px 8px;border-radius:20px;letter-spacing:.06em;text-transform:uppercase;
 flex-shrink:0;white-space:nowrap;
}
.rc-source-badge .rc-pip{width:5px;height:5px;border-radius:50%;background:currentColor;display:inline-block;flex-shrink:0}
.rc-source-badge.live{background:rgba(90,140,122,.12);color:var(--green);border:1px solid rgba(90,140,122,.3)}
.rc-source-badge.live .rc-pip{animation:rc-pulse 1.5s ease-in-out infinite}
@keyframes rc-pulse{0%,100%{opacity:.4;transform:scale(.8)}50%{opacity:1;transform:scale(1.15)}}
.rc-source-badge.cached{background:var(--cream-d);color:var(--ink-faint);border:1px solid var(--border)}
.rc-source-badge.example{background:rgba(201,123,58,.1);color:var(--amber-risk);border:1px solid rgba(201,123,58,.3)}

.rc-match-badge{
 display:inline-flex;align-items:center;gap:3px;
 font-family:var(--ff-m);font-size:.58rem;font-weight:600;
 padding:2px 9px;border-radius:20px;letter-spacing:.04em;
 flex-shrink:0;white-space:nowrap;
 transition:opacity .45s ease,transform .45s cubic-bezier(.34,1.56,.64,1);
}
.rc-match-badge.match-high{background:rgba(90,140,122,.12);color:var(--green);border:1px solid rgba(90,140,122,.3)}
.rc-match-badge.match-med{background:rgba(200,169,110,.14);color:var(--gold-deep);border:1px solid rgba(200,169,110,.35)}
.rc-match-badge.match-low{background:var(--cream-d);color:var(--ink-faint);border:1px solid var(--border)}

.rc-stripe{height:5px;width:100%;flex-shrink:0}

.rc-detail{display:none;border-top:1px solid var(--border);padding:.85rem 1rem 1rem;background:var(--warm)}
.rc-detail.on{display:block;animation:rc-slide-down .25s ease}
@keyframes rc-slide-down{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
.rc-section{margin-bottom:.85rem}
.rc-section:last-child{margin-bottom:0}
.rc-label{display:flex;align-items:center;gap:6px;font-family:var(--ff-m);font-size:.56rem;letter-spacing:.09em;text-transform:uppercase;font-weight:600;color:var(--ink-faint);margin-bottom:5px}
.rc-text{font-size:.78rem;color:var(--ink-mid);line-height:1.55}
.rc-text strong{color:var(--ink);font-weight:600}
.rc-your-action{background:white;border:1px solid var(--border-g);border-left:3px solid var(--gold);border-radius:0 8px 8px 0;padding:.6rem .75rem;margin-top:.5rem}
.rc-your-action .rc-label{color:var(--gold-deep)}
.reddit-card.rc-expanded{width:100% !important;border-color:var(--green);border-width:2px;box-shadow:0 6px 22px rgba(44,74,62,.12)}
.rc-expand-btn.open{background:var(--cream-d);color:var(--green)}

.rc-match-summary{
 display:flex;align-items:flex-start;gap:10px;
 padding:.7rem .9rem;margin-bottom:.85rem;
 border-radius:10px;font-family:var(--ff-b);font-size:.8rem;line-height:1.5;
}
.rc-match-summary.strong{background:rgba(90,140,122,.08);border:1px solid rgba(90,140,122,.25);color:var(--green)}
.rc-match-summary.partial{background:rgba(200,169,110,.08);border:1px solid rgba(200,169,110,.3);color:var(--gold-deep)}
.rc-match-summary.weak{background:var(--cream-d);border:1px solid var(--border);color:var(--ink-mid)}
.rc-match-summary.none{background:rgba(201,123,58,.06);border:1px solid rgba(201,123,58,.2);color:var(--amber-risk)}
.rc-match-summary-icon{font-size:1rem;flex-shrink:0;line-height:1.1}
.rc-match-summary strong{font-weight:600}
.rc-body{padding:.75rem 1rem;display:flex;flex-direction:column;flex:1}
.rc-title{font-family:var(--ff-d);font-size:.98rem;font-weight:500;color:var(--ink);line-height:1.3;margin-bottom:.5rem}
.rc-snippet{font-size:.78rem;color:var(--ink-mid);line-height:1.55;margin-bottom:.7rem;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;flex:1}
.rc-meta{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.04em;color:var(--ink-faint);margin-bottom:.6rem;display:flex;gap:8px;flex-wrap:wrap}
.rc-footer{padding:.55rem 1rem .7rem;border-top:1px solid var(--border);flex-shrink:0;display:flex;gap:6px;align-items:stretch}
.rc-expand-btn{flex:1;padding:7px;background:var(--green);color:white;border:none;border-radius:8px;font-family:var(--ff-b);font-size:.74rem;font-weight:500;cursor:pointer;transition:background .15s}
.rc-expand-btn:hover{background:var(--green-mid)}
.rc-ask-btn{flex-shrink:0;padding:7px 11px;background:var(--cream);color:var(--green);border:1px solid var(--gold);border-radius:8px;font-family:var(--ff-b);font-size:.74rem;font-weight:500;cursor:pointer;transition:all .15s}
.rc-ask-btn:hover{background:var(--gold);color:var(--cream);border-color:var(--gold)}

.reddit-card-skel{background:var(--cream-d);border:1px solid var(--border);border-radius:14px;height:220px;width:260px;flex-shrink:0;animation:ideas-shimmer 1.6s ease-in-out infinite}
@keyframes ideas-shimmer{0%,100%{opacity:.45}50%{opacity:.85}}
@media(max-width:480px){
 .reddit-carousel-viewport{padding-left:4px;padding-right:2px}
 .reddit-card,.reddit-card-skel{width:min(260px,82vw)}
}

.fetch-status{display:flex;align-items:center;justify-content:center;padding:.6rem 0;margin-top:.25rem}
.fetch-status.hidden{display:none}
.fetch-status-inner{display:flex;align-items:center;gap:8px;font-family:var(--ff-m);font-size:.68rem;color:var(--ink-faint)}
.fetch-status-spinner{width:12px;height:12px;border:2px solid rgba(44,74,62,.2);border-top-color:var(--green);border-radius:50%;animation:ih-spin .7s linear infinite;flex-shrink:0}
.fetch-error{font-family:var(--ff-m);font-size:.7rem;color:var(--danger);text-align:center;padding:.5rem 0}

.grid-updating-bar{display:none;align-items:center;gap:8px;padding:.55rem 1rem;margin-bottom:.75rem;background:var(--gold-pale);border:1px solid var(--border-g);border-radius:8px;font-family:var(--ff-m);font-size:.7rem;color:var(--ink)}
.grid-updating-bar.on{display:flex}
.grid-updating-bar .gu-spinner{width:12px;height:12px;border:2px solid rgba(200,169,110,.25);border-top-color:var(--gold-deep);border-radius:50%;animation:ih-spin .7s linear infinite;flex-shrink:0}
.grid-updating-bar .gu-text{flex:1}
.grid-updating-bar .gu-filter{color:var(--gold-deep);font-weight:600}
.grid-updating-bar .gu-timer{margin-left:auto;font-size:.62rem;color:var(--ink-faint);white-space:nowrap}

.ih-profile-row{background:var(--cream-d);border:1px solid var(--border-g);border-radius:14px;padding:1rem 1.1rem;margin-top:1.5rem}
.ih-profile-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:.75rem}
.ih-profile-star{color:var(--gold);font-size:.9rem}
.ih-profile-title{font-family:var(--ff-d);font-size:1.05rem;font-weight:500;color:var(--green)}
.ih-profile-status{margin-left:auto;font-family:var(--ff-m);font-size:.62rem;color:var(--ink-faint);letter-spacing:.04em}
.ih-profile-fields{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end}
.ih-pf-group{flex:1;min-width:170px;display:flex;flex-direction:column;gap:4px}
.ih-pf-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-faint);font-weight:500}
.ih-pf-input{border:1px solid var(--border-g);border-radius:8px;padding:9px 11px;font-size:.85rem;font-family:var(--ff-b);color:var(--ink);background:white;outline:none;transition:border-color .15s;width:100%}
.ih-pf-input:focus{border-color:var(--green)}
.ih-pf-select{appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='none' stroke='%234A4A4A' stroke-width='1.2' d='M1 1l4 4 4-4'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;padding-right:28px}
.ih-pf-btn-wrap{display:flex;flex-direction:column;gap:4px}
.ih-pf-btn{display:inline-flex;align-items:center;gap:6px;padding:9px 16px;background:var(--green);color:white;border:none;border-radius:8px;font-family:var(--ff-b);font-size:.78rem;font-weight:500;cursor:pointer;transition:background .15s;white-space:nowrap}
.ih-pf-btn:hover{background:var(--green-mid)}
.ih-pf-btn-sec{background:white;color:var(--green);border:1px solid var(--border-g)}
.ih-pf-btn-sec:hover{background:var(--green-pale)}

.ih-community-tags{margin-top:.8rem}
.ih-platform-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:.4rem}
.ih-platform-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);font-weight:500;margin-right:4px}
.ih-ctag{display:inline-flex;align-items:center;gap:4px;font-family:var(--ff-m);font-size:.66rem;padding:3px 9px;border-radius:20px;background:var(--green-pale);color:var(--green);border:1px solid rgba(44,74,62,.15);font-weight:500}
.ih-ctag.live{background:rgba(160,120,64,.07);color:#8a6535;border-color:rgba(160,120,64,.2)}
.ih-ctag.live::before{content:"";display:inline-block;width:5px;height:5px;background:#A07840;border-radius:50%;margin-right:2px}
.ih-ctag.pinterest{background:rgba(44,74,62,.07);color:#1F3A2F;border-color:rgba(44,74,62,.25);font-weight:600}
.ih-ctag.pinterest::before{content:"P/";opacity:.55;font-weight:400;margin-right:2px}

.ih-deep-divider{height:1px;background:var(--border-g);margin:1rem 0}

.ih-deep-search{}
.ih-deep-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:.5rem;flex-wrap:wrap;gap:.25rem}
.ih-deep-label{font-family:var(--ff-d);font-size:1rem;font-weight:500;color:var(--green)}
.ih-deep-hint{font-family:var(--ff-m);font-size:.62rem;color:var(--ink-faint)}
.ih-textarea{width:100%;min-height:80px;resize:vertical;border:1px solid var(--border-g);border-radius:8px;padding:.7rem .85rem;font-size:.85rem;font-family:var(--ff-b);color:var(--ink);background:white;box-sizing:border-box;outline:none;transition:border-color .15s;line-height:1.5}
.ih-textarea:focus{border-color:var(--green)}
.ih-chips{margin-top:.75rem}
.ih-chips-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:.4rem;display:block}
.ih-chip-row{display:flex;flex-wrap:wrap;gap:6px}
.ih-chip{padding:5px 11px;border:1px solid var(--border-g);border-radius:20px;font-size:.72rem;cursor:pointer;background:white;color:var(--ink-mid);transition:all .12s;font-family:var(--ff-b)}
.ih-chip.on{background:var(--green);color:white;border-color:var(--green)}
.ih-deep-foot{display:flex;gap:1rem;margin-top:.85rem;flex-wrap:wrap;justify-content:space-between}
.ih-btn-hint{display:block;font-family:var(--ff-m);font-size:.58rem;color:var(--ink-faint);margin-top:3px}

.sr-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:.75rem;flex-wrap:wrap;gap:8px}
.sr-title{font-family:var(--ff-d);font-size:1.15rem;font-weight:500;color:var(--green)}
.sr-title em{font-style:italic;color:var(--gold);font-weight:400}
.sr-meta{font-family:var(--ff-m);font-size:.66rem;color:var(--ink-faint)}
.situation-results{display:none;margin-top:1.25rem;padding-top:1.25rem;border-top:1px solid var(--border-g)}
.situation-results.on{display:block}
.sr-loading{display:none;align-items:center;gap:8px;font-family:var(--ff-m);font-size:.72rem;color:var(--ink-faint);padding:.4rem 0}
.sr-loading.on{display:flex}
.sr-grid{display:flex;flex-wrap:wrap;gap:12px;margin-top:.5rem}
.sr-grid .reddit-card{width:calc(50% - 6px)}
@media(max-width:700px){.sr-grid .reddit-card{width:100%}}
.sr-disclaimer{display:none;margin-top:.75rem;font-family:var(--ff-m);font-size:.62rem;color:var(--ink-faint);padding:.4rem .6rem;background:var(--cream-d);border-radius:6px}
.sr-disclaimer.on{display:block}

.sr-scan-wrap{display:none;margin:.75rem 0}
.sr-scan-wrap.on{display:block}
.sr-scan-bar{display:flex;align-items:center;gap:10px;padding:.55rem .75rem;background:white;border:1px solid var(--border-g);border-radius:8px;margin-bottom:.35rem}
.sr-scan-pulse{width:8px;height:8px;border-radius:50%;background:#A07840;flex-shrink:0;animation:sr-pulse 1s ease-in-out infinite}
@keyframes sr-pulse{0%,100%{opacity:.3;transform:scale(.85)}50%{opacity:1;transform:scale(1.1)}}
.sr-scan-community{font-family:var(--ff-m);font-size:.68rem;color:var(--green);font-weight:600;min-width:140px}
.sr-scan-track{flex:1;height:4px;background:var(--cream-d);border-radius:20px;overflow:hidden;position:relative}
.sr-scan-fill{height:100%;background:linear-gradient(90deg,var(--gold),var(--green));transition:width .4s ease;border-radius:20px}
.sr-scan-count{font-family:var(--ff-m);font-size:.62rem;color:var(--ink-faint);min-width:58px;text-align:right}

.rp-wrap{display:none;margin-top:1.25rem}
.rp-wrap.on{display:block}
.rp-panel{background:white;border:1px solid var(--border-g);border-radius:14px;overflow:hidden}
.rp-header{display:flex;gap:12px;padding:1rem 1.1rem;background:var(--green);color:white;align-items:flex-start}
.rp-header-icon{flex-shrink:0;width:32px;height:32px;background:rgba(255,255,255,.12);border-radius:50%;display:flex;align-items:center;justify-content:center}
.rp-header-text{flex:1;min-width:0}
.rp-eyebrow{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--gold-lt);font-weight:500}
.rp-header-title{font-family:var(--ff-d);font-size:1.15rem;font-weight:500;margin-top:3px;line-height:1.25}
.rp-header-title em{font-style:italic;color:var(--gold-lt);font-weight:400}
.rp-header-sub{font-size:.76rem;color:rgba(255,255,255,.75);margin-top:5px;line-height:1.5}
.rp-body{padding:1rem 1.1rem}
.rp-subs-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-faint);font-weight:500;margin-bottom:.45rem}
.rp-subs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:1rem}
.rp-sub-chip{padding:4px 10px;border:1px solid rgba(160,120,64,.25);border-radius:20px;background:rgba(160,120,64,.06);color:#8a6535;font-family:var(--ff-m);font-size:.68rem;cursor:pointer;transition:all .12s}
.rp-sub-chip.on{background:#A07840;color:white;border-color:#A07840}
.rp-loading{display:flex;align-items:center;gap:8px;padding:.5rem 0;font-family:var(--ff-m);font-size:.72rem;color:var(--ink-faint)}
.rp-form-area{margin-bottom:1rem}
.rp-form-bar{display:flex;justify-content:space-between;align-items:center;margin-bottom:.4rem}
.rp-form-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-faint);font-weight:500}
.rp-copy-btn{display:inline-flex;align-items:center;gap:4px;font-family:var(--ff-m);font-size:.58rem;color:var(--green);background:none;border:1px solid var(--border-g);border-radius:20px;padding:2px 9px;cursor:pointer;transition:all .12s}
.rp-copy-btn:hover{background:var(--green-pale)}
.rp-title-input{width:100%;border:1px solid var(--border-g);border-radius:8px;padding:9px 11px;font-size:.9rem;font-family:var(--ff-b);color:var(--ink);background:white;outline:none;transition:border-color .15s}
.rp-title-input:focus{border-color:var(--green)}
.rp-body-textarea{width:100%;min-height:130px;resize:vertical;border:1px solid var(--border-g);border-radius:8px;padding:.7rem .85rem;font-size:.82rem;font-family:var(--ff-b);color:var(--ink-mid);background:white;outline:none;transition:border-color .15s;line-height:1.55;box-sizing:border-box}
.rp-body-textarea:focus{border-color:var(--green)}
.rp-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.rp-action-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border-radius:8px;font-family:var(--ff-b);font-size:.76rem;font-weight:500;cursor:pointer;transition:all .15s;border:1px solid transparent}
.rp-copy-all-btn{background:white;color:var(--green);border-color:var(--border-g)}
.rp-copy-all-btn:hover{background:var(--green-pale)}
.rp-post-btn{background:#A07840;color:white}
.rp-post-btn:hover{background:#8a6535}
.rp-regen-btn{background:white;color:var(--ink-mid);border-color:var(--border-g)}
.rp-regen-btn:hover{background:var(--cream-d)}
.rp-actions-hint{font-family:var(--ff-m);font-size:.58rem;color:var(--ink-faint);margin-left:auto}

.brief-box{display:none;margin-top:1.5rem;background:white;border:1px solid var(--border-g);border-radius:14px;overflow:hidden}
.brief-box.on{display:block}
.brief-header{padding:1rem 1.2rem;background:var(--green);color:white}
.brief-title{font-family:var(--ff-d);font-size:1.2rem;font-weight:500}
.brief-date{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;color:rgba(255,255,255,.65);margin-top:3px}
.brief-sub{font-size:.78rem;color:rgba(255,255,255,.8);margin-top:5px}
.brief-body{padding:1.1rem 1.2rem}
.brief-section{margin-bottom:1.1rem}
.brief-section:last-child{margin-bottom:0}
.bsec-label{display:flex;align-items:center;gap:7px;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-mid);font-weight:600;margin-bottom:.4rem}
.bdot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.brief-ai-loading{display:flex;align-items:center;gap:8px;font-family:var(--ff-m);font-size:.72rem;color:var(--ink-faint);padding:.3rem 0}
.brief-ai-loading.hidden{display:none}
.brief-ai-loading .bspin{width:12px;height:12px;border:2px solid rgba(44,74,62,.2);border-top-color:var(--green);border-radius:50%;animation:ih-spin .7s linear infinite}
.brief-ai-output{font-size:.85rem;color:var(--ink-mid);line-height:1.7}
.brief-ai-output strong{font-weight:600;color:var(--ink)}
.brief-ai-output > *:first-child{margin-top:0}
.brief-ai-output > .brief-contact-item:first-child,
.brief-ai-output > .brief-gap-item:first-child{padding-top:2px}

.brief-summary{
 display:none;padding:11px 14px;margin-bottom:1rem;
 background:var(--cream);border-left:3px solid var(--green);border-radius:3px 8px 8px 3px;
 font-size:.88rem;color:var(--ink);line-height:1.55;
}
.brief-summary.on{display:block}
.brief-summary-label{
 display:inline-block;font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;
 text-transform:uppercase;color:var(--green-mid);font-weight:600;margin-right:8px;
 vertical-align:baseline;
}
.brief-error{
 background:rgba(185,64,64,.06);border:1px solid rgba(185,64,64,.25);border-radius:8px;
 padding:.75rem .9rem;color:var(--ink-mid);font-size:.82rem;line-height:1.6;
}
.brief-error strong{color:var(--danger);font-weight:600}

.brief-plan-list{margin:0;padding-left:1.25rem;list-style-position:outside}
.brief-plan-list li{margin:.35rem 0;padding-left:.15rem;line-height:1.65}
.brief-plan-list li::marker{color:var(--gold-deep);font-family:var(--ff-m);font-size:.8em}

.brief-contact-item{padding:10px 0;border-bottom:1px dashed var(--border-g)}
.brief-contact-item:last-child{border-bottom:none}
.bci-head{display:flex;align-items:center;gap:10px;margin-bottom:4px;flex-wrap:wrap}
.bci-cat{font-family:var(--ff-b);font-size:.92rem;color:var(--charcoal);font-weight:500}
.bci-rationale{font-size:.84rem;color:var(--ink-mid);line-height:1.55}
.bci-lead{font-family:var(--ff-m);font-size:.68rem;color:var(--ink-faint);margin-top:3px;letter-spacing:.03em;text-transform:uppercase}
.urg-badge{display:inline-flex;align-items:center;padding:2px 9px;border-radius:10px;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;font-weight:600}
.urg-badge.uc-critical{background:rgba(185,64,64,.1);color:var(--danger);border:1px solid rgba(185,64,64,.25)}
.urg-badge.uc-high{background:rgba(200,169,110,.12);color:var(--gold-deep);border:1px solid rgba(200,169,110,.35)}
.urg-badge.uc-medium{background:rgba(44,74,62,.08);color:var(--green-mid);border:1px solid rgba(44,74,62,.2)}
/* 2026-05-01 Slice 8c: bucketed plan view (Overdue / This week / This
   month / Later / No target date). Each bucket gets a header and the
   items are sorted by target_contact_date ascending within. */
.brief-bucket{margin-top:10px}
.brief-bucket:first-child{margin-top:0}
.brief-bucket-label{display:flex;align-items:center;gap:8px;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-mid);font-weight:600;padding:8px 0 6px;border-top:1px solid var(--border-g);margin-bottom:2px}
.brief-bucket:first-child .brief-bucket-label{border-top:none;padding-top:0}
.brief-bucket-count{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 6px;border-radius:9px;background:rgba(44,74,62,.08);color:var(--green-mid);font-family:var(--ff-m);font-size:.62rem;font-weight:600;letter-spacing:0}
.brief-bucket.bbk-overdue .brief-bucket-label{color:var(--gold-deep,#A07840)}
.brief-bucket.bbk-overdue .brief-bucket-count{background:rgba(160,120,64,.12);color:var(--gold-deep,#A07840)}
.brief-bucket.bbk-week .brief-bucket-label{color:var(--gold-deep)}
.brief-bucket.bbk-week .brief-bucket-count{background:rgba(200,169,110,.15);color:var(--gold-deep)}
.brief-bucket.bbk-later .brief-bucket-label,
.brief-bucket.bbk-undated .brief-bucket-label{color:var(--ink-faint)}
.bci-due{display:inline-block;font-family:var(--ff-m);font-size:.66rem;letter-spacing:.04em;color:var(--ink-mid);margin:2px 0 4px;padding:2px 8px;border-radius:10px;background:rgba(44,74,62,.05);border:1px solid var(--border-g)}

.brief-gap-item{padding:10px 0;border-bottom:1px dashed var(--border-g)}
.brief-gap-item:last-child{border-bottom:none}
.bgi-name{font-family:var(--ff-b);font-size:.88rem;color:var(--charcoal);font-weight:500;margin-bottom:4px}
.bgi-list{margin:0;padding-left:1.2rem;font-size:.82rem;color:var(--ink-mid);line-height:1.55}
.bgi-list li{margin:2px 0}

.brief-empty{padding:14px 16px;background:var(--cream);border-radius:8px;font-size:.82rem;color:var(--ink-mid);font-style:italic;border:1px dashed var(--border-g)}

.checklist-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px;margin-top:4px}
.cl-item{padding:10px 12px;border-radius:8px;border:1px solid var(--border-g);background:var(--white);display:flex;flex-direction:column;gap:3px}
.cl-item.cls-skipped{background:var(--cream);opacity:.65}
.cl-item.cls-signed{background:rgba(44,74,62,.05);border-color:rgba(44,74,62,.25)}
.cl-item.cls-complete{background:rgba(44,74,62,.12);border-color:var(--green-mid)}
.cl-item.cls-unsigned{background:rgba(200,169,110,.06);border-color:rgba(200,169,110,.3)}
.cl-item.cls-self{background:var(--cream);border-style:dashed}
.cl-name{font-family:var(--ff-b);font-size:.82rem;color:var(--charcoal);font-weight:500}
.cl-budget{font-family:var(--ff-mono,monospace);font-size:.72rem;color:var(--ink-faint)}
.cl-state{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted)}
.cl-item.cls-signed .cl-state{color:var(--green-mid)}
.cl-item.cls-complete .cl-state{color:var(--green);font-weight:700}
.cl-item.cls-unsigned .cl-state{color:var(--gold-deep)}
.cl-item.cls-skipped .cl-state{color:var(--ink-faint)}
.cl-vendor{font-size:.75rem;color:var(--ink-mid);font-style:italic;margin-top:2px}

.brief-badge{
 display:inline-flex;align-items:center;gap:5px;
 margin-top:8px;padding:3px 9px;
 background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.2);border-radius:20px;
 font-family:var(--ff-m);font-size:.55rem;letter-spacing:.08em;text-transform:uppercase;
 color:rgba(255,255,255,.9);
}
.brief-badge svg{opacity:.7}

.brief-cite{
 display:inline-block;
 background:var(--gold-pale);color:var(--gold-deep);
 font-family:var(--ff-m);font-size:.58rem;font-weight:600;
 padding:1px 5px;margin:0 1px;border-radius:8px;
 cursor:pointer;transition:all .15s;vertical-align:.15em;
 border:1px solid rgba(200,169,110,.3);
}
.brief-cite:hover{background:var(--gold);color:white;border-color:var(--gold)}
.brief-cite.is-active{background:var(--gold-deep);color:white;border-color:var(--gold-deep)}

.brief-refine{
 margin-top:1.25rem;padding-top:1rem;
 border-top:1px dashed var(--border-g);
}
.brief-refine-label{
 font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;
 color:var(--ink-faint);margin-bottom:.6rem;
}
.brief-refine-chips{display:flex;flex-wrap:wrap;gap:8px}
.brief-refine-chip{
 display:inline-flex;align-items:center;gap:6px;
 background:white;border:1px solid var(--border-g);border-radius:20px;
 padding:6px 14px;
 font-family:var(--ff-m);font-size:.74rem;color:var(--green);
 cursor:pointer;transition:all .15s;
}
.brief-refine-chip:hover{background:var(--green-pale);border-color:var(--green-lt)}
.brief-refine-chip:disabled{opacity:.5;cursor:default}
.brief-refine-chip .ai-spark{color:var(--gold);font-size:.78rem}

.brief-evidence-panel{
 margin-top:1rem;padding:.85rem 1rem;
 background:var(--gold-pale);border:1px solid rgba(200,169,110,.35);border-radius:10px;
 animation:brief-ev-slide .22s ease;
}
@keyframes brief-ev-slide{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
.brief-evidence-head{
 display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem;
}
.brief-evidence-title{
 font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;
 color:var(--gold-deep);font-weight:600;
}
.brief-evidence-close{
 width:22px;height:22px;border-radius:50%;border:1px solid rgba(200,169,110,.35);
 background:transparent;color:var(--ink-faint);cursor:pointer;font-size:14px;line-height:1;
 display:flex;align-items:center;justify-content:center;transition:all .15s;
}
.brief-evidence-close:hover{background:white;border-color:var(--gold);color:var(--gold-deep)}
.brief-evidence-item{
 padding:.5rem 0;border-top:1px dashed rgba(200,169,110,.25);
 font-size:.78rem;color:var(--ink-mid);line-height:1.55;
}
.brief-evidence-item:first-child{border-top:none;padding-top:0}
.brief-evidence-item .ev-head{
 display:flex;align-items:center;gap:6px;margin-bottom:3px;
 font-family:var(--ff-m);font-size:.6rem;letter-spacing:.05em;color:var(--gold-deep);font-weight:600;
}
.brief-evidence-item .ev-num{
 display:inline-block;background:var(--gold);color:white;
 font-size:.58rem;font-weight:600;padding:1px 6px;border-radius:8px;
}
.brief-evidence-item .ev-title{color:var(--ink);font-weight:500}
.brief-evidence-item .ev-sub{color:var(--ink-faint);font-size:.7rem;margin-top:2px}

.ideas-disclaimer{margin-top:.75rem;font-family:var(--ff-m);font-size:.6rem;color:var(--ink-faint);font-style:italic}

.pi-grid-wrap{position:relative;margin-bottom:.75rem}

.pi-carousel-row{display:flex;align-items:stretch;gap:8px}
.pi-carousel-arrow{
 flex-shrink:0;width:32px;background:white;border:1px solid var(--border-g);border-radius:8px;cursor:pointer;
 display:flex;align-items:center;justify-content:center;color:var(--green);transition:all .15s;align-self:stretch;
}
.pi-carousel-arrow:hover{background:var(--green-pale);border-color:var(--green-lt)}
.pi-carousel-arrow:disabled{opacity:.3;cursor:default}
.pi-carousel-viewport{flex:1;overflow:hidden;position:relative}

.pi-grid{display:flex;gap:12px;flex-wrap:wrap}
.pi-grid.is-carousel{flex-wrap:nowrap;transition:transform .3s ease;will-change:transform}
.pi-grid.is-carousel.is-auto-scrolling{transition:none}

.pi-card{background:white;border:1px solid var(--border-g);border-radius:14px;overflow:hidden;cursor:pointer;transition:box-shadow .2s,border-color .2s,transform .2s;width:calc(33.333% - 8px);flex-shrink:0;display:flex;flex-direction:column;min-width:200px}
.pi-grid.is-carousel .pi-card{width:240px;min-width:0}
.pi-card:hover{box-shadow:0 6px 24px rgba(44,74,62,.14);transform:translateY(-2px);border-color:rgba(44,74,62,.3)}
.pi-card-img{height:120px;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;overflow:hidden}
.pi-card-img-icon{font-size:30px;opacity:.7}
.pi-card-saves{position:absolute;top:8px;right:9px;background:rgba(0,0,0,.48);color:white;font-family:var(--ff-m);font-size:.56rem;font-weight:600;padding:2px 7px;border-radius:20px;letter-spacing:.03em}
.pi-card-body{padding:.8rem .9rem;display:flex;flex-direction:column;flex:1}
.pi-card-topic{font-family:var(--ff-m);font-size:.56rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:#2C4A3E;margin-bottom:5px}
.pi-card-title{font-family:var(--ff-d);font-size:.9rem;font-weight:500;color:var(--ink);line-height:1.35;margin-bottom:.5rem;flex:1;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.pi-card-tags{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:.6rem}
.pi-card-tag{font-family:var(--ff-m);font-size:.55rem;background:rgba(44,74,62,.07);color:#1F3A2F;border:1px solid rgba(44,74,62,.2);border-radius:20px;padding:1px 7px;white-space:nowrap}
.pi-card-btn{width:100%;padding:7px;background:#2C4A3E;color:white;border:none;border-radius:8px;font-family:var(--ff-b);font-size:.72rem;font-weight:500;cursor:pointer;transition:background .15s;margin-top:auto;flex-shrink:0}
.pi-card-btn:hover{background:#1F3A2F}
.pi-skel{background:var(--cream-d);border:1px solid var(--border);border-radius:14px;height:240px;width:calc(33.333% - 8px);min-width:200px;flex-shrink:0;animation:ideas-shimmer 1.6s ease-in-out infinite}
.pi-grid.is-carousel .pi-skel{width:240px;min-width:0}
.pi-empty{padding:2rem;text-align:center;color:var(--ink-faint);font-family:var(--ff-m);font-size:.82rem;background:var(--cream-d);border-radius:14px;border:1px dashed var(--border-g);width:100%}

.pi-grid-wrap.pi-paused .pi-carousel-viewport::after{opacity:.75}
.pi-carousel-viewport::after{
 content:"";position:absolute;top:8px;right:8px;width:6px;height:6px;
 border-radius:50%;background:var(--gold);opacity:0;transition:opacity .25s;
 pointer-events:none;z-index:2;
}

@media(max-width:700px){
 .pi-card,.pi-skel{width:calc(50% - 6px);min-width:0}
 .pi-grid.is-carousel .pi-card,.pi-grid.is-carousel .pi-skel{width:200px}
 .pi-card-img{height:90px}
}
@media(max-width:440px){
 .pi-card,.pi-skel{width:100%}
 .pi-grid.is-carousel .pi-card,.pi-grid.is-carousel .pi-skel{width:180px}
}

.pi-find-btn{display:inline-flex;align-items:center;gap:6px;padding:9px 16px;background:#2C4A3E;color:white;border:none;border-radius:8px;font-family:var(--ff-b);font-size:.78rem;font-weight:500;cursor:pointer;transition:background .15s;white-space:nowrap}
.pi-find-btn:hover{background:#1F3A2F}
.ih-refresh-btn.pi-refresh{color:#2C4A3E;background:white;border-color:rgba(44,74,62,.25)}
.ih-refresh-btn.pi-refresh:hover{background:rgba(44,74,62,.06)}

.ideas-eyebrow.ie-tiktok{color:#C97B3A}
.ih-ctag.tiktok{background:rgba(201,123,58,.07);color:#A66530;border-color:rgba(201,123,58,.22);font-weight:600}
.ih-ctag.tiktok::before{content:"";margin-right:3px;opacity:.6;font-weight:400}

.tt-grid-wrap{position:relative;margin-bottom:.75rem}

.tt-carousel-row{display:flex;align-items:stretch;gap:8px}
.tt-carousel-arrow{
 flex-shrink:0;width:32px;background:white;border:1px solid var(--border-g);border-radius:8px;cursor:pointer;
 display:flex;align-items:center;justify-content:center;color:var(--green);transition:all .15s;align-self:stretch;
}
.tt-carousel-arrow:hover{background:var(--green-pale);border-color:var(--green-lt)}
.tt-carousel-arrow:disabled{opacity:.3;cursor:default}
.tt-carousel-viewport{flex:1;overflow:hidden;position:relative}

.tt-grid{display:flex;gap:12px;flex-wrap:wrap}
.tt-grid.is-carousel{flex-wrap:nowrap;transition:transform .3s ease;will-change:transform}
.tt-grid.is-carousel.is-auto-scrolling{transition:none}

.tt-card{
 background:white;border:1px solid var(--border-g);border-radius:14px;overflow:hidden;cursor:pointer;
 transition:box-shadow .2s,border-color .2s,transform .2s;
 width:calc(33.333% - 8px);flex-shrink:0;display:flex;flex-direction:column;min-width:200px;
}
.tt-grid.is-carousel .tt-card{width:240px;min-width:0}

.tt-grid-wrap.tt-paused .tt-carousel-viewport::after{opacity:.75}
.tt-carousel-viewport::after{
 content:"";position:absolute;top:8px;right:8px;width:6px;height:6px;
 border-radius:50%;background:var(--gold);opacity:0;transition:opacity .25s;
 pointer-events:none;z-index:2;
}
.tt-card:hover{box-shadow:0 6px 24px rgba(201,123,58,.14);transform:translateY(-2px);border-color:rgba(201,123,58,.3)}
.tt-card-thumb{
 height:150px;position:relative;overflow:hidden;flex-shrink:0;
 background:linear-gradient(135deg,#1a1a1a 0%,#1e2a24 100%);
 display:flex;align-items:center;justify-content:center;
}
.tt-card-thumb-emoji{font-size:42px;opacity:.85;filter:drop-shadow(0 2px 8px rgba(0,0,0,.4))}
.tt-card-play-overlay{
 position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
 width:42px;height:42px;border-radius:50%;
 background:rgba(255,255,255,.9);
 display:flex;align-items:center;justify-content:center;
 box-shadow:0 4px 14px rgba(0,0,0,.3);
 transition:transform .18s;
}
.tt-card:hover .tt-card-play-overlay{transform:translate(-50%,-50%) scale(1.08)}
.tt-card-play-overlay::after{
 content:"";width:0;height:0;border-style:solid;border-width:7px 0 7px 11px;
 border-color:transparent transparent transparent #C97B3A;margin-left:3px;
}
.tt-card-meta-top{
 position:absolute;top:8px;left:9px;right:9px;display:flex;justify-content:space-between;align-items:flex-start;pointer-events:none;
}
.tt-card-category{
 background:rgba(0,0,0,.55);color:white;font-family:var(--ff-m);font-size:.52rem;
 letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:3px 8px;border-radius:20px;
}
.tt-card-duration{
 background:rgba(0,0,0,.55);color:white;font-family:var(--ff-m);font-size:.58rem;
 padding:2px 7px;border-radius:4px;
}
.tt-card-body{padding:.8rem .9rem;display:flex;flex-direction:column;flex:1}
.tt-card-creator{display:flex;align-items:center;gap:5px;font-family:var(--ff-m);font-size:.58rem;font-weight:500;color:#C97B3A;margin-bottom:5px}
.tt-card-title{font-family:var(--ff-d);font-size:.92rem;font-weight:500;color:var(--ink);line-height:1.35;margin-bottom:.55rem;flex:1;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.tt-card-stats{display:flex;gap:10px;margin-bottom:.55rem;font-family:var(--ff-m);font-size:.6rem;color:var(--ink-faint)}
.tt-card-stats span{display:inline-flex;align-items:center;gap:3px}
.tt-card-tags{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:.6rem}
.tt-card-tag{font-family:var(--ff-m);font-size:.54rem;background:rgba(201,123,58,.07);color:#A66530;border:1px solid rgba(201,123,58,.18);border-radius:20px;padding:1px 7px;white-space:nowrap}
.tt-card-btn{width:100%;padding:7px;background:#C97B3A;color:white;border:none;border-radius:8px;font-family:var(--ff-b);font-size:.72rem;font-weight:500;cursor:pointer;transition:background .15s;margin-top:auto;flex-shrink:0}
.tt-card-btn:hover{background:#A66530}
.tt-skel{background:var(--cream-d);border:1px solid var(--border);border-radius:14px;height:280px;width:calc(33.333% - 8px);min-width:200px;flex-shrink:0;animation:ideas-shimmer 1.6s ease-in-out infinite}
.tt-grid.is-carousel .tt-skel{width:240px;min-width:0}
.tt-find-btn{display:inline-flex;align-items:center;gap:6px;padding:9px 16px;background:#C97B3A;color:white;border:none;border-radius:8px;font-family:var(--ff-b);font-size:.78rem;font-weight:500;cursor:pointer;transition:background .15s;white-space:nowrap}
.tt-find-btn:hover{background:#A66530}
.ih-refresh-btn.tt-refresh{color:#C97B3A;background:white;border-color:rgba(201,123,58,.25)}
.ih-refresh-btn.tt-refresh:hover{background:rgba(201,123,58,.05)}

@media(max-width:700px){
 .tt-card,.tt-skel{width:calc(50% - 6px);min-width:0}
 .tt-grid.is-carousel .tt-card,.tt-grid.is-carousel .tt-skel{width:200px}
 .tt-card-thumb{height:120px}
 .tt-card-thumb-emoji{font-size:34px}
}
@media(max-width:440px){
 .tt-card,.tt-skel{width:100%}
 .tt-grid.is-carousel .tt-card,.tt-grid.is-carousel .tt-skel{width:180px}
}

.step-bar.has-ideas{grid-template-columns:auto 1px 1fr auto 1fr auto 1fr auto 1fr auto 1fr !important}

@media(max-width:860px){
 .ideas-btn{padding:.7rem .75rem;gap:8px}
 .ideas-btn-name{font-size:.82rem}
 .ideas-btn-icon{width:22px;height:22px;font-size:.62rem}
 .ideas-menu{min-width:220px}
}
@media(max-width:560px){
 .ideas-btn-text{display:none}
 .ideas-btn{padding:.7rem .6rem}
 .step-bar.has-ideas{grid-template-columns:auto 1px 1fr auto 1fr auto 1fr auto 1fr auto 1fr !important}
}

/* The .ai-spark mark is Verdeaux's "we orchestrated this for you" signal —
 appears on every AI-driven action button (Parsing / Searching / Analyzing /
 Generate). Green for high contrast on cream backgrounds; the glyph itself
 is rendered as ✨ in the markup so it reads as "value-add" not generic
 chrome. Pure brand-decorative stars stay gold elsewhere. */
.ai-spark{display:inline-block;color:currentColor;margin-right:4px;font-size:.95em;line-height:1;font-variant-emoji:text}

/* ═══ Profile shortcuts bar ════════════════════════════════════════════
 Sits below the page header, above the step-bar nav. Always-visible
 persistent quick access to the four Account-modal tabs. Mimics
 vsb.solutions' workflow-bar look-and-feel: sticky sub-header, pills
 with rounded icon-squares, hover lifts to the brand accent. */
/* Fixed-position strip permanently locked at the top of the viewport,
 just below the page header (which is itself fixed at top:0 with
 ~62px height). Cream bg + backdrop-blur match the header for visual
 cohesion. The signed-in body class bumps `.bridge` padding so content
 starts below this bar; signed-out users keep the original padding. */
.vx-profile-bar{position:fixed;top:74px;left:0;right:0;z-index:80;background:rgba(250,247,242,1);/* backdrop-filter dropped 2026-07-21 — inert (opaque bg) + iPadOS tap-swallow hazard over the open account dropdown; see header */border-bottom:1px solid var(--border-g,rgba(44,74,62,.12));padding-left:max(2rem,env(safe-area-inset-left));padding-right:max(2rem,env(safe-area-inset-right));line-height:1;display:flex;align-items:center;min-height:54px}

/* Pipeline v2 — Your Situation panel (Step 13)
   Mounted at the top of category Prepare phases when the category
   declares a situationTemplate. Reads window.state.weddingDetails. */
.vx-situation{background:var(--white,#fff);border:1px solid rgba(44,74,62,.12);border-left:3px solid var(--gold);border-radius:0 var(--radius-lg,10px) var(--radius-lg,10px) 0;padding:18px 22px;margin:12px 0 24px}
.vx-situation-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
.vx-situation-eyebrow a{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;color:var(--green);text-decoration:underline;text-transform:none;letter-spacing:0;font-weight:500}
.vx-situation-prose{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.08rem;line-height:1.55;color:var(--ink);margin-bottom:14px}
.vx-situation-prose em{color:var(--gold-deep,#A07840);font-style:italic}
.vx-situation-divider{border:0;border-top:1px solid rgba(44,74,62,.1);margin:14px 0}
.vx-situation-timeline{display:grid;grid-template-columns:1fr auto;gap:6px 16px;font-size:.86rem}
.vx-situation-timeline-label{color:var(--text-mid)}
.vx-situation-timeline-when{color:var(--text-muted);font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;text-align:right;white-space:nowrap}
.vx-situation-status{display:inline-block;padding:2px 10px;border-radius:999px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}
.vx-situation-status-ok{background:var(--green-pale,rgba(44,74,62,.08));color:var(--green)}
.vx-situation-status-soon{background:#FCF3DC;color:var(--gold-deep,#A07840)}
.vx-situation-status-urgent{background:#FCE9D8;color:var(--amber,#C4621A)}
.vx-situation-status-over{background:#FBE5E5;color:var(--danger,#C0392B)}
.vx-situation-fillin{display:inline-block;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;color:var(--green);text-decoration:underline dotted;cursor:pointer}

/* Pipeline v2 — Hidden-costs primer (Step 14)
   Disclosure panel listing the costs vendors typically don't volunteer.
   Closed by default on first visit; opens when any deep question on the
   card is marked status='deflected' (wired in Step 17). */
.vx-hc-primer{background:#FAF7F2;border:1px solid rgba(44,74,62,.12);border-radius:var(--radius-lg,10px);padding:0;margin:0 0 20px;font-family:var(--ff-b,'DM Sans',sans-serif)}
.vx-hc-primer>summary{list-style:none;cursor:pointer;padding:14px 18px;display:flex;align-items:center;gap:10px;font-size:.78rem;font-weight:600;color:var(--gold-deep,#A07840);font-family:var(--ff-m,'DM Mono',monospace);letter-spacing:.06em;text-transform:uppercase}
.vx-hc-primer>summary::-webkit-details-marker{display:none}
.vx-hc-primer>summary::before{content:'▸';display:inline-block;transition:transform .18s ease;color:var(--gold-deep,#A07840);font-size:.7rem}
.vx-hc-primer[open]>summary::before{transform:rotate(90deg)}
.vx-hc-primer-body{padding:0 18px 16px}
.vx-hc-primer-intro{font-size:.82rem;line-height:1.55;color:var(--text-mid,#5b6a64);margin:0 0 12px}
.vx-hc-primer-list{display:grid;grid-template-columns:1fr auto;gap:8px 18px;font-size:.86rem}
.vx-hc-primer-label{color:var(--ink,#1c1c1c);font-weight:500}
.vx-hc-primer-range{color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;text-align:right;white-space:nowrap}

/* Pipeline v2 — Fast-pass / Scheduled-call tabs (Step 16) +
   per-question status buttons (Step 17). Layered onto the existing
   renderInterview output for situationTemplate categories. */
.vx-tier-tabs{display:flex;border-bottom:1px solid rgba(44,74,62,.12);margin:18px 0 8px;gap:0}
.vx-tier-tab{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:600;color:var(--text-muted,#88928d);padding:10px 20px;cursor:pointer;border:none;background:none;border-bottom:2px solid transparent;transition:color .15s,border-color .15s;letter-spacing:.01em}
.vx-tier-tab.is-active{color:var(--green,#2C4A3E);border-bottom-color:var(--green,#2C4A3E)}
.vx-tier-tab:hover:not(.is-active){color:var(--ink,#1c1c1c)}
.vx-tier-tab-count{display:inline-block;margin-left:8px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;color:var(--text-muted,#88928d);background:rgba(44,74,62,.06);border-radius:999px;padding:1px 8px;letter-spacing:0;font-weight:500}
.vx-tier-tab.is-active .vx-tier-tab-count{background:rgba(200,169,110,.18);color:var(--gold-deep,#A07840)}
.vx-tier-mode-fast .question-row[data-tier="deep"],
.vx-tier-mode-fast .question-row[data-tier="nice"],
.vx-tier-mode-deep .question-row[data-tier="fast"],
.vx-tier-mode-deep .question-row[data-tier="nice"],
.vx-tier-mode-nice .question-row[data-tier="fast"],
.vx-tier-mode-nice .question-row[data-tier="deep"]{display:none !important}
.question-row[data-risk="high"]{border-left:3px solid var(--gold,#C8A96E);padding-left:12px;margin-left:-15px}
.vx-q-actions{display:flex;gap:10px;align-items:center;margin-top:6px;font-size:.78rem}
.vx-q-vague,.vx-q-na{background:none;border:1px solid rgba(44,74,62,.18);border-radius:4px;padding:3px 9px;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted,#88928d);transition:color .15s,border-color .15s,background .15s}
.vx-q-vague:hover{color:var(--amber,#C4621A);border-color:var(--amber,#C4621A)}
.vx-q-vague.is-set{color:var(--amber,#C4621A);border-color:var(--amber,#C4621A);background:rgba(196,98,26,.06)}
.vx-q-na:hover{color:var(--text-mid,#5b6a64);border-color:rgba(44,74,62,.4)}
.vx-q-na.is-set{color:var(--text-muted,#88928d);border-color:rgba(44,74,62,.3);background:rgba(44,74,62,.05);text-decoration:line-through}
.vx-q-status-pill{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:2px 8px;border-radius:999px;margin-left:6px;color:var(--text-muted,#88928d)}
.vx-q-status-pill.is-deflected{background:#FCE9D8;color:var(--amber,#C4621A)}
.vx-q-status-pill.is-na{background:rgba(44,74,62,.08);color:var(--text-muted,#88928d)}
.vx-q-status-pill.is-confirmed{background:rgba(44,74,62,.08);color:var(--green,#2C4A3E)}

/* First-visit gate (Step 15) */
.vx-first-visit{background:#fff;border:1px solid rgba(44,74,62,.12);border-left:3px solid var(--gold,#C8A96E);border-radius:0 var(--radius-lg,10px) var(--radius-lg,10px) 0;padding:24px 28px;margin:0 0 24px;text-align:center}
.vx-first-visit h3{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.5rem;font-weight:400;color:var(--green,#2C4A3E);margin:0 0 8px}
.vx-first-visit p{font-size:.9rem;color:var(--text-mid,#5b6a64);margin:0 0 18px;line-height:1.55}
.vx-first-visit-ctas{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
.vx-fv-cta{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;font-weight:500;padding:10px 18px;border-radius:8px;cursor:pointer;border:1px solid var(--green,#2C4A3E);background:var(--green,#2C4A3E);color:#fff;transition:opacity .15s}
.vx-fv-cta:hover{opacity:.9}
.vx-fv-cta.vx-fv-cta-secondary{background:#fff;color:var(--green,#2C4A3E)}

/* Pipeline v2 Step 19 — vendor card grid (Stage 1 enrichment view).
   Presented above the legacy comparison table for situationTemplate
   categories. Renders shallow facts only; "More about this vendor →"
   scrolls to and highlights the deep comparison row. */
.vx-vendor-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;margin:18px 0 24px}
.vx-vendor-card{background:#fff;border:1px solid rgba(44,74,62,.12);border-radius:var(--radius-lg,10px);padding:18px;display:flex;flex-direction:column;gap:8px;transition:border-color .15s,box-shadow .15s}
.vx-vendor-card:hover{border-color:rgba(200,169,110,.5);box-shadow:0 4px 14px rgba(44,74,62,.06)}
.vx-vendor-card-empty{background:#FAF7F2;border-style:dashed;color:var(--text-muted,#88928d);align-items:center;justify-content:center;text-align:center;font-size:.82rem;min-height:140px}
.vx-vendor-card-name{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.18rem;font-weight:500;color:var(--green,#2C4A3E);line-height:1.2}
.vx-vendor-card-meta{font-size:.78rem;color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace);letter-spacing:.02em}
/* 2026-06-09 (Stephen — fit-ranking why-card) — the transparent "why this
   vendor ranked for you" line: ★ rating · in your band · matches your style.
   The visible, un-buyable anti-Knot signal. */
.vx-vendor-card-fit{font-size:.72rem;color:var(--gold-deep,#A07840);font-family:var(--ff-m,'DM Mono',monospace);letter-spacing:.02em;line-height:1.4;margin-top:1px}
/* 2026-06-10 (fit-ranking slice 3) — "Known for" line: vendor specialty
   harvested from the Compare-enrichment Claude call. Quieter than the ✦
   why-line (sage, not gold) so it reads as a vendor attribute, not a ranking
   reason. Only renders once a vendor has been researched. */
.vx-vendor-card-known{font-size:.72rem;color:var(--green-mid,#3a6b59);font-family:var(--ff-b,'DM Sans',sans-serif);font-style:italic;line-height:1.4;margin-top:3px}
.vx-vendor-card-blurb{font-size:.86rem;color:var(--ink,#1c1c1c);line-height:1.5;flex:1}
.vx-vendor-card-tags{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px}
.vx-vendor-card-tag{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:3px 8px;border-radius:999px;background:rgba(44,74,62,.06);color:var(--text-mid,#5b6a64)}
.vx-vendor-card-tag.is-price{background:rgba(200,169,110,.15);color:var(--gold-deep,#A07840)}
.vx-vendor-card-actions{display:flex;gap:8px;margin-top:8px}
.vx-vendor-card-more{flex:1;font-size:.78rem;font-weight:500;color:var(--green,#2C4A3E);background:none;border:1px solid rgba(44,74,62,.18);border-radius:6px;padding:6px 10px;cursor:pointer;transition:background .15s,border-color .15s}
.vx-vendor-card-more:hover{background:rgba(44,74,62,.04);border-color:var(--green,#2C4A3E)}
.vx-vendor-card.is-shortlisted{border-color:var(--gold,#C8A96E);background:#FFFCF5}
.vx-vendor-card-shortlist{font-size:.72rem;color:var(--text-muted,#88928d);background:none;border:none;cursor:pointer;padding:0;text-decoration:underline dotted}
.vx-vendor-card-shortlist.is-set{color:var(--gold-deep,#A07840);text-decoration:none}
@keyframes vxRowFlash{0%{background:rgba(200,169,110,.18)}100%{background:transparent}}
.ct-row.vx-row-flash{animation:vxRowFlash 1.5s ease-out}

/* Pipeline v2 — Compare → Personalize card. Budget-pattern collapsible
   that holds the search drivers (ZIP, radius, filters) + the
   Search-my-top-5 CTA. Open by default first visit; auto-collapses
   to a banner once the first search returns. */
.vx-cmp-personalize{margin:0 0 20px}
.vx-cmp-personalize.is-open{background:#fff;border:1px solid rgba(44,74,62,.12);border-radius:var(--radius-lg,10px);padding:22px 24px;box-shadow:0 2px 12px rgba(44,74,62,.04)}
.vx-cmp-pers-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px}
.vx-cmp-pers-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin-bottom:4px;font-weight:500}
.vx-cmp-pers-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.45rem;font-weight:400;color:var(--green,#2C4A3E);line-height:1.15}
.vx-cmp-pers-toggle{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;color:var(--text-mid,#5b6a64);background:none;border:1px solid rgba(44,74,62,.18);border-radius:999px;padding:6px 14px;cursor:pointer;transition:color .15s,border-color .15s,background .15s}
.vx-cmp-pers-toggle:hover{color:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E);background:rgba(44,74,62,.04)}
.vx-cmp-pers-toggle.is-open-btn{color:#fff;background:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E)}
.vx-cmp-pers-toggle.is-open-btn:hover{background:var(--green-mid,#3a5e4f)}
.vx-cmp-pers-body{display:block}
.vx-cmp-pers-help{font-size:.86rem;color:var(--text-mid,#5b6a64);line-height:1.5;margin:0 0 14px}
.vx-cmp-pers-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:14px}
@media(max-width:600px){.vx-cmp-pers-grid{grid-template-columns:1fr}}
.vx-cmp-pers-label{display:block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted,#88928d);margin:0 0 6px;font-weight:500}
/* 2026-06-09 (Stephen) — uniform box model + height so the Style <select>
   matches the postcode/radius/guest <input>s exactly (native selects and
   number inputs render at different heights/widths otherwise). */
.vx-cmp-pers-input{width:100%;box-sizing:border-box;height:40px;padding:9px 12px;border:1px solid rgba(44,74,62,.2);border-radius:6px;background:#FAF7F2;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;line-height:1.2;color:var(--ink,#1c1c1c);transition:border-color .15s,background .15s}
.vx-cmp-pers-input:focus{outline:none;border-color:var(--green,#2C4A3E);background:#fff}
/* Normalize the native select chrome so its height/width line up with the
   inputs; restore a custom caret since appearance:none removes the default. */
select.vx-cmp-pers-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding-right:30px;background-image:url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'10'%20height%3D'6'%3E%3Cpath%20d%3D'M1%201l4%204%204-4'%20stroke%3D'%237a7468'%20stroke-width%3D'1.5'%20fill%3D'none'%2F%3E%3C%2Fsvg%3E");background-repeat:no-repeat;background-position:right 11px center}
.vx-cmp-pers-filters{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:14px}
.vx-cmp-pers-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:6px}
/* 2026-04-29: defensive hover styling for the Search button inside the
   Personalize card. The legacy .btn-next sage-dark hover background was
   getting stomped by an inherited hover rule when nested inside the
   personalize card's white background, making the button look like it
   "disappeared" on hover. Re-pinning explicit colors. */
.vx-cmp-pers-actions .btn-next{background:var(--green,#2C4A3E);color:#fff;border:none;border-radius:999px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;font-weight:500;padding:11px 24px;cursor:pointer;transition:background .15s,transform .15s,box-shadow .15s}
.vx-cmp-pers-actions .btn-next:hover{background:var(--green-mid,#3a5e4f);color:#fff;transform:translateY(-1px);box-shadow:0 4px 12px rgba(44,74,62,.18)}
.vx-cmp-pers-actions .btn-next:active{transform:translateY(0);box-shadow:0 2px 6px rgba(44,74,62,.12)}
.vx-cmp-pers-actions .btn-pdf-outline{background:#fff;color:var(--green,#2C4A3E);border:1px solid var(--green,#2C4A3E);border-radius:999px;padding:10px 18px;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;transition:background .15s}
.vx-cmp-pers-actions .btn-pdf-outline:hover{background:var(--green-pale,rgba(44,74,62,.08));color:var(--green,#2C4A3E)}
/* Collapsed-banner state — Budget's "PROFILE SETUP HIDDEN" pattern. */
.vx-cmp-personalize.is-collapsed{background:linear-gradient(135deg,var(--green,#2C4A3E),var(--green-mid,#3a5e4f));border-radius:var(--radius-lg,10px);padding:14px 22px;color:#fff}
.vx-cmp-pers-banner{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.vx-cmp-pers-banner-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--gold-light,#E8D5B0);margin-bottom:2px;font-weight:600}
.vx-cmp-pers-banner-text{font-size:.92rem;color:#fff;line-height:1.4}
.vx-cmp-personalize.is-collapsed .vx-cmp-pers-toggle{background:rgba(255,255,255,.14);color:#fff;border-color:rgba(255,255,255,.3)}
.vx-cmp-personalize.is-collapsed .vx-cmp-pers-toggle:hover{background:rgba(255,255,255,.24);border-color:rgba(255,255,255,.5)}

/* Pipeline v2 — Compare grid (curated table). Replaces the legacy
   wide-table + the v2 card-grid for situationTemplate categories.
   Criteria-rows × 5 vendor-columns. Three sections (From Google /
   Shop info / Hidden costs). MUST tag highlights load-bearing rows;
   "—" is a feature not a defect; Tier A pre-fill cells cite source. */
.vx-cmp-table{background:#fff;border:1px solid rgba(44,74,62,.12);border-radius:var(--radius-lg,10px);overflow:hidden;box-shadow:0 4px 18px rgba(44,74,62,.05);font-family:var(--ff-b,'DM Sans',sans-serif)}
.vx-cmp-head{display:grid;grid-template-columns:240px repeat(5,1fr);background:linear-gradient(135deg,var(--green,#2C4A3E),var(--green-mid,#3a5e4f));color:#fff;position:sticky;top:0;z-index:5}
.vx-cmp-head-criterion{padding:14px 16px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;opacity:.75;display:flex;align-items:flex-end}
.vx-cmp-head-vendor{padding:12px 14px 11px;border-left:1px solid rgba(255,255,255,.12);position:relative;display:flex;flex-direction:column;gap:3px;min-height:62px;align-items:center;text-align:center}
.vx-cmp-head-vendor.is-empty{opacity:.45}
.vx-cmp-head-vendor-name{font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;font-weight:600;color:#fff;padding-right:16px}
.vx-cmp-head-vendor-density{font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;letter-spacing:.04em;color:var(--gold-light,#E8D5B0);margin-top:2px;font-weight:600}
.vx-cmp-density-check{margin-left:2px}
.vx-cmp-hide-btn{position:absolute;top:8px;right:8px;background:rgba(255,255,255,.08);border:none;color:rgba(255,255,255,.7);width:22px;height:22px;border-radius:50%;cursor:pointer;font-size:.72rem;line-height:1;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}
.vx-cmp-hide-btn:hover{background:rgba(255,255,255,.18);color:#fff}
/* 2026-05-12 — Why? + ✕ action row on v2 compare header. Stacks BELOW
   the vendor name (not absolute) so a longer "Why?" pill doesn't overlap
   the "VENDOR N" label. Compact pill style matched to the dark green
   header band so the visual reads cohesive. */
.vx-cmp-head-actions{display:flex;gap:6px;align-items:center;justify-content:center;margin-top:4px}
.vx-cmp-head-actions .vx-cmp-hide-btn{position:static;width:22px;height:22px;flex-shrink:0}
.vx-cmp-why-btn{appearance:none;background:rgba(200,169,110,.22);border:1px solid rgba(200,169,110,.55);border-radius:999px;padding:3px 10px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:11px;font-weight:500;line-height:1.1;letter-spacing:.04em;color:#fff;cursor:pointer;transition:background .15s,border-color .15s,transform .12s;white-space:nowrap}
.vx-cmp-why-btn:hover{background:rgba(200,169,110,.40);border-color:#C8A96E;transform:translateY(-1px)}
/* 2026-05-12 — Inquiry status pill (B.5 UI). Sits inside .vx-cmp-head-vendor
   between the "VENDOR N" label and the action row. Color encodes the
   workflow state: idle (not_contacted) → in-flight (emailed) → quoting
   → site-visit → terminal (signed/declined). Click opens a small popover. */
.vx-cmp-inquiry-pill{display:inline-flex;align-items:center;gap:5px;margin-top:6px;padding:3px 9px;border-radius:999px;font-family:var(--ff-m,'DM Mono',monospace);font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;line-height:1.1;cursor:pointer;border:1px solid transparent;transition:background .15s,border-color .15s,transform .12s;white-space:nowrap}
.vx-cmp-inquiry-pill:hover{transform:translateY(-1px)}
/* 2026-05-23 — Belt-and-suspenders for #43. The JS render at line ~9737
   already gates the pill on `inqStatus !== 'not_contacted'`, but
   Stephen reported the pill still showing in a fresh Safari private
   session after the JS fix deployed (deployed JS confirmed via curl).
   Whatever render path is bypassing the JS gate, this CSS catches it:
   any pill emitted with data-status="not_contacted" is hidden via
   display:none regardless of which renderer produced it. */
.vx-cmp-inquiry-pill[data-status="not_contacted"]{display:none !important}
/* 2026-05-23 — Corridor badge for premium hotel-route search picks.
   Renders under the vendor name in Compare header when corridor metadata
   is present on the vendor. Gold accent matches the gold CTA. Title
   attribute carries the full Opus narration so hover surfaces it. */
.vx-cmp-corridor-badge{display:inline-block;margin-top:4px;padding:3px 8px;border-radius:999px;font-family:var(--ff-m,'DM Mono',monospace);font-size:9.5px;font-weight:600;letter-spacing:.04em;line-height:1.25;background:rgba(200,169,110,.16);border:1px solid rgba(200,169,110,.5);color:#f3e0bb;cursor:help;max-width:100%;text-align:center;white-space:normal}
.vx-cmp-inquiry-pill[data-status="emailed"]{background:rgba(110,160,200,.22);border-color:rgba(110,160,200,.55);color:#cfe1f3}
.vx-cmp-inquiry-pill[data-status="quote_received"]{background:rgba(200,169,110,.24);border-color:rgba(200,169,110,.62);color:#f3e0bb}
.vx-cmp-inquiry-pill[data-status="site_visit_scheduled"]{background:rgba(180,140,200,.22);border-color:rgba(180,140,200,.55);color:#e6d4f0}
.vx-cmp-inquiry-pill[data-status="signed"]{background:rgba(120,170,130,.32);border-color:rgba(120,170,130,.7);color:#dff0e0}
.vx-cmp-inquiry-pill[data-status="declined"]{background:rgba(170,90,90,.22);border-color:rgba(170,90,90,.5);color:#f0d4d4;text-decoration:line-through;text-decoration-thickness:1px}
.vx-cmp-inquiry-pill .vx-cmp-inquiry-quote{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:9.5px;font-weight:500;letter-spacing:.02em;text-transform:none;opacity:.85;margin-left:2px}
.vx-cmp-inquiry-pop{position:fixed;z-index:9999;min-width:230px;max-width:280px;background:#fff;border:1px solid rgba(44,74,62,.18);border-radius:12px;box-shadow:0 16px 36px rgba(0,0,0,.18);padding:10px;font-family:var(--ff-b,'DM Sans',sans-serif)}
.vx-cmp-inquiry-pop-q{font-family:var(--ff-m,'DM Mono',monospace);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--green,#2C4A3E);padding:2px 4px 8px;border-bottom:1px solid rgba(44,74,62,.08);margin-bottom:8px}
.vx-cmp-inquiry-pop-opt{display:flex;align-items:center;justify-content:space-between;width:100%;background:#fff;border:1px solid rgba(44,74,62,.12);border-radius:8px;padding:8px 10px;margin:4px 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:12.5px;color:var(--ink,#1a1f1c);cursor:pointer;text-align:left;transition:background .12s,border-color .12s}
.vx-cmp-inquiry-pop-opt:hover{background:rgba(200,169,110,.10);border-color:rgba(200,169,110,.45)}
.vx-cmp-inquiry-pop-opt.is-current{background:rgba(44,74,62,.06);border-color:rgba(44,74,62,.25);font-weight:600;cursor:default}
.vx-cmp-inquiry-pop-opt .vx-cmp-inquiry-pop-tick{font-family:var(--ff-m,'DM Mono',monospace);font-size:10px;opacity:.55}
.vx-cmp-inquiry-pop-quote{display:flex;align-items:center;gap:6px;margin:8px 4px 4px;padding:6px 8px;background:#FBF3F3;border:1px dashed rgba(170,90,90,.35);border-radius:8px;font-size:11.5px;color:var(--ink,#1a1f1c)}
.vx-cmp-inquiry-pop-quote input{flex:1;border:1px solid rgba(44,74,62,.18);border-radius:6px;padding:4px 8px;font-family:inherit;font-size:12px;min-width:0}
.vx-cmp-inquiry-pop-foot{display:flex;justify-content:space-between;align-items:center;margin-top:6px;padding-top:6px;border-top:1px solid rgba(44,74,62,.08)}
.vx-cmp-inquiry-pop-close{background:none;border:none;font-family:var(--ff-m,'DM Mono',monospace);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-muted,#6c7570);cursor:pointer;padding:2px 6px}
.vx-cmp-inquiry-pop-close:hover{color:var(--ink,#1a1f1c)}
/* 2026-05-22 — Tighter section-header padding per Stephen's mobile
   feedback. The "FROM GOOGLE (FACTUAL)" / "VENUE INFO" / "HIDDEN COSTS"
   dividers ate vertical space without earning it on small viewports.
   Halved the vertical padding; mobile gets even tighter. */
.vx-cmp-section-header{padding:7px 18px 6px;background:rgba(44,74,62,.04);border-top:1px solid rgba(44,74,62,.1);border-bottom:1px solid rgba(44,74,62,.06)}
@media (max-width: 768px){.vx-cmp-section-header{padding:5px 12px 4px}}
.vx-cmp-section-header.is-google{background:rgba(44,74,62,.05)}
.vx-cmp-section-header.is-shop{background:#FFFCF5}
.vx-cmp-section-header.is-cost{background:#FBF3F3}
/* 2026-05-22 — Section title scoped INSIDE .vx-cmp-section-header
   only — the bare .vx-cmp-section-title class is also used by
   DocCompare results (Cormorant italic 1.25rem) at line ~4827.
   Stephen's feedback: match the phase-tab register on the Vendor+
   Compare card. DocCompare keeps its own editorial styling. */
.vx-cmp-section-header .vx-cmp-section-title{font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.14em;text-transform:uppercase;color:var(--green,#2C4A3E);margin-bottom:2px;font-weight:500;opacity:.85;font-style:normal}
.vx-cmp-section-header.is-cost .vx-cmp-section-title{color:var(--rose,#C97B6A)}
.vx-cmp-section-prose{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:.92rem;line-height:1.45;color:var(--text-mid,#5b6a64);font-style:italic}
.vx-cmp-row{display:grid;grid-template-columns:240px repeat(5,1fr);border-bottom:1px solid rgba(44,74,62,.06);transition:background .15s;align-items:stretch}
.vx-cmp-row:hover{background:#FAF7F2}
.vx-cmp-row:last-child{border-bottom:none}
/* 2026-05-14 — Weight 450 was non-standard half-step. Promoted to
   500 which is the brand's utility-label weight (matches .pain-card h3,
   .couple-badge-text, .sn-name). */
/* ⚑ align-items:center SINCE 2026-08-21. Stephen: "could you center the 'Save
   to contact' in the cell so it matches the other row titles."
   Every label was flex-START, which is invisible on a short row because the
   label fills it — and obvious on a TALL one. The Save-to-contact row is tall
   because its cells hold a button, and `.vx-cmp-cell` centres its own content,
   so the button sat centred while the label it belonged to clung to the top.
   Centring the label makes short rows identical and tall rows correct. */
.vx-cmp-row-label{padding:11px 16px;font-size:.84rem;color:var(--ink,#1c1c1c);background:rgba(44,74,62,.025);border-right:1px solid rgba(44,74,62,.06);display:flex;align-items:center;line-height:1.35;font-weight:500}
.vx-cmp-cell{padding:11px 14px;border-left:1px solid rgba(44,74,62,.06);font-size:.86rem;color:var(--ink,#1c1c1c);line-height:1.4;display:flex;flex-direction:column;gap:3px;align-items:center;text-align:center;justify-content:flex-start}
.vx-cmp-cell.is-blank{background:rgba(44,74,62,.015);justify-content:center}
.vx-cmp-cell-dash{color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace);font-size:1rem;cursor:help}
/* Uniform cell-content cap: every value gets the same max-height + fade
   mask. Short values fit inside; long values fade out at the bottom.
   Keeps row rhythm consistent across vendors regardless of content
   length variance. Hover/click reveals full text via the title attr. */
.vx-cmp-cell-value{word-break:break-word;max-height:6.4em;overflow:hidden;-webkit-mask-image:linear-gradient(to bottom, black 80%, transparent 100%);mask-image:linear-gradient(to bottom, black 80%, transparent 100%);width:100%}
/* PROVENANCE LIVES IN THE SOURCE PILL. Two earlier placements were wrong in
   opposite directions: a caption under every cell buried the grid's content
   under its own footnotes, and hoisting it to the column header produced
   three cramped lines of 8px type under a vendor's name. The claim-to-source
   link is legally load-bearing, so it moved somewhere with room for whole
   sentences rather than being trimmed until it fitted.

   What stays in the grid is the cheapest possible marker: a sourced value
   carries the faintest dotted underline, and its exact URL is on hover. */
.vx-cmp-cell-value.is-sourced{border-bottom:1px dotted rgba(44,74,62,.18)}
@media (max-width:1100px){
  .vx-cmp-head,.vx-cmp-row{grid-template-columns:180px repeat(5,1fr)}
  .vx-cmp-head-criterion,.vx-cmp-row-label{padding-left:10px;padding-right:10px;font-size:.78rem}
  .vx-cmp-cell{padding:9px 8px;font-size:.78rem}
}
/* 2026-08-08 (Stephen) — ROTATE HINT. At ≤780px the grid is a 920px scroller,
   so a 390px phone shows the 180px criteria column plus about one and a half
   vendors. Landscape roughly triples that. The hint is pure CSS: it exists only
   in portrait, so rotating makes it disappear on its own — no listener, no
   resize handler, nothing to leak. Hidden by default and revealed by the
   portrait query below, so every wider viewport never sees it. */
.vx-cmp-rotate{display:none}
@media (max-width:780px) and (orientation:portrait){
  .vx-cmp-rotate{
    display:flex;align-items:center;gap:10px;
    margin:0 0 10px;padding:9px 12px;
    background:rgba(200,169,110,.09);
    border:1px solid rgba(200,169,110,.28);
    border-radius:8px;
    font-family:var(--ff-b,'DM Sans',sans-serif);
    font-size:.78rem;line-height:1.45;color:var(--text-mid,#4A4A4A)}
  .vx-cmp-rotate.is-dismissed{display:none}
  .vx-cmp-rotate-icon{flex:0 0 auto;font-size:1rem;line-height:1}
  .vx-cmp-rotate-txt{flex:1 1 auto;min-width:0}
  .vx-cmp-rotate-x{flex:0 0 auto;background:none;border:none;cursor:pointer;
    padding:2px 4px;margin:-2px -4px -2px 0;line-height:1;
    font-size:.95rem;color:var(--text-muted,#88928d)}
}
@media (max-width:780px){
  .vx-cmp-table{overflow-x:auto;display:block;-webkit-overflow-scrolling:touch}
  .vx-cmp-head,.vx-cmp-row{min-width:920px}
  /* ⚑ 2026-09-07 — ONE WHOLE VENDOR HAS TO FIT BESIDE THE FROZEN COLUMN, and
     until now it did not. The criteria column inherits 180px from the ≤1100px
     rule above; the scroller is 920px, so each of the five vendors gets
     (920-180)/5 = 148px. MEASURED IN CHROMIUM, not reasoned about:

        viewport   criteria   vendor 1   left for vendor 2
        320px      180 (56%)  148        -8px   ← vendor 1 does not even fit
        360px      180 (50%)  148        32px
        390px      180 (46%)  148        62px

     On an iPhone SE the frozen column plus one vendor is EIGHT PIXELS WIDER
     than the screen, so there is no scroll position that shows a single
     complete vendor. On a 390px phone the criteria labels eat 46% of the
     glass. This is a comparison table on which you cannot compare.

     The weekend module hit the same wall and solved it by giving the sticky
     column only what its labels need (104-118px there). Same fix here, sized
     the same way — by rendering the app's own longest criteria label
     ("Distance to your first stop", 27 characters) and finding the width at
     which it stops fitting. It still does not clip at 104px, so 116px carries
     real headroom rather than sitting on the edge:

        viewport   criteria   vendor 1   left for vendor 2
        320px      116 (36%)  161        43px
        390px      116 (30%)  161        113px

     Zero labels and zero values clip at any width from 320px to 768px, and
     the row height is untouched — 72px was tried and clipped 15 of 30 values,
     so the 84px uniform height from 2026-05-15 is load-bearing and stays. */
  .vx-cmp-head,.vx-cmp-row{grid-template-columns:116px repeat(5,1fr)}
  .vx-cmp-head-criterion,
  .vx-cmp-row-label{padding-left:8px;padding-right:8px;font-size:.74rem;line-height:1.25}
  /* 2026-05-15 — Item 5: freeze the criteria column so the user can
     swipe horizontally to read one vendor at a time without losing the
     row labels. The cream background ensures vendor cells don't bleed
     through during scroll. */
  .vx-cmp-head-criterion,
  .vx-cmp-row-label{
    position:sticky;
    left:0;
    z-index:3;
    box-shadow:1px 0 0 rgba(44,74,62,.10), 4px 0 8px rgba(44,74,62,.05);
  }
  .vx-cmp-row-label{background:var(--cream,#FAF7F2)}
  /* ⚑ 2026-08-12 — SAY THERE IS MORE. The criteria column has been frozen since
     2026-05-15, which makes horizontal reading bearable, but nothing ever said
     the table continued past the edge — so five vendor columns read as five
     vendors. A fade on the right whenever there is more to scroll, gone the
     moment there is not. Pointer-events none: it is a signal, never a target. */
  .vx-cmp-table{position:relative}
  .vx-cmp-table.vx-cmp-more::after{
    content:'';position:sticky;right:0;top:0;float:right;
    width:26px;height:100%;margin-left:-26px;pointer-events:none;
    background:linear-gradient(to right,rgba(250,247,242,0),rgba(44,74,62,.10));
  }
  .vx-cmp-head-criterion{background:linear-gradient(135deg,var(--green,#2C4A3E),var(--green-mid,#3a5e4f))}
  /* ⚑ 2026-09-16 — THE SECTION BANDS SCROLLED AWAY WITH THE TABLE (Stephen).
     `.vx-cmp-head` and `.vx-cmp-row` both carry min-width:920px, so they span
     the scroller; the section headers never did. Two consequences on a phone,
     and only the second one had been noticed:

       · the band is one viewport wide, so scrolling right runs it out and the
         rows below sit under no band at all;
       · the title ("What a customer can look up") travels left with the scroll
         and is gone by the second operator — which is exactly when a reader
         needs to know which section they are in.

     The frozen criteria column has been sticky since 2026-05-15; this is the
     same fix one level up. The band gets the scroller's width so it runs the
     whole way, and the TITLE is what sticks — pinned at the same 8px the row
     labels below it use, so the section name and the criteria it heads stay in
     one vertical line however far the table is scrolled.

     ⚑ display:inline-block IS LOAD-BEARING. `position:sticky;left:8px` on a
     full-width block cannot move: the box already spans its container, so
     there is no room to shift into and the title scrolls away exactly as
     before — green, and unchanged. It has to be shrink-wrapped first. */
  .vx-cmp-section-header{min-width:920px;padding-left:8px;padding-right:8px}
  .vx-cmp-section-header .vx-cmp-section-title{
    position:sticky;
    left:8px;
    display:inline-block;
    max-width:calc(100vw - 32px);
  }
}

/* 2026-05-15 — Item 5: uniform row height across all data rows so
   visual weighting is consistent on every vendor + every criteria. The
   existing .vx-cmp-cell-value mask fades content that overflows. The
   header row (.vx-cmp-head) keeps its variable height for action pills. */
.vx-cmp-row{min-height:84px;max-height:84px}
.vx-cmp-row-label,
.vx-cmp-cell{
  min-height:84px;
  max-height:84px;
  overflow:hidden;
}
.vx-cmp-cell-value{
  max-height:calc(84px - 22px);
}

/* Step-bar wrapper — third tier of the fixed top chrome. Profile bar
 is always visible (signed-in OR signed-out), so the step-bar always
 sits at top:110px (header 62 + profile bar ~48 = 110). */
.step-bar-fixed{position:fixed;top:129px;left:0;right:0;z-index:70;background:rgba(250,247,242,1);/* backdrop-filter dropped 2026-07-21 — inert + iPadOS tap-swallow hazard; see header */border-bottom:1px solid rgba(44,74,62,.1);min-height:54px;display:flex;align-items:center;padding:0 2rem;padding-left:max(2rem,env(safe-area-inset-left));padding-right:max(2rem,env(safe-area-inset-right))}
.step-bar-fixed .step-bar{max-width:900px;margin:0 auto;width:100%}

/* ══════════════════════════════════════════════════════════════════════
   --vx-chrome-bottom — WHERE THE FIXED CHROME ENDS. One number, four
   breakpoints, every consumer.
   ──────────────────────────────────────────────────────────────────────
   ⚑ MEASURED IN A BROWSER, NOT DERIVED FROM THE COMMENTS. The comments
   describing this stack said header 0-74 and chrome bottom 183. The header
   is 78 and the chrome bottom is 183 only above 768px. Every other
   breakpoint disagreed with the prose, and four separate things had each
   hardcoded their own guess:

     width   chrome ends   budget strip pinned at   page content started at
     834     183           183  ✓                   192  ✓
     700     177           183  → 6px gap           186  ✓
     560      72            61  → 11px CLIPPED       64  → 8px under header
     390      58            53  → 5px CLIPPED        56  → 2px under header

   The 11px clip is the sliced bar in Stephen's 2026-08-11 screenshot: a
   sticky strip pinning ABOVE the bottom of an opaque fixed header slides
   under it and loses its top edge. The 8px is every mobile page, on every
   tab, since 2026-08-04.

   Each of those four numbers was maintained by hand, and the rule they had
   to track lived somewhere else. That is the actual defect; the pixels are
   symptoms. Now there is one declaration per breakpoint and everything
   reads it, so the next header change moves all of them together.

   ⚑ BELOW 601px BOTH BARS ARE display:none, so the chrome collapses to the
   header alone — which is why the number drops 177 → 72 rather than easing
   down. A formula that interpolated would be wrong at exactly one place.

   The env() terms mirror the header's own padding formula so a notched
   iPhone grows the offset with it; the constants are what measurement said,
   not what the old formulas assumed (they were 8px and 2px short).
   ══════════════════════════════════════════════════════════════════════ */
:root { --vx-chrome-bottom: 183px; }
@media (max-width:768px){ :root{ --vx-chrome-bottom: 177px } }
@media (max-width:600px){
 :root{ --vx-chrome-bottom: calc(max(13px, env(safe-area-inset-top, 0px) + 10px) + 59px) }
}
@media (max-width:480px){
 :root{ --vx-chrome-bottom: calc(max(10px, env(safe-area-inset-top, 0px) + 8px) + 48px) }
}

.bridge{padding-top:calc(11rem + 16px)}
.vx-pb-inner{max-width:900px;margin:0 auto;display:flex;align-items:center;gap:14px;width:100%}
.vx-pb-inner[hidden]{display:none}
.vx-pb-collapsed{max-width:900px;margin:0 auto;min-height:40px;display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%}
.vx-pb-collapsed[hidden]{display:none}
.vx-pb-hide,.vx-pb-show{appearance:none;background:transparent;color:var(--text-muted);border:0;font-family:var(--ff-m);font-size:.7rem;letter-spacing:.04em;cursor:pointer;padding:4px 6px;flex-shrink:0;align-self:center;text-decoration:underline;text-underline-offset:3px;transition:color .12s}
.vx-pb-hide:hover,.vx-pb-show:hover{color:var(--green)}

/* ── Wedding switcher ── */
.vx-ws-trigger{display:inline-flex;align-items:center;gap:6px;background:transparent;border:none;padding:0;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;font-weight:500;color:var(--text-mid);white-space:nowrap;flex-shrink:0;transition:color .15s}
.vx-ws-trigger[hidden]{display:none}
.vx-ws-trigger:hover{color:var(--green)}
.vx-ws-chevron{flex-shrink:0;transition:transform .18s;color:inherit;opacity:.6}
.vx-ws-trigger[aria-expanded="true"] .vx-ws-chevron{transform:rotate(180deg)}
.vx-ws-dropdown{position:absolute;top:calc(100% + 4px);left:max(2rem,env(safe-area-inset-left));min-width:260px;max-width:340px;background:var(--white,#fff);border:1px solid rgba(44,74,62,.13);border-radius:12px;box-shadow:0 8px 32px rgba(44,74,62,.13),0 2px 8px rgba(44,74,62,.06);z-index:200;overflow:hidden}
.vx-ws-item{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 16px;border-bottom:1px solid rgba(44,74,62,.07);transition:background .12s}
.vx-ws-item:last-child{border-bottom:none}
.vx-ws-item.is-active{background:rgba(44,74,62,.04)}
.vx-ws-item-info{display:flex;flex-direction:column;gap:2px;min-width:0}
.vx-ws-item-name{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:600;color:var(--ink,#1a2e24);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vx-ws-item-role{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted);letter-spacing:.02em}
.vx-ws-active-dot{width:8px;height:8px;border-radius:50%;background:var(--green);flex-shrink:0}
.vx-ws-switch-btn{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;font-weight:500;color:var(--green);background:transparent;border:1px solid rgba(44,74,62,.18);border-radius:6px;padding:4px 10px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:all .15s}
.vx-ws-switch-btn:hover{background:rgba(44,74,62,.06);border-color:var(--green)}
.vx-ws-footer{padding:10px 16px;border-top:1px solid rgba(44,74,62,.07)}
.vx-ws-join-btn{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;color:var(--text-muted);background:transparent;border:none;cursor:pointer;padding:0;transition:color .15s}
.vx-ws-join-btn:hover{color:var(--green)}
/* Planning spaces in-panel card */
.vx-planning-spaces-card{background:var(--cream);border:1px solid rgba(44,74,62,.1);border-radius:var(--radius-lg);padding:18px 20px;margin:0 0 18px}
.vx-planning-spaces-card legend{font-family:var(--ff-d);font-size:1rem;color:var(--green);font-weight:500}
.vx-planning-spaces-card legend em{font-style:italic;color:var(--gold)}
.vx-ws-panel-list{list-style:none;margin:10px 0 0;padding:0;border:1px solid rgba(44,74,62,.1);border-radius:8px;overflow:hidden;background:var(--white,#fff)}
.vx-ws-panel-list .vx-ws-item{padding:10px 14px}
.vx-ws-panel-list .vx-ws-item.is-active{background:rgba(44,74,62,.04)}
.vx-pb-label{display:inline-flex;align-items:center;align-self:center;gap:5px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;font-weight:500;color:var(--text-mid);white-space:nowrap;flex-shrink:0}
.vx-pb-star{color:var(--green);font-size:.95rem;line-height:1}
/* 2026-04-29: profile bar pills restyled as text-link nav matching the
   main step bar rhythm ("Insights | Budget | Research | Review"). Icons
   dropped, pill chrome removed. Separator pipes are CSS pseudo-elements
   on every pill except the first so the markup stays clean. */
.vx-pb-pills{display:flex;align-items:center;gap:0;flex:1;min-width:0;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.vx-pb-pills::-webkit-scrollbar{display:none}
.vx-pb-pill{appearance:none;display:inline-flex;align-items:center;background:transparent;color:var(--text-muted,#88928d);border:none;border-radius:0;padding:6px 14px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;font-weight:400;cursor:pointer;white-space:nowrap;transition:color .15s ease;flex-shrink:0;letter-spacing:.01em}
.vx-pb-pill:hover{color:var(--green,#2C4A3E)}
.vx-pb-pill:focus-visible{outline:2px solid var(--green,#2C4A3E);outline-offset:2px;border-radius:4px}
.vx-pb-pill.is-active{color:var(--green,#2C4A3E);font-weight:500}
.vx-pb-pill + .vx-pb-pill::before{content:"|";color:var(--border-g,#cdc5b6);margin-right:0;margin-left:0;font-weight:300;opacity:.7;align-self:center;padding:0 4px 0 0}
/* 2026-05-15 — "Update available" pill. Subtle gold treatment so it
   reads as an actionable signal without competing with the regular
   nav. `hidden` attr keeps it out of the layout entirely until a new
   service worker is waiting (set by _vxShowUpdatePill). The pulse
   animation is gentle — once on appearance, then static. */
.vx-pb-pill-update[hidden]{display:none !important}
.vx-pb-pill-update{color:var(--gold-deep,#A07840) !important;font-weight:500;cursor:pointer;animation:vxUpdatePillIn .42s var(--ease,cubic-bezier(.4,0,.2,1)) both}
.vx-pb-pill-update:hover{color:var(--gold,#C8A96E) !important}
@keyframes vxUpdatePillIn{
  0%{opacity:0;transform:translateY(-3px)}
  100%{opacity:1;transform:translateY(0)}
}
/* "Update available" modal — mirrors the lock-modal shape so it feels
   like a native part of Verdeaux's design language. */
.vx-update-modal-host{position:fixed;inset:0;z-index:9700;display:flex;align-items:center;justify-content:center;padding:18px;opacity:0;pointer-events:none;transition:opacity .22s}
.vx-update-modal-host.is-open{opacity:1;pointer-events:auto}
.vx-update-modal-backdrop{position:absolute;inset:0;background:rgba(28,28,28,.45);backdrop-filter:blur(2px);cursor:pointer}
.vx-update-modal{position:relative;width:100%;max-width:440px;background:#fff;border-radius:14px;padding:22px 24px 18px;box-shadow:0 20px 60px rgba(28,28,28,.25);transform:translateY(8px);transition:transform .22s var(--ease,cubic-bezier(.4,0,.2,1))}
.vx-update-modal-host.is-open .vx-update-modal{transform:translateY(0)}
.vx-update-modal-eyebrow{display:flex;align-items:center;justify-content:space-between;font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);font-weight:500;margin-bottom:8px}
.vx-update-modal-close{appearance:none;background:none;border:none;color:var(--text-muted,#88928d);font-size:.95rem;cursor:pointer;padding:2px 7px;border-radius:5px}
.vx-update-modal-close:hover{color:var(--ink,#1c1c1c);background:rgba(28,28,28,.05)}
.vx-update-modal-h{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-size:1.45rem;font-weight:400;color:var(--green,#2C4A3E);margin:0 0 10px;line-height:1.2}
.vx-update-modal-sub{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13.5px;line-height:1.55;color:var(--text-mid,#5b6a64);margin:0 0 16px}
.vx-update-modal-actions{display:flex;justify-content:flex-end;gap:10px;flex-wrap:wrap}
.vx-update-modal-cancel,.vx-update-modal-confirm{appearance:none;border-radius:999px;padding:9px 18px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,color .15s,transform .12s}
.vx-update-modal-cancel{background:#fff;color:var(--ink,#1c1c1c);border:1px solid rgba(44,74,62,.22)}
.vx-update-modal-cancel:hover{background:rgba(44,74,62,.04);border-color:rgba(44,74,62,.4)}
.vx-update-modal-confirm{background:var(--green,#2C4A3E);color:#fff;border:1px solid var(--green,#2C4A3E)}
.vx-update-modal-confirm:hover{background:#243d33;transform:translateY(-1px)}
.vx-update-modal-confirm:disabled{opacity:.7;cursor:wait;transform:none}

@media (max-width:768px){
 .vx-profile-bar{padding:0 14px}
 .vx-pb-label{display:none}
 .vx-pb-pill{font-size:12px;padding:5px 10px}
 .step-bar-fixed{padding-left:max(14px,env(safe-area-inset-left));padding-right:max(14px,env(safe-area-inset-right))}
}
@media (min-width:769px){
 .vx-pb-pills{gap:0}
}
@media (max-width:560px){
 /* 2026-04-29: text-link nav, no inner icon/info spans to hide. Keep the
    full label visible so couples can read the nav at any width. */
 .vx-pb-pill{font-size:11px;padding:4px 8px}
 .vx-pb-pill + .vx-pb-pill::before{padding:0 2px 0 0}
 .vx-pb-pill > span:not(.vx-pb-pill-icon):not(.vx-pb-info){display:inline}
 .vx-pb-pill{padding:4px;gap:0}
 .vx-pb-pills{display:none}
 .vx-pb-hide{display:none}
 .vx-pb-mobile-trigger{display:inline-flex}
 /* On mobile, collapse is meaningless — drawer IS the profile bar.
    Always show the expanded row (trigger only) and hide the collapsed strip. */
 #vxProfileBarCollapsed{display:none!important}
 #vxProfileBarExpanded{display:flex!important}
 /* Compact avatar circle — replaces the "Sign-out" pill on mobile */
 .header-greeting{display:none!important}
 .header-auth-btn.is-signed-in{width:34px!important;min-width:34px!important;height:34px!important;padding:0!important;border-radius:50%!important;font-size:0!important;line-height:34px!important;text-overflow:clip!important;overflow:hidden!important}
 .header-auth-btn.is-signed-in::after{content:attr(data-initial);font-size:.82rem;font-weight:600;font-family:var(--ff-b,'DM Sans',sans-serif);color:#fff;display:block;text-align:center;line-height:34px}
 /* Step bar → elegant tab strip on mobile */
 .step-bar-fixed{padding:0!important;border-bottom:1px solid rgba(44,74,62,.1)}
 .step-bar,.step-bar.has-ideas{display:flex!important;background:transparent!important;border:none!important;border-radius:0!important;overflow-x:auto!important;scrollbar-width:none!important;padding:0 4px!important;gap:0!important}
 .step-bar::-webkit-scrollbar{display:none}
 .step-divider{display:none!important}
 .sn-num{display:none!important}
 .sn-name{display:block!important;font-family:var(--ff-b,'DM Sans',sans-serif)!important;font-size:.75rem!important;font-weight:500!important;color:var(--text-muted,#888)!important;white-space:nowrap!important}
 .step-node{flex-shrink:0!important;padding:10px 14px!important;min-height:unset!important;border-radius:0!important;background:transparent!important;border-bottom:2px solid transparent!important;justify-content:center!important;gap:0!important;opacity:1!important}
 .step-node--current{background:transparent!important;border-bottom-color:var(--gold)!important}
 /* 2026-05-14 — Active state weight aligned with brand family — 600 → 500. */
 .step-node--current .sn-name{color:var(--green)!important;font-weight:500!important}
 .step-node--done .sn-name,.step-node--next .sn-name{display:block!important}
 .step-node--done .sn-name{color:var(--text-muted,#888)!important}
 .step-node--next .sn-name{color:rgba(44,74,62,.35)!important}
 .ideas-btn{flex-shrink:0!important;padding:10px 14px!important;min-height:unset!important;border-radius:0!important;background:transparent!important;border-bottom:2px solid transparent!important;gap:0!important}
 .ideas-btn-text{display:flex!important}
 .ideas-btn-name{font-family:var(--ff-b,'DM Sans',sans-serif)!important;font-size:.75rem!important;font-weight:500!important;color:var(--text-muted,#888)!important;white-space:nowrap!important}
 .ideas-chevron{display:none!important}
 .ideas-btn-icon{display:none!important}
 .ideas-btn.is-active{background:transparent!important;border-bottom-color:var(--gold)!important}
 .ideas-btn.is-active .ideas-btn-name,.ideas-btn.is-open .ideas-btn-name{color:var(--green)!important;font-weight:600!important}
 .ideas-btn.is-open{background:transparent!important}
}

/* ── Wedding Card Drawer (mobile ≤560px) ─────────────────────────── */
.vx-pb-mobile-trigger{display:none;align-items:center;gap:7px;flex:1;appearance:none;background:transparent;border:none;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;font-weight:500;color:var(--text-mid);padding:4px 0;justify-content:space-between}
.vx-pb-mobile-trigger-label{display:flex;align-items:center;gap:6px}
.vx-pb-mobile-chevron{transition:transform .22s ease;color:var(--text-muted);flex-shrink:0}
.vx-pb-mobile-trigger[aria-expanded="true"] .vx-pb-mobile-chevron{transform:rotate(180deg)}

.vx-wd-backdrop{position:fixed;inset:0;z-index:940;background:rgba(28,28,28,.38);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);opacity:0;pointer-events:none;transition:opacity .28s ease}
.vx-wd-backdrop.is-open{opacity:1;pointer-events:auto}

.vx-wd-drawer{position:fixed;top:0;right:0;bottom:0;z-index:950;width:min(320px,88vw);background:var(--cream,#FAF7F2);box-shadow:-6px 0 48px rgba(28,28,28,.2);transform:translateX(100%);transition:transform .32s cubic-bezier(.32,.72,0,1);display:flex;flex-direction:column;overflow:hidden;visibility:hidden}
.vx-wd-drawer.is-open{transform:translateX(0);visibility:visible}

.vx-wd-close{position:absolute;top:14px;right:14px;appearance:none;background:transparent;border:none;cursor:pointer;color:var(--text-muted);padding:8px;line-height:1;transition:color .15s;z-index:1}
.vx-wd-close:hover{color:var(--green)}

.vx-wd-card{padding:36px 24px 22px;background:linear-gradient(145deg,rgba(44,74,62,.055) 0%,rgba(200,169,110,.07) 100%);border-bottom:1px solid rgba(200,169,110,.22);flex-shrink:0}
.vx-wd-card-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.13em;text-transform:uppercase;color:var(--gold,#C8A96E);margin-bottom:10px}
.vx-wd-card-names{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.65rem;font-weight:400;color:var(--green,#2C4A3E);line-height:1.18;letter-spacing:.01em}
.vx-wd-card-names em{font-style:italic;color:var(--gold-deep,#A07840)}
.vx-wd-card-meta{margin-top:10px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted);display:flex;align-items:center;gap:8px;flex-wrap:wrap;line-height:1.4}
.vx-wd-card-dot{color:rgba(44,74,62,.25)}

.vx-wd-menu{flex:1;overflow-y:auto;padding:6px 0}
.vx-wd-item{display:flex;align-items:center;gap:14px;width:100%;appearance:none;background:transparent;border:none;border-bottom:1px solid rgba(44,74,62,.07);cursor:pointer;padding:17px 22px;text-align:left;transition:background .15s}
.vx-wd-item:last-child{border-bottom:none}
.vx-wd-item:hover,.vx-wd-item:focus-visible{background:rgba(44,74,62,.04);outline:none}
.vx-wd-item:active{background:rgba(44,74,62,.09)}
.vx-wd-item-icon{width:36px;height:36px;border-radius:10px;background:rgba(44,74,62,.06);border:1px solid rgba(44,74,62,.1);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--green);transition:background .15s,border-color .15s}
.vx-wd-item:hover .vx-wd-item-icon{background:rgba(44,74,62,.11);border-color:rgba(44,74,62,.2)}
.vx-wd-item-text{flex:1;min-width:0}
.vx-wd-item-label{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.875rem;font-weight:500;color:var(--ink,#1C1C1C);margin-bottom:3px}
.vx-wd-item-desc{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;color:var(--text-muted);line-height:1.45}
.vx-wd-item-arrow{color:var(--text-muted);opacity:.4;flex-shrink:0;font-size:1rem;line-height:1}

.vx-wd-footer{padding:14px 22px 18px;border-top:1px solid rgba(44,74,62,.08);flex-shrink:0}
.vx-wd-footer-hide{appearance:none;background:transparent;border:none;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;color:var(--text-muted);cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:3px;transition:color .15s}
.vx-wd-footer-hide:hover{color:var(--green)}

/* ── Mobile Home Feed (≤600px) ───────────────────────────────────────
   Fixed overlay surfaces AI features on mobile. Dismissed when user
   navigates to a workspace section; restored via logo tap. */
/* ═══ Verdeaux home (2026-04-29 redesign w/ wallpaper) ═══════════════
   Universal landing — mobile (2x3 dense grid covering the viewport)
   AND desktop (3x2 centered "gallery" grid inside the bridge area).
   Tiles float over a rotating wedding-photography wallpaper as
   frosted-glass panels. Countdown eyebrow above the grid personalizes.
   The home is the front door for both; tapping a tile opens its
   section. Tapping the logo always returns here.
   When .is-dismissed is set, the home hides and the section shows. */
#mh-overlay{position:fixed;inset:0;z-index:65;background:var(--cream,#FAF7F2);overflow-y:auto;-webkit-overflow-scrolling:touch;display:flex;align-items:center;justify-content:center;padding:96px 20px env(safe-area-inset-bottom,40px);transition:opacity .22s cubic-bezier(.22,1,.36,1)}

/* 2026-04-30 v3 final: two clean states with identical layout.
   • No photo → cream background, green icons, green-outlined tiles.
   • Photo  → full-bleed photo background, cream icons (filter), 100%
     transparent tiles with cream outline.
   Tile positions, icon size, and label position are identical between
   the two states. Only color/transparency changes. */
#mh-overlay{background:var(--cream-d, #F0EBE1)}
.vx-home-bg{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;background:transparent}
.vx-home-bg-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:0;transition:opacity 0.8s cubic-bezier(.22,1,.36,1)}
.vx-home-bg-img.is-on{opacity:1}
.vx-home-bg-scrim{display:none}
/* Photo state — full-bleed photo as the wallpaper. */
body.vx-home-has-photo #mh-overlay{background:transparent}
body.vx-home-has-photo .vx-home-bg{background:var(--vx-home-photo) center / cover no-repeat fixed}
@supports (-webkit-touch-callout: none){
 body.vx-home-has-photo .vx-home-bg{background-attachment:scroll}
}

.vx-home-content{position:relative;z-index:1;width:100%;max-width:720px;display:flex;flex-direction:column;align-items:center;gap:22px}
@media(max-width:600px){.vx-home-content{gap:18px}}

/* ── Countdown eyebrow ─────────────────────────────────────────────
   Editorial-classic line above the tiles. Cream-on-photo with a faint
   glow for legibility regardless of the underlying image. Hidden
   entirely if wedding_date is unset — never shows fake placeholder. */
/* Countdown eyebrow CSS retired with the markup — see HTML comment. */
#mh-overlay.is-dismissed{opacity:0;pointer-events:none;display:none!important}
/* 2026-04-30 v3: vertically center the grid within the full screen on
   mobile too (used to be flex-start anchored under the header). The
   safe-area paddings still keep the grid clear of notch/home-indicator. */
@media(max-width:600px){#mh-overlay{align-items:center;padding:80px 16px calc(env(safe-area-inset-bottom,0px) + 84px)}}
@media(max-width:480px){#mh-overlay{padding-top:74px}}
/* When home is showing, the step-bar + profile-bar are noise. They
   reappear on desktop only when the user enters a section (they
   become the breadcrumb-style hop nav). On mobile, the step bar
   stays hidden — return-home via logo is the navigation pattern. */
/* 2026-04-30: 6-tile launcher is the MOBILE home only. On desktop the
   user gets the full nav (profile bar with "Your wedding" submenu +
   main step bar) and navigates freely — no overlay landing screen. */
@media(max-width:600px){
 body:not(.vx-home-dismissed) .step-bar-fixed{display:none!important}
 body:not(.vx-home-dismissed) .vx-profile-bar{display:none!important}
 .vx-profile-bar{display:none!important}
 .step-bar-fixed{display:none!important}
 /* 2026-08-04 (Stephen, on-device) — was a flat 88px at every mobile width, which
    left a visible empty band between the header and the Allocated/Remaining strip
    on BOTH the iOS app and Safari: the header measures 53px at ≤480 and 61px at
    ≤600, so 88px was 35px / 27px of nothing.
    The floor is not the header, it is the totals strip — position:sticky and the
    first child of #section-budget. If content starts ABOVE the strip's pin, sticky
    shoves it down onto the H1 (the overlap fixed 2026-07-21). So this is the pin
    + 3px, written with the SAME expression as the pin so the two can never drift
    apart. The pin is now the header's exact height, so the chain is:
      header bottom  ==  strip pin  ==  content start − 3px
    Everything is derived from the header's own padding formula, which is why the
    inset belongs HERE and #section-budget's compensating padding could go (it was
    double-counting the inset in standalone mode).
    At inset 0 this is 56px (≤480) / 64px (≤600) — 32px / 24px reclaimed. It lifts
    EVERY mobile page, not just Budget; the others have no strip and only ever
    needed to clear the header. */
 .bridge{padding-top:var(--vx-chrome-bottom)!important}
}
@media(max-width:480px){
 .bridge{padding-top:var(--vx-chrome-bottom)!important}
}
@media(min-width:601px){
 #mh-overlay{display:none!important}
 #mh-back-bar{display:none!important}
 .step-bar-fixed{display:flex!important}
 .vx-profile-bar{display:flex!important}
}

/* ── 6-tile grid (2026-04-30 home rewire) ────────────────────────────
   Two-column grid (mobile-only screen — desktop uses the full nav).
   Default state: cream-on-cream tiles with a hairline border and the
   green wordmark. Photo state: frosted glass over the user wallpaper. */
.vx-home-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;width:100%;max-width:720px;padding:0 14px;margin-block:auto}

/* Editorial mark CSS retired with the markup. */

/* Quick-edit pencil retired 2026-04-30 v3. Wallpaper upload lives
   only on Wedding Details now. */

/* Tile component — default state: cream background + green outline. */
.vx-home-tile{position:relative;aspect-ratio:1/1.1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:14px;padding:14px 12px 16px;border-radius:14px;background:var(--cream, #FAF7F2);border:1px solid var(--green, #2C4A3E);color:var(--green, #2C4A3E);cursor:pointer;appearance:none;text-align:center;transition:transform .15s ease, background .18s ease, border-color .18s ease;box-shadow:none}
.vx-home-tile:hover{background:rgba(255,255,255,.95);border-color:var(--green, #2C4A3E)}
.vx-home-tile:active{transform:scale(.98)}

.vx-home-tile-icon{flex:1;width:100%;display:flex;align-items:center;justify-content:center;color:var(--green, #2C4A3E);transition:transform .15s ease;min-height:0}
/* PNG rendering — same sizing rule as before so the visual proportion
   stays consistent. SVG rule kept as a fallback for any inline SVG
   (e.g. notification dots, shouldn't apply but defensive). */
.vx-home-tile-icon img,
.vx-home-tile-icon svg{width:72%;height:auto;max-width:120px;max-height:100%;display:block;object-fit:contain}
.vx-home-tile:hover .vx-home-tile-icon{transform:translateY(-1px)}

/* 2026-04-30 v3 final: switched from Cormorant Garamond (busy on
   small tiles) to DM Sans — same family the "Shared Access" pill in
   the profile bar uses. Cleaner, less editorial-loud. */
/* 2026-05-04: bumped from 14px → 18px — empirically the max that still
   keeps 'Your Wedding' (longest label) on a single line at 320px iPhone SE
   width. Labels now have visual weight to match the icon scale. */
.vx-home-tile-name{font-family:var(--ff-b, 'DM Sans', sans-serif);font-size:18px;font-weight:500;line-height:1.15;color:var(--green, #2C4A3E);text-align:center;letter-spacing:.01em;flex-shrink:0}
/* 2026-04-30 v3 final: italic on second word retired per Stephen.
   Keeping the <em> tags in markup as no-ops (zero visual diff) so we
   don't churn the HTML, but visually the labels read as one word now. */
.vx-home-tile-name em{font-style:normal;font-weight:inherit;color:inherit}

.vx-home-tile-dot{position:absolute;top:10px;right:10px;width:8px;height:8px;border-radius:50%;background:var(--gold, #C8A96E);box-shadow:0 0 0 2px var(--cream, #FAF7F2);animation:vx-home-dot-fade .35s ease-out}
.vx-home-tile-dot[hidden]{display:none}
@keyframes vx-home-dot-fade{from{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}

/* Photo state — 2026-04-30 v3 final. Tiles 100% transparent with
   cream outline. Two icon strategies:
     1. Single-color icons (chat / up next / budget / scouting) —
        one PNG, recolored green→cream via CSS filter.
     2. Multi-color icons (Contract IQ / Wedding Details) — two
        PNGs (default + baked-in-cream variant), swapped via CSS
        so accent colors (gold heart, cream lens disc with green
        magnifier) are preserved in both states. */
body.vx-home-has-photo .vx-home-tile{background:transparent;border:1px solid var(--cream, #FAF7F2);color:var(--cream, #FAF7F2)}
body.vx-home-has-photo .vx-home-tile:hover{background:rgba(250,247,242,.06);border-color:rgba(255,255,255,1)}
/* Filter applies only to single-image tiles, not the pair-swap ones. */
body.vx-home-has-photo .vx-home-tile-icon:not([data-icon-pair]) img{
 filter: brightness(0) invert(1) sepia(.06) saturate(2) hue-rotate(-10deg) drop-shadow(0 1px 6px rgba(28,28,28,.55));
}
/* Default/cream PNG swap. Default state: hide cream variant. Photo
   state: hide default variant. */
.vx-home-tile-icon[data-icon-pair] .vx-icon-photo{display:none}
body.vx-home-has-photo .vx-home-tile-icon[data-icon-pair] .vx-icon-default{display:none}
body.vx-home-has-photo .vx-home-tile-icon[data-icon-pair] .vx-icon-photo{display:block;filter:drop-shadow(0 1px 6px rgba(28,28,28,.4))}
body.vx-home-has-photo .vx-home-tile-name,
body.vx-home-has-photo .vx-home-tile-name em{color:var(--cream, #FAF7F2);font-weight:600;text-shadow:0 1px 4px rgba(28,28,28,.9),0 0 4px rgba(28,28,28,.55)}

/* iPhone SE / very-narrow: shrink padding only. Keep typography intact
   so the editorial register doesn't shift between phone sizes. */
@media(max-width:380px){
 .vx-home-grid{gap:10px;padding:0 10px}
 .vx-home-tile{padding:12px 10px 14px;border-radius:12px;gap:10px}
 .vx-home-tile-icon svg{max-width:100px}
}

/* ⚑ THE GUIDE INDEX'S BAR LIFTS OVER THE ENV BANNER, LIKE THE PLAN'S NAV DOES.
   Stephen 2026-08-27: "the transportation footer is much taller than the guide
   index, can they align."

   ⚑ MEASURED, AND THE PADDINGS WERE ALREADY IDENTICAL — both bars are
   `10px 16px` with `calc(10px + env(safe-area-inset-bottom))` beneath. The whole
   difference was this `bottom:0` against the plan nav's
   `bottom:var(--vx-envbar-h)`: the nav sits ABOVE the "V3 — not production"
   banner and this bar sat UNDER it, clearing it only because a 34px home-
   indicator inset happens to be about as tall as the banner. On a device with
   no inset it was simply behind it.

   ⚑ SO THIS IS A NO-OP IN PRODUCTION. `--vx-envbar-h` is 0 wherever there is no
   banner, which is everywhere that is not v3 — the misalignment he is looking at
   exists only on the branch, and fixing the OFFSET rather than the padding is
   what keeps that true. */
#mh-back-bar{position:fixed;bottom:var(--vx-envbar-h,0px);left:0;right:0;z-index:66;background:rgba(250,247,242,.96);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-top:1px solid rgba(44,74,62,.1);padding:10px 16px max(10px, env(safe-area-inset-bottom,0px));display:none;align-items:center;gap:8px}
@media(max-width:600px){#mh-back-bar.is-visible{display:flex}}
#mh-back-btn{appearance:none;background:transparent;border:1px solid rgba(44,74,62,.2);border-radius:20px;padding:6px 16px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;color:var(--green);cursor:pointer;display:flex;align-items:center;gap:5px;transition:background .15s}
#mh-back-btn:hover{background:rgba(44,74,62,.05)}
/* 2026-07-08 (Stephen) — surface label retired from the back bar: redundant
   with the visible surface itself, and freeing the row lets the Help pill
   share it (below). Element kept (JS still writes it) but never shown. */
#mh-back-bar-label{display:none!important;font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted);margin-left:4px}

.mh-hero{padding:28px 20px 22px;border-bottom:1px solid rgba(44,74,62,.08)}
.mh-hero-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.54rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold,#C8A96E);margin-bottom:14px}
.mh-hero-names{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:2.1rem;font-weight:400;color:var(--green,#2C4A3E);line-height:1.15;letter-spacing:.01em;margin-bottom:10px}
.mh-hero-names em{font-style:italic;color:var(--gold-deep,#A07840)}
.mh-hero-date-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:6px}
.mh-hero-date{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.55rem;font-weight:400;color:var(--green,#2C4A3E);line-height:1.2;letter-spacing:.01em}
.mh-hero-edit{background:none;border:none;padding:0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;color:var(--gold,#C8A96E);letter-spacing:.02em;cursor:pointer;text-decoration:underline;text-underline-offset:2px;flex-shrink:0}
.mh-settings-card{display:flex;align-items:center;gap:12px;width:100%;margin:16px 0 0;padding:14px 16px;background:#fff;border:1px solid rgba(200,169,110,.25);border-radius:12px;cursor:pointer;text-align:left;transition:background .18s}
.mh-settings-card:active{background:rgba(200,169,110,.08)}
.mh-settings-icon{font-size:1rem;color:var(--gold,#C8A96E);flex-shrink:0}
.mh-settings-text{flex:1;display:flex;flex-direction:column;gap:2px}
.mh-settings-name{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.83rem;font-weight:600;color:var(--green,#2C4A3E)}
.mh-settings-desc{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted)}
.mh-settings-arrow{font-size:1.1rem;color:var(--gold,#C8A96E);flex-shrink:0}
.mh-hero-meta{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;color:var(--text-muted)}

.mh-find-card{margin:18px 16px;background:#fff;border:1px solid rgba(200,169,110,.3);border-radius:16px;padding:20px 18px;box-shadow:0 2px 18px rgba(44,74,62,.07)}
.mh-find-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.54rem;letter-spacing:.12em;text-transform:uppercase;color:var(--gold,#C8A96E);margin-bottom:10px}
.mh-find-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.35rem;font-weight:400;color:var(--green,#2C4A3E);margin-bottom:4px;line-height:1.25}
.mh-find-title em{font-style:italic;color:var(--gold-deep,#A07840)}
.mh-find-sub{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;color:var(--text-muted);line-height:1.55;margin-bottom:14px}
.mh-find-input{width:100%;box-sizing:border-box;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;color:var(--ink,#1C1C1C);background:var(--cream,#FAF7F2);border:1px solid rgba(44,74,62,.14);border-radius:10px;padding:10px 12px;resize:none;line-height:1.5;transition:border-color .15s,box-shadow .15s;margin-bottom:10px;display:block}
.mh-find-input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,169,110,.15)}
.mh-find-btn{width:100%;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;font-weight:500;color:#fff;background:var(--green,#2C4A3E);border:none;border-radius:10px;padding:12px;cursor:pointer;transition:background .15s;display:flex;align-items:center;justify-content:center;gap:6px}
.mh-find-btn:hover{background:var(--green-mid,#3a6054)}
.mh-find-btn:disabled{opacity:.55;cursor:not-allowed}

.mh-section-head{display:flex;align-items:center;justify-content:space-between;padding:18px 20px 10px}
.mh-section-label{font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted)}
.mh-section-link{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.75rem;color:var(--green);background:none;border:none;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:3px;transition:color .12s}
.mh-section-link:hover{color:var(--gold)}

.mh-tools-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:6px 16px 32px}
.mh-tool-card{background:#fff;border:1px solid rgba(44,74,62,.1);border-radius:14px;padding:18px 16px;text-align:left;cursor:pointer;appearance:none;transition:background .15s,border-color .15s,transform .12s;display:flex;flex-direction:column;gap:8px;width:100%}
.mh-tool-card:active{transform:scale(.97)}
.mh-tool-card:hover{background:rgba(250,247,242,.8);border-color:rgba(44,74,62,.2)}
.mh-tool-icon{width:32px;height:32px;border-radius:9px;background:rgba(44,74,62,.07);border:1px solid rgba(44,74,62,.1);display:flex;align-items:center;justify-content:center;color:var(--green,#2C4A3E)}
.mh-tool-name{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.88rem;font-weight:500;color:var(--ink,#1C1C1C)}
.mh-tool-desc{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;color:var(--text-muted);line-height:1.4}

/* ── AI Priority feed ──────────────────────────────────────────────── */
.mh-priorities{padding:4px 16px 2px}
.mh-pri-item{display:flex;align-items:center;gap:11px;padding:13px 14px;background:#fff;border:1px solid rgba(44,74,62,.1);border-radius:12px;margin-bottom:8px;cursor:pointer;text-align:left;width:100%;appearance:none;transition:background .15s,border-color .15s}
.mh-pri-item:active{background:rgba(44,74,62,.04)}
.mh-pri-item[data-urgency="high"]{border-color:rgba(200,169,110,.35)}
.mh-pri-emoji{font-size:1.25rem;flex-shrink:0;width:28px;text-align:center}
.mh-pri-text{flex:1;min-width:0}
.mh-pri-label{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.83rem;font-weight:600;color:var(--ink,#1C1C1C);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mh-pri-sub{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.68rem;color:var(--text-muted);line-height:1.4;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mh-pri-arrow{font-size:.9rem;color:rgba(44,74,62,.3);flex-shrink:0}
.mh-pri-item[data-urgency="high"] .mh-pri-arrow{color:var(--gold,#C8A96E)}
.mh-pri-loading{padding:14px 16px;text-align:center;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted);opacity:.7}
.mh-pri-empty{display:none}

/* ── Mobile/tablet top-chrome offsets ───────────────────────────────
 The header padding shrinks at ≤768px (16px→13px) and ≤480px (→10px),
 reducing header height from ~62px to ~56px to ~48px. Profile-bar and
 step-bar top values must track the header bottom; bridge padding-top
 only needs to clear the chrome, not stay at the full desktop 15rem. */
@media (max-width:768px){
 .vx-profile-bar{top:68px}
 .step-bar-fixed{top:123px}
 .bridge{padding-top:calc(11rem + 10px)}
}
@media (max-width:560px){
 .vx-profile-bar{top:61px}
}
@media (max-width:480px){
 .vx-profile-bar{top:55px}
 .step-bar-fixed{top:110px}
 .bridge{padding-top:calc(10.5rem + 5px)}
 .sn-name{display:block!important;font-size:.58rem;white-space:nowrap;overflow:hidden}
 .step-node{padding:.55rem .38rem!important;gap:4px;min-height:40px;justify-content:flex-start}
 .ideas-btn-text{display:block}
 .ideas-btn-name{font-size:.58rem}
 .ideas-btn{padding:.55rem .38rem;gap:4px}
}
@media (max-width:360px){
 .bridge{padding-top:10.5rem}
 .sn-name{display:none!important}
 .step-node{justify-content:center;padding:.55rem .38rem!important}
 .ideas-btn-text{display:none}
 .ideas-btn{justify-content:center}
}

.ss-vrow-fields{grid-template-columns:1.3fr minmax(140px,1fr) 92px 92px 120px 65px 65px}

.ssv-signed-field{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.ssv-signed-field .sw{margin-top:4px}

.ss-vendor-row.is-signed{background:rgba(200,169,110,.09);box-shadow:inset 3px 0 0 var(--gold)}
.ss-vendor-row.is-signed:hover{background:rgba(200,169,110,.14)}

.ss-vendor-row.is-signed.is-complete{background:rgba(44,74,62,.04);opacity:.72;box-shadow:inset 3px 0 0 var(--green-mid)}

#verdeaux-auth-overlay{position:fixed;inset:0;z-index:9999;background:linear-gradient(135deg,var(--cream) 0%,var(--green-pale) 100%);display:flex;align-items:center;justify-content:center;padding:24px;font-family:var(--ff-b)}
#verdeaux-auth-overlay[hidden]{display:none !important}
.auth-card{max-width:420px;width:100%;background:#fff;border:1px solid rgba(44,74,62,.12);border-radius:16px;padding:36px 32px;box-shadow:0 12px 40px rgba(44,74,62,.14)}
.auth-card h2{font-family:var(--ff-d);font-size:1.7rem;font-weight:400;color:var(--green);margin-bottom:6px;letter-spacing:.01em}
.auth-card h2 em{font-style:italic;color:var(--gold)}
.auth-card .auth-sub{font-size:.82rem;color:var(--ink-faint);margin-bottom:22px;line-height:1.55}
/* 2026-07-09 (Stephen "home view slightly too big, avatar cut off") —
   16px minimum on the auth inputs. iOS auto-zooms the page when a focused
   input's font is under 16px, and WKWebView KEEPS that zoom after sign-in:
   the whole home rendered oversized and clipped the header avatar at the
   right edge. 16px (vs 15.2px) is visually identical and kills the zoom
   trigger on mobile Safari too. The bundle also pins maximum-scale=1
   (scripts/build-ios-bundle.mjs) so no zoom state can ever stick in-app. */
.auth-input{display:block;width:100%;font-family:var(--ff-b);font-size:16px;color:var(--ink);background:var(--cream);border:1px solid rgba(44,74,62,.16);border-radius:10px;padding:12px 14px;margin-bottom:14px;transition:border-color .15s,box-shadow .15s;box-sizing:border-box}
.auth-input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,169,110,.18)}
.auth-btn{display:block;width:100%;font-family:var(--ff-b);font-size:.9rem;font-weight:500;color:#fff;background:var(--green);border:none;border-radius:10px;padding:13px 18px;cursor:pointer;transition:background .15s,transform .1s;box-sizing:border-box}
.auth-btn:hover:not(:disabled){background:var(--green-mid)}
.auth-btn:active:not(:disabled){transform:translateY(1px)}
.auth-btn:disabled{opacity:.55;cursor:not-allowed}
/* 2026-05-10: passkey sign-in button. Cream/green inverse so it doesn't
   compete with the primary magic-link CTA — passkey is the everyday
   fast path; magic link is the bootstrap. */
.auth-btn-passkey{margin-top:10px;background:#fff;color:var(--green);border:1px solid rgba(44,74,62,.32);display:flex;align-items:center;justify-content:center;gap:10px}
.auth-btn-passkey:hover:not(:disabled){background:rgba(200,169,110,.10);border-color:rgba(200,169,110,.6);color:var(--green)}
.auth-passkey-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:var(--gold-deep);color:#fff;font-size:.78rem;font-family:var(--ff-d);font-style:italic}
/* 2026-05-10: SVG passkey-key glyph. Stroke inherits currentColor so
   the green/cream button colours flow through naturally. */
.auth-passkey-glyph{flex-shrink:0;color:var(--gold-deep);transition:color .15s}
.auth-btn-passkey:hover:not(:disabled) .auth-passkey-glyph{color:var(--green)}
.auth-divider{display:flex;align-items:center;gap:10px;margin:14px 2px 4px;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted)}
.auth-divider::before,.auth-divider::after{content:'';flex:1;height:1px;background:rgba(44,74,62,.12)}
/* 2026-05-10: OTP-paste row — revealed after a successful magic-link
   send. Styling mirrors the passkey button (cream/white bg, gold-deep
   accent, no heavy fills) so the secondary auth paths feel like a
   matched pair below the primary "Send magic link" CTA. */
.auth-otp-row{display:flex;gap:8px;margin-top:10px;align-items:stretch;animation:vxAuthOtpReveal .25s ease}
/* 2026-05-10: matched padding/border/font so input + Verify button
   resolve to the exact same height. Both: 12px vertical padding +
   1px border + 0.95rem font with 1.4 line-height = ~46px. */
.auth-otp-row .auth-otp-input{flex:1;letter-spacing:.22em;text-align:center;font-family:var(--ff-m);font-size:16px;line-height:1.4;background:#fff;border:1px solid rgba(44,74,62,.32);color:var(--green);padding:12px 14px;box-sizing:border-box;height:auto;margin:0}
.auth-otp-row .auth-otp-input:focus{outline:none;border-color:var(--gold-deep);box-shadow:0 0 0 2px rgba(200,169,110,.18)}
.auth-otp-row .auth-otp-input::placeholder{color:var(--text-muted);letter-spacing:.18em;font-size:.85rem}
.auth-btn-otp{flex-shrink:0;width:auto;min-width:90px;padding:12px 18px;font-size:.95rem;line-height:1.4;background:#fff;color:var(--green);border:1px solid rgba(44,74,62,.32);font-weight:500;box-sizing:border-box}
.auth-btn-otp:hover:not(:disabled){background:rgba(200,169,110,.10);border-color:rgba(200,169,110,.6);color:var(--green)}
@keyframes vxAuthOtpReveal{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
.auth-msg{margin-top:14px;padding:10px 12px;border-radius:8px;font-size:.78rem;line-height:1.5;display:none}
.auth-msg.is-on{display:block}
.auth-msg.ok{background:rgba(90,140,122,.1);color:var(--green-mid);border:1px solid rgba(90,140,122,.22)}
.auth-msg.err{background:rgba(185,64,64,.06);color:var(--danger);border:1px solid rgba(185,64,64,.2)}
.auth-footer{margin-top:18px;padding-top:16px;border-top:1px solid rgba(44,74,62,.08);font-family:var(--ff-m);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);text-align:center}
.auth-footer em{font-style:italic;color:var(--gold)}

.verdeaux-toast{position:fixed;bottom:22px;right:22px;z-index:9998;max-width:320px;background:var(--green);color:var(--cream);font-family:var(--ff-b);font-size:.82rem;padding:12px 18px;border-radius:10px;box-shadow:0 6px 24px rgba(44,74,62,.3);animation:verdeaux-toast-in .24s ease-out;transition:opacity .35s,transform .35s}
.verdeaux-toast.verdeaux-toast-out{opacity:0;transform:translateY(6px)}
.verdeaux-toast.verdeaux-toast-err{background:var(--danger)}
.verdeaux-toast.verdeaux-toast-ok{background:var(--green-mid)}

.header-auth-btn{cursor:pointer;font:inherit;transition:background .15s,border-color .15s,color .15s;max-width:260px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}
.header-auth-btn:hover{border-color:var(--green-mid);color:var(--green)}
.header-auth-btn.is-signed-in{background:var(--gold-pale);border-color:rgba(200,169,110,.4);color:var(--gold-deep)}
.header-auth-btn.is-signed-in:hover{background:rgba(200,169,110,.14);border-color:var(--gold)}

.verdeaux-logoff-modal{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px;animation:verdeaux-logoff-in .18s ease-out}
.verdeaux-logoff-modal.verdeaux-logoff-out{animation:verdeaux-logoff-out .18s ease-out forwards}
.verdeaux-logoff-backdrop{position:absolute;inset:0;background:rgba(44,74,62,.45);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.verdeaux-logoff-card{position:relative;background:var(--cream);border:1px solid rgba(44,74,62,.12);border-radius:14px;padding:26px 28px 22px;max-width:420px;width:100%;box-shadow:0 14px 44px rgba(44,74,62,.28);font-family:var(--ff-b)}
.verdeaux-logoff-card h2{font-family:var(--ff-d);font-size:1.45rem;font-weight:400;color:var(--green);margin:0 0 8px;letter-spacing:.01em}
.verdeaux-logoff-card p{font-size:.88rem;color:#4A4A4A;line-height:1.55;margin:0 0 22px;word-break:break-word}
.verdeaux-logoff-card p strong{color:var(--green);font-weight:500}
.verdeaux-logoff-actions{display:flex;gap:10px;justify-content:flex-end}
.verdeaux-logoff-actions button{font:inherit;font-family:var(--ff-b);font-size:.82rem;padding:9px 20px;border-radius:8px;cursor:pointer;transition:background .15s,border-color .15s,color .15s}
.verdeaux-logoff-cancel{background:transparent;border:1px solid rgba(44,74,62,.22);color:var(--green)}
.verdeaux-logoff-cancel:hover{background:rgba(44,74,62,.06);border-color:var(--green-mid)}
.verdeaux-logoff-cancel:focus-visible{outline:2px solid var(--green-mid);outline-offset:2px}
.verdeaux-logoff-confirm{background:var(--green);border:1px solid var(--green);color:var(--cream)}
.verdeaux-logoff-confirm:hover{background:var(--green-mid);border-color:var(--green-mid)}
.verdeaux-logoff-confirm:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
@keyframes verdeaux-logoff-in{from{opacity:0}to{opacity:1}}
@keyframes verdeaux-logoff-out{from{opacity:1}to{opacity:0}}
.verdeaux-logoff-modal .verdeaux-logoff-card{animation:verdeaux-logoff-card-in .2s cubic-bezier(.2,.9,.3,1)}
@keyframes verdeaux-logoff-card-in{from{opacity:0;transform:translateY(8px) scale(.97)}to{opacity:1;transform:none}}
@keyframes verdeaux-toast-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}


/* ══════════════════════════════════════════════════════════════════
 Ideas card rewire (2026-04-23) — filter chips + specialized voices
 Replaces the 3-submenu Reddit/Pinterest/TikTok UI with a unified feed.
 Server-side RPC inspirations_for_me returns match-scored rows; filter
 chips re-query with category/tier/demographic params.
 ══════════════════════════════════════════════════════════════════ */

.specialized-voices-section{margin:2.5rem auto 4rem;max-width:1100px;padding:0 clamp(20px,6vw,80px)}
.specialized-voices-head{margin-bottom:1rem;padding-bottom:.75rem;border-bottom:2px solid rgba(200,169,110,.3)}
.specialized-voices-title{font-family:'Cormorant Garamond','Cormorant Fallback',Georgia,serif;font-size:1.65rem;font-weight:500;color:#2C4A3E;margin-bottom:.25rem}
.specialized-voices-sub{font-size:.82rem;color:#4A4A4A;line-height:1.55;font-style:italic;max-width:760px}
.specialized-voices-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1rem;margin-top:1.25rem}
.specialized-voices-card{background:#FFFFFF;border:1px solid rgba(44,74,62,.12);border-left:3px solid #C8A96E;border-radius:10px;padding:18px 20px;display:flex;flex-direction:column;gap:8px;text-decoration:none;color:inherit;transition:all .2s ease}
.specialized-voices-card:hover{transform:translateY(-2px);box-shadow:0 6px 20px rgba(44,74,62,.12)}
.specialized-voices-card-source{font-family:'DM Mono',monospace;font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:#C8A96E;font-weight:500}
.specialized-voices-card-title{font-family:'Cormorant Garamond',serif;font-size:1.05rem;font-weight:500;color:#2C4A3E;line-height:1.3}
.specialized-voices-card-summary{font-size:.78rem;color:#4A4A4A;line-height:1.55;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.specialized-voices-card-meta{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}
.vx-badge{display:inline-block;font-family:'DM Mono',monospace;font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:2px 8px;border-radius:100px;font-weight:500}
.vx-badge--demo{background:rgba(200,169,110,.18);color:#A07840}

.ideas-bar-desc-inline{font-family:'DM Sans',sans-serif;font-size:.75rem;color:rgba(255,255,255,.78);font-weight:300;margin-left:10px;flex:1;line-height:1.4}

/* ═══ Phase 5: Outreach ═════════════════════════════════════════ */
.vx-outreach-intro{max-width:1040px;margin:0 auto 1.25rem;padding:0 1rem}
.vx-outreach-toolbar{display:flex;align-items:center;gap:1rem;flex-wrap:wrap;padding:.75rem 1rem;background:var(--white);border:1px solid var(--border-g);border-radius:10px;box-shadow:0 1px 6px rgba(44,74,62,.04)}
.vx-outreach-select-all{display:inline-flex;align-items:center;gap:6px;font-size:.85rem;color:var(--text-mid);cursor:pointer;user-select:none}
.vx-outreach-select-all input{width:14px;height:14px;accent-color:var(--green)}
.vx-outreach-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px;max-width:1040px;margin:0 auto 2rem;padding:0 1rem}
.vx-outreach-card{background:var(--white);border:1px solid var(--border-g);border-radius:10px;padding:14px 16px;display:flex;flex-direction:column;gap:8px;transition:border-color .15s,box-shadow .15s}
.vx-outreach-card.is-checked{border-color:var(--green);box-shadow:0 2px 10px rgba(44,74,62,.08)}
.vx-outreach-card-head{display:flex;align-items:flex-start;gap:10px}
.vx-outreach-card-checkbox{width:16px;height:16px;accent-color:var(--green);margin-top:2px;flex-shrink:0;cursor:pointer}
.vx-outreach-card-body{flex:1;min-width:0}
.vx-outreach-card-name{font-family:'Cormorant Garamond',serif;font-size:1.08rem;font-weight:500;color:var(--green);line-height:1.25;margin:0 0 2px;word-wrap:break-word}
.vx-outreach-card-cat{font-family:'DM Mono',monospace;font-size:.54rem;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep)}
.vx-outreach-card-meta{font-size:.76rem;color:var(--text-muted);line-height:1.45;display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.vx-outreach-card-meta a{color:var(--green);text-decoration:none;border-bottom:1px dotted rgba(44,74,62,.3)}
.vx-outreach-card-meta a:hover{border-bottom-style:solid}
.vx-outreach-card-status{display:inline-flex;align-items:center;gap:5px;font-family:'DM Mono',monospace;font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:2px 7px;border-radius:100px}
.vx-outreach-status-sent{background:rgba(90,140,122,.12);color:#3d6a58;border:1px solid rgba(90,140,122,.28)}
.vx-outreach-status-reply{background:rgba(200,169,110,.15);color:#8A6B2B;border:1px solid rgba(200,169,110,.35)}
.vx-outreach-status-drafted{background:rgba(44,74,62,.08);color:#6b7075;border:1px solid rgba(44,74,62,.15)}
.vx-outreach-drafts{max-width:1040px;margin:0 auto;padding:0 1rem;display:flex;flex-direction:column;gap:1rem}
.vx-outreach-draft{background:var(--white);border:1px solid var(--border-g);border-radius:12px;padding:20px 22px;box-shadow:0 2px 10px rgba(44,74,62,.05)}
.vx-outreach-draft-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.vx-outreach-draft-title{font-family:'Cormorant Garamond',serif;font-size:1.2rem;color:var(--green);margin:0}
.vx-outreach-draft-loading{font-size:.78rem;color:var(--text-muted);font-style:italic}
.vx-outreach-draft-error{font-size:.85rem;color:#B94040;background:rgba(185,64,64,.05);border:1px solid rgba(185,64,64,.22);border-radius:8px;padding:10px 12px}
.vx-outreach-draft-field{display:flex;flex-direction:column;gap:4px;margin-bottom:10px}
.vx-outreach-draft-field label{font-family:'DM Mono',monospace;font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.vx-outreach-draft-field input,.vx-outreach-draft-field textarea{width:100%;border:1px solid var(--border);border-radius:8px;padding:9px 12px;font-family:'DM Sans',sans-serif;font-size:.92rem;color:var(--ink);background:var(--cream);box-sizing:border-box;transition:border-color .15s}
.vx-outreach-draft-field input:focus,.vx-outreach-draft-field textarea:focus{border-color:var(--green);outline:none}
.vx-outreach-draft-field textarea{min-height:140px;line-height:1.55;resize:vertical}
.vx-outreach-draft-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:6px}
.vx-outreach-draft-actions button,.vx-outreach-draft-actions a.vx-outreach-btn{appearance:none;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;padding:9px 16px;border-radius:8px;border:1px solid rgba(44,74,62,.22);background:var(--white);color:var(--text-mid);cursor:pointer;transition:all .15s;text-decoration:none;display:inline-flex;align-items:center;gap:6px}
.vx-outreach-draft-actions button:hover,.vx-outreach-draft-actions a.vx-outreach-btn:hover{background:var(--green-pale);border-color:var(--green);color:var(--green)}
.vx-outreach-draft-actions .vx-outreach-btn-primary{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-outreach-draft-actions .vx-outreach-btn-primary:hover{background:var(--green-mid);color:var(--white);border-color:var(--green-mid)}
.vx-outreach-draft-actions .vx-outreach-btn-sent{background:rgba(90,140,122,.12);border-color:rgba(90,140,122,.3);color:#3d6a58}
.vx-outreach-reply-box{margin-top:12px;padding:12px 14px;background:rgba(200,169,110,.06);border:1px dashed rgba(200,169,110,.4);border-radius:8px;display:none}
.vx-outreach-reply-box.is-open{display:block}
.vx-outreach-reply-box textarea{width:100%;min-height:100px;border:1px solid var(--border);border-radius:8px;padding:9px 12px;font-family:'DM Sans',sans-serif;font-size:.9rem;background:var(--white);box-sizing:border-box}
.vx-outreach-reply-saved{font-size:.8rem;color:#3d6a58;margin-top:6px;display:none}
.vx-outreach-reply-saved.is-visible{display:block}
@media (max-width:767px){
 .vx-outreach-grid{grid-template-columns:1fr}
 .vx-outreach-toolbar{padding:.65rem .75rem;gap:.5rem}
 .vx-outreach-toolbar #vxOutreachGenBtn{margin-left:0;width:100%;margin-top:4px}
 .vx-outreach-draft{padding:16px}
 .vx-outreach-draft-actions{flex-direction:column}
 .vx-outreach-draft-actions button,.vx-outreach-draft-actions a.vx-outreach-btn{justify-content:center;width:100%}
}

/* ═══ Phase 7: Compare Proposals ═════════════════════════════════ */
.vx-cmp-wrap{max-width:1080px;margin:0 auto 4rem}
.vx-cmp-meta{display:flex;align-items:center;gap:8px;max-width:1040px;margin:0 auto 14px;padding:0 1rem;flex-wrap:wrap}

/* 2026-05-01 Slice 7 polish: per-surface blurb sits between the sub-nav
   and the working surface (upload zone / compare zones). Sized to match
   the .pt-sub paragraph in the new shared intro so the per-surface
   text feels like a small handoff, not another hero. */
.vx-cr-surface-blurb { max-width: 720px; margin: 1.5rem auto 1.25rem; padding: 0 clamp(20px,5vw,48px); text-align: left; }
.vx-cr-surface-blurb p { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .82rem; color: var(--ink-mid,#4A4A4A); line-height: 1.6; font-weight: 300; margin: 0 0 .75rem; }
.vx-cr-surface-blurb .privacy-strip { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; font-family: var(--ff-m,'DM Mono',monospace); font-size: .58rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted,#88928d); }
.vx-cr-surface-blurb .privacy-strip .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--green-mid,#3a6b59); display: inline-block; }

/* 2026-05-01 Slice 7 — Contract IQ shared intro above the sub-nav.
   Matches the interview-guide header pattern: gold mono eyebrow,
   Cormorant display heading with italic gold em, body-font subtitle. */
.vx-cr-intro { max-width: 760px; margin: 1.5rem auto 0; padding: 0 clamp(20px,5vw,48px); text-align: center; }
.vx-cr-intro-eyebrow { font-family: var(--ff-m,'DM Mono',monospace); font-size:var(--fs-eyebrow,.62rem); letter-spacing:.14em; text-transform: uppercase; color: var(--gold-deep,#A07840); font-weight: 500; margin: 0 0 .9rem; }
.vx-cr-intro-h { font-family: var(--ff-d,'Cormorant Garamond',serif); font-size: clamp(1.85rem, 4.4vw, 2.6rem); font-weight: 400; color: var(--green,#2C4A3E); line-height: 1.12; letter-spacing: -.01em; margin: 0 0 .85rem; }
.vx-cr-intro-h em { font-style: italic; color: var(--gold,#C8A96E); }
.vx-cr-intro-sub { font-family: var(--ff-b,'DM Sans',sans-serif); font-size: 1rem; line-height: 1.7; color: var(--text-mid,#4A4A4A); max-width: 620px; margin: 0 auto; }

/* 2026-05-01 Slice 7 — Contract IQ sub-nav (DocReview / DocCompare).
   2026-07-28 (Stephen) — the 900px-max/no-padding bar stuck out past the
   surface content beneath it (the paid + confidential banner, the privacy
   strip, the Not-Legal-Advice box, the report) on both left and right. Match
   the sub-nav column EXACTLY to `.vx-cr-surface-blurb` (720px max + the same
   clamp side padding) so the tab bar, the paid/confidential banner, and the
   body read as one aligned column — nothing sticking out. The clamp handles
   the responsive side gutter, so the old 960px padding override is gone. */
.vx-cr-subnav { background: transparent; border: none; margin: 1.5rem auto 1rem; max-width: 720px; padding: 0 clamp(20px,5vw,48px); position: relative; z-index: 1; }
.vx-cr-subnav .phase-nav-inner { display: flex; background: var(--white,#fff); border: 1px solid var(--border,#eae5dd); border-radius: 16px; padding: 6px; gap: 4px; box-shadow: 0 2px 10px rgba(44,74,62,.04); }
.vx-cr-subnav .phase-tab { flex: 1; min-width: 140px; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 12px 18px; font-family: var(--ff-b,'DM Sans',sans-serif); font-size: .92rem; font-weight: 400; color: var(--text-mid,#4A4A4A); background: none; border: none; border-radius: 12px; cursor: pointer; transition: all .2s cubic-bezier(.4,0,.2,1); }
.vx-cr-subnav .phase-tab:hover { color: var(--green,#2C4A3E); background: var(--green-pale,#EAF0ED); }
.vx-cr-subnav .phase-tab.active { color: #fff; background: var(--green,#2C4A3E); font-weight: 500; }
.vx-cr-subnav .phase-tab.active:hover { background: var(--green-deep,#1F362D); }
.vx-cr-subnav .phase-number { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-family: var(--ff-m,'DM Mono',monospace); font-size: .68rem; font-weight: 500; flex-shrink: 0; background: rgba(44,74,62,.08); color: var(--text-muted,#88928d); }
.vx-cr-subnav .phase-tab.active .phase-number { background: rgba(255,255,255,.22); color: #fff; }

/* 2026-05-01 Slice 7 — Compare mode toggle, asks textarea, apply pill.
   Toggle styled like the workspace nav ( | Chat | Budget | ... | ) so
   the two modes read as parallel destinations, not a binary switch. */
.vx-cmp-mode{display:flex;align-items:center;justify-content:center;gap:0;max-width:1040px;margin:0 auto 18px;padding:0 1rem;flex-wrap:wrap}
.vx-cmp-mode-btn{background:transparent;border:none;color:var(--text-muted,#88928d);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:1rem;font-weight:400;padding:8px 18px;cursor:pointer;transition:color .15s ease,font-weight .15s ease;letter-spacing:normal;text-transform:none}
.vx-cmp-mode-btn:hover:not(.is-active){color:var(--charcoal,#1C1C1C)}
.vx-cmp-mode-btn.is-active{color:var(--green,#2C4A3E);font-weight:600}
.vx-cmp-mode-pipe{color:var(--border-g,#cdc5b6);font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.1rem;font-weight:300;user-select:none}

.vx-cmp-asks{max-width:1040px;margin:0 auto 1.25rem;padding:0 1rem}
.vx-cmp-asks-label{display:block;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;color:var(--charcoal);margin-bottom:6px}
.vx-cmp-asks-hint{font-size:.78rem;color:var(--text-muted);font-style:italic;font-weight:400}
.vx-cmp-asks-input{width:100%;border:1px solid var(--border,#eae5dd);background:var(--white,#fff);border-radius:8px;padding:10px 12px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;color:var(--charcoal);resize:vertical;min-height:80px;outline:none}
.vx-cmp-asks-input:focus{border-color:var(--green,#2C4A3E)}

.vx-cmp-apply-this{background:var(--green,#2C4A3E);color:#fff;border:none;border-radius:100px;padding:8px 18px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;font-weight:500;cursor:pointer;transition:all .15s}
.vx-cmp-apply-this:hover{background:var(--green-mid,#3a6b59)}
.vx-cmp-apply-this[disabled]{opacity:.5;cursor:not-allowed}
/* 2026-05-04: secondary "Add to Budget" button — softer ghost variant
   sitting beside the primary lock button on Best At This Stage. */
.vx-cmp-add-to-budget{background:transparent;color:var(--green,#2C4A3E);border:1px solid rgba(44,74,62,.35);border-radius:100px;padding:8px 18px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;font-weight:500;cursor:pointer;transition:all .15s;margin-left:10px}
.vx-cmp-add-to-budget:hover{background:rgba(58,107,89,.08);border-color:var(--green,#2C4A3E)}
@media (max-width:560px){
 .vx-cmp-add-to-budget{margin-left:0;margin-top:8px;width:100%}
 .vx-cmp-best-actions{display:flex;flex-direction:column;align-items:stretch}
 .vx-cmp-best-actions .vx-cmp-apply-this{width:100%}
}

/* Slice 7 — V2 results panel: vendor cards, best-at-this-stage, asks audit */
.vx-cmp-summary{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:1rem;color:var(--charcoal);line-height:1.6;padding:18px 22px;background:var(--cream-warm,#F0EBE1);border-radius:12px;margin-bottom:1.25rem;border-left:3px solid var(--gold,#C8A96E)}
/* 2026-05-04: Vendor summary cards align column-for-column under the
   upload zones (3 equal columns at the page-title canonical width). When
   only 2 docs are uploaded, the 2 cards naturally sit in columns 1 and 2,
   matching the same upload columns above. The vertical dividers between
   columns mirror the upload-row structure — visually carrying the 3-zone
   rhythm down through the feedback sections. */
.vx-cmp-vendor-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;margin-bottom:1.25rem;border-top:1px solid rgba(44,74,62,.18);border-bottom:1px solid rgba(44,74,62,.18)}
.vx-cmp-vendor-cards>*{padding:14px 16px;border-right:1px solid rgba(44,74,62,.12);min-width:0}
.vx-cmp-vendor-cards>*:last-child{border-right:none}
.vx-cmp-vendor-card{background:#fff;border:1px solid var(--border,#eae5dd);border-radius:10px;padding:14px 16px}
.vx-cmp-vendor-name{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;font-weight:500;color:var(--charcoal);margin-bottom:4px}
.vx-cmp-vendor-price{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--money-ink,#33352f);margin-bottom:6px}
.vx-cmp-vendor-scope{font-size:.82rem;color:var(--text-mid);line-height:1.5}
.vx-cmp-best{background:linear-gradient(135deg,rgba(58,107,89,.08),rgba(200,169,110,.08));border:1px solid rgba(58,107,89,.25);border-radius:14px;padding:22px 26px;margin-bottom:1.5rem}
.vx-cmp-best-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;color:var(--green-mid,#3a6b59);font-weight:500;margin-bottom:6px}
.vx-cmp-best-name{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.5rem;color:var(--green,#2C4A3E);font-weight:400;margin-bottom:8px}
.vx-cmp-best-rationale{font-size:.95rem;color:var(--charcoal);line-height:1.6;margin-bottom:10px}
.vx-cmp-best-meta{margin-bottom:10px}
.vx-cmp-best-conf{display:inline-block;padding:3px 10px;border-radius:100px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}
.vx-cmp-conf-high{background:rgba(58,107,89,.15);color:var(--green-mid,#3a6b59)}
.vx-cmp-conf-moderate{background:rgba(200,169,110,.15);color:var(--gold-deep,#A07840)}
.vx-cmp-conf-low{background:rgba(125,125,125,.12);color:var(--text-muted)}
.vx-cmp-best-caveat{font-size:.82rem;color:var(--text-mid);font-style:italic;line-height:1.55;padding:10px 0;border-top:1px dashed rgba(44,74,62,.18);margin-top:8px}
/* 2026-07-28 objective-axis: deterministic grounding line under the pick,
   the mismatch "worth a second look" caveat, and the counsel footer. */
.vx-cmp-best-grounding{font-family:var(--ff-m,'DM Mono',monospace);font-size:.72rem;letter-spacing:.02em;color:var(--green-mid,#3a6b59);line-height:1.5;margin-bottom:10px}
.vx-cmp-best-mismatch{font-style:normal;color:var(--gold-deep,#A07840);border-top-color:rgba(200,169,110,.4)}
.vx-cmp-counsel-note{font-size:.8rem;color:var(--text-muted);line-height:1.55;margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--border-g,rgba(44,74,62,.12));text-align:center}
.vx-cmp-best-actions{margin-top:12px}
.vx-cmp-rec-accept{border-color:rgba(58,107,89,.35)}
.vx-cmp-rec-push_back,.vx-cmp-rec-request_more_changes{background:linear-gradient(135deg,rgba(201,123,58,.08),rgba(200,169,110,.06));border-color:rgba(201,123,58,.25)}
.vx-cmp-rec-walk_away{background:rgba(185,64,64,.05);border-color:rgba(185,64,64,.25)}
.vx-cmp-pushback{margin:10px 0 0;padding-left:20px;font-size:.88rem;color:var(--charcoal);line-height:1.7}
.vx-cmp-pushback li{margin-bottom:4px}
.vx-cmp-section-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.25rem;color:var(--green,#2C4A3E);font-weight:400;font-style:italic;margin:1.5rem 0 .75rem}
.vx-cmp-actions{margin:0;padding-left:24px;font-size:.9rem;color:var(--charcoal);line-height:1.65}
.vx-cmp-actions li{margin-bottom:8px}
.vx-cmp-action-vendor{font-weight:500;color:var(--green,#2C4A3E)}
.vx-cmp-action-pri-high::marker{color:var(--amber-risk,#C97B3A)}
.vx-cmp-info{margin:0;padding-left:24px;font-size:.88rem;color:var(--charcoal);line-height:1.65}
.vx-cmp-info li{margin-bottom:6px}
.vx-cmp-info strong{color:var(--green,#2C4A3E);font-weight:500}
.vx-cmp-cell-advantage{background:rgba(58,107,89,.06);font-weight:500}
.vx-cmp-cell-bad{background:rgba(185,64,64,.06)}
.vx-cmp-asks-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:10px}
.vx-cmp-asks-list li{padding:12px 14px;border:1px solid var(--border,#eae5dd);border-radius:10px;background:#fff}
.vx-cmp-ask-status{font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;letter-spacing:.06em;font-weight:500;margin-bottom:4px}
.vx-cmp-ask-addressed .vx-cmp-ask-status{color:var(--green-mid,#3a6b59)}
.vx-cmp-ask-partially_addressed .vx-cmp-ask-status{color:var(--gold-deep,#A07840)}
.vx-cmp-ask-ignored .vx-cmp-ask-status{color:var(--rose,#C97B6A)}
.vx-cmp-ask-not_in_revision .vx-cmp-ask-status{color:var(--text-muted)}
.vx-cmp-ask-text{font-size:.92rem;color:var(--charcoal);margin-bottom:4px}
.vx-cmp-asks-list blockquote{margin:6px 0 0;padding:6px 10px;background:var(--cream-warm,#F0EBE1);border-left:2px solid var(--border-g,#cdc5b6);font-size:.82rem;color:var(--text-mid);font-style:italic}
.vx-cmp-mag-major{display:inline-block;padding:1px 6px;background:rgba(185,64,64,.1);color:var(--rose,#C97B6A);border-radius:100px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}
.vx-cmp-mag-moderate{display:inline-block;padding:1px 6px;background:rgba(200,169,110,.15);color:var(--gold-deep,#A07840);border-radius:100px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}
.vx-cmp-mag-minor{display:inline-block;padding:1px 6px;background:rgba(44,74,62,.06);color:var(--text-muted);border-radius:100px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}
.vx-cmp-select{font-family:'DM Sans',sans-serif;font-size:.9rem;padding:8px 32px 8px 12px;border:1px solid var(--border-g);border-radius:8px;background:var(--white);color:var(--ink);cursor:pointer;min-width:200px;appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%232C4A3E' stroke-width='1.3' fill='none' stroke-linecap='round'/></svg>");background-repeat:no-repeat;background-position:right 10px center}
/* 2026-05-01 Slice 7 polish: zones restyled to match the single-doc
   .upload-zone aesthetic — cream background, dashed gold border,
   centered icon + Cormorant heading + subtitle + outlined Choose File
   pill. Vendor-name input and paste textarea are kept (functional
   parity with the prior zones) but visually subordinated to the
   primary "drop a file" affordance. */
/* 2026-05-04: locked to the page-title canonical container — 820px max,
   clamp(1rem,4vw,2rem) horizontal padding — so the upload row spans
   exactly from the left edge of the submenu tabs to the right edge of
   the "hide" toggle. minmax(0,1fr) on each column prevents any cell
   from growing past its 1/3 share when a long filename is dropped in;
   the filename ellipsis (.vx-cmp-zone-file-name) handles overflow. */
.vx-cmp-zones{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;max-width:820px;margin:0 auto 1.25rem;padding:0 clamp(1rem,4vw,2rem)}
.vx-cmp-zone{position:relative;border:1.5px dashed var(--border-strong,#cdc5b6);border-radius:var(--radius-lg,12px);background:rgba(242,235,224,0.4);padding:1.5rem 1rem 1.25rem;text-align:center;display:flex;flex-direction:column;gap:10px;transition:all .25s ease;min-height:240px;min-width:0;overflow:hidden}
.vx-cmp-zone:hover,.vx-cmp-zone.is-dragover{border-color:var(--gold,#C8A96E);background:rgba(201,169,110,.06)}
.vx-cmp-zone.is-filled{border-style:solid;border-color:var(--green,#2C4A3E);background:rgba(107,143,113,.05)}
.vx-cmp-zone-head{display:flex;align-items:center;justify-content:center;gap:6px;font-family:'DM Mono',monospace;font-size:.58rem;letter-spacing:.12em;text-transform:uppercase}
.vx-cmp-zone-num{color:var(--gold-deep,#A07840);font-weight:500}
.vx-cmp-zone-optional{color:var(--text-muted,#88928d);opacity:.8;font-size:.52rem}
/* Vendor-name input — small, label-style at top so the file affordance
   stays primary. */
.vx-cmp-zone-label-input{width:80%;align-self:center;border:none;background:transparent;font-family:'Cormorant Garamond',serif;font-size:1rem;color:var(--green,#2C4A3E);padding:2px 0;outline:none;border-bottom:1px dotted rgba(44,74,62,.18);text-align:center;margin-bottom:6px}
.vx-cmp-zone-label-input:focus{border-bottom-color:var(--green,#2C4A3E)}
.vx-cmp-zone-label-input::placeholder{color:var(--text-muted,#88928d);font-style:italic}
/* Big gold upload icon at top, mirroring .upload-icon presence */
.vx-cmp-zone-icon{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:1px solid rgba(201,169,110,.4);border-radius:8px;color:var(--gold,#C8A96E);margin:6px auto 4px}
.vx-cmp-zone-title{font-family:'Cormorant Garamond',serif;font-size:1.2rem;font-weight:400;color:var(--ink,#1C1C1C);margin:0 0 2px}
.vx-cmp-zone-sub{font-size:.78rem;color:var(--text-muted,#88928d);margin:0 0 8px}
.vx-cmp-zone-file{display:flex;align-items:center;gap:8px;background:rgba(107,143,113,.08);border:1px solid rgba(107,143,113,.22);border-radius:8px;padding:8px 10px;font-size:.82rem;color:var(--green,#2C4A3E);min-width:0;max-width:100%}
.vx-cmp-zone-file-name{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500;text-align:left}
.vx-cmp-zone-choose{appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:8px;align-self:center;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;color:var(--green,#2C4A3E);background:transparent;border:1.5px solid rgba(44,74,62,.28);padding:9px 22px;border-radius:40px;cursor:pointer;transition:all .25s ease}
.vx-cmp-zone:hover .vx-cmp-zone-choose{border-color:var(--green,#2C4A3E);background:rgba(44,74,62,.06)}
.vx-cmp-zone-or{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted,#88928d);text-align:center;margin:6px 0 2px}
.vx-cmp-zone-paste{width:100%;min-height:54px;border:1px solid var(--border,#eae5dd);border-radius:8px;padding:8px 10px;font-family:'DM Sans',sans-serif;font-size:.8rem;background:var(--white,#fff);box-sizing:border-box;resize:vertical;color:var(--ink,#1C1C1C)}
.vx-cmp-zone-paste:focus{outline:none;border-color:var(--green,#2C4A3E)}
.vx-cmp-zone-paste::placeholder{color:var(--text-muted,#88928d);font-style:italic}
.vx-cmp-zone-counter{font-family:'DM Mono',monospace;font-size:.58rem;letter-spacing:.06em;color:var(--text-muted,#88928d);text-align:right}
.vx-cmp-zone-clear{position:absolute;top:10px;right:10px;background:transparent;border:none;font-size:.82rem;color:var(--text-muted,#88928d);cursor:pointer;padding:4px 6px;border-radius:4px;transition:color .12s,background .12s;line-height:1;z-index:2}
.vx-cmp-zone-clear:hover{color:#B94040;background:rgba(185,64,64,.06)}
.vx-cmp-actions{display:flex;gap:12px;justify-content:center;margin-bottom:1rem;flex-wrap:wrap;padding:0 1rem}
.vx-cmp-error{max-width:800px;margin:0 auto 1rem;padding:12px 16px;background:rgba(185,64,64,.05);border:1px solid rgba(185,64,64,.22);border-radius:8px;color:#B94040;font-size:.88rem}
.vx-cmp-stream{max-width:1040px;margin:0 auto 1.5rem;padding:1.25rem;background:var(--white);border:1px solid var(--border-g);border-radius:12px;box-shadow:0 2px 12px rgba(44,74,62,.05)}
.vx-cmp-stream-head{display:flex;align-items:center;gap:10px;font-family:'DM Mono',monospace;font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:10px}
.vx-cmp-stream-dot{width:8px;height:8px;border-radius:50%;background:var(--gold);animation:blink-dot 1.1s ease-in-out infinite}
.vx-cmp-stream-body{font-family:'DM Mono',monospace;font-size:.74rem;color:var(--text-mid);background:rgba(44,74,62,.03);border-radius:8px;padding:12px 14px;margin:0;max-height:320px;overflow-y:auto;white-space:pre-wrap;word-break:break-word;line-height:1.55}
/* 2026-05-04: results container shares the upload row's canonical width
   so the 3-column vendor cards inside align under the 3 upload zones. */
.vx-cmp-results{max-width:820px;margin:0 auto 2rem;padding:0 clamp(1rem,4vw,2rem)}

/* Auto-detected category badge — appears at the top of results when the
   user left the dropdown on "Auto-detect," communicating which frame the
   model used for its analysis. Subtle, just-noticeable; not a full alert. */
.vx-cmp-inferred-cat{display:flex;align-items:baseline;gap:8px;margin:0 0 .9rem;padding:8px 14px;background:rgba(242,235,224,.55);border:1px solid rgba(200,169,110,.25);border-radius:8px;font-family:'DM Sans',sans-serif}
.vx-cmp-inferred-cat-eyebrow{font-family:'DM Mono',monospace;font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
.vx-cmp-inferred-cat-label{font-size:.92rem;color:var(--green,#2C4A3E);font-weight:500}
.vx-cmp-matrix-dim{font-weight:500;color:var(--green);font-family:'Cormorant Garamond',serif;font-size:1rem}
.vx-cmp-matrix-note{font-size:.82rem;color:var(--text-mid);line-height:1.5}
.vx-cmp-flags-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;margin-bottom:1.5rem}
.vx-cmp-flags-col{background:var(--white);border:1px solid var(--border-g);border-radius:12px;padding:16px 18px}
.vx-cmp-flags-vname{font-family:'Cormorant Garamond',serif;font-size:1.12rem;color:var(--green);margin:0 0 10px;font-weight:500}
.vx-cmp-flag{display:flex;gap:8px;padding:8px 0;border-top:1px solid var(--border-g);font-size:.86rem;line-height:1.5;color:var(--text-mid)}
.vx-cmp-flag:first-child{border-top:none}
.vx-cmp-flag-sev{display:inline-block;width:8px;height:8px;border-radius:50%;margin-top:7px;flex-shrink:0}
.vx-cmp-flag-sev-critical{background:#B94040}
.vx-cmp-flag-sev-warning{background:#C8A96E}
.vx-cmp-flag-sev-caution{background:#8e8579}

/* 2026-05-04: Risks-by-vendor layout — 3 vertical columns that align
   under the upload row above. Replaces the legacy "table of full-width
   rows" rendering for the main vendor-compare path. Each column lists
   one vendor's flags as severity-tinted cards with white text + left-
   justified content for fast scanning. Vertical column rails reinforce
   the 3:3 mapping with the upload row. Stacks to 1 column on mobile. */
.vx-cmp-risks-by-vendor{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;margin-bottom:1.5rem;border-top:1px solid rgba(44,74,62,.18);border-bottom:1px solid rgba(44,74,62,.18)}
.vx-cmp-risks-col{display:flex;flex-direction:column;gap:10px;min-width:0;padding:14px 16px;border-right:1px solid rgba(44,74,62,.12)}
.vx-cmp-risks-col:last-child{border-right:none}
.vx-cmp-risks-vname{font-family:'Cormorant Garamond',serif;font-size:1.05rem;color:var(--green);margin:0;font-weight:500;text-align:center;padding:0 0 8px;border-bottom:1px solid rgba(44,74,62,.18);letter-spacing:.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vx-cmp-risks-empty{font-size:.78rem;color:var(--text-muted);font-style:italic;padding:14px 12px;border:1px dashed rgba(44,74,62,.15);border-radius:8px;text-align:center;line-height:1.4}
/* Risk card height lock + content fade — 1.5× the matrix cell height
   (10.5em) so cards in the same row across vendor columns share top
   and bottom edges. The fade is applied to an inner wrapper so the
   severity-colored card background stays sharp at the bottom edge —
   only the text content dissolves, not the card itself. */
.vx-cmp-risk-card{border-radius:8px;color:#fff;text-align:left;height:10.5em;overflow:hidden;position:relative;box-sizing:border-box}
/* 2026-07-29 (Stephen) — softened from loud saturated fills to calm muted tones
   so the whole compare read stays even-keeled (no alarm-red). */
.vx-cmp-risk-card.vx-cmp-flag-sev-critical{background:#9B5F58}
.vx-cmp-risk-card.vx-cmp-flag-sev-warning{background:#A98A55}
.vx-cmp-risk-card.vx-cmp-flag-sev-caution{background:#8A817B}
.vx-cmp-risk-card-inner{padding:12px 14px;height:100%;overflow:hidden;-webkit-mask-image:linear-gradient(to bottom, black 80%, transparent 100%);mask-image:linear-gradient(to bottom, black 80%, transparent 100%);box-sizing:border-box}

/* Tap-to-expand affordance — appears ONLY on risk cards whose content
   genuinely overflows the 10.5em cap (detected post-render in JS). The
   button sits in the bottom-right of the card OUTSIDE the masked inner
   wrapper so it stays sharp while the text content fades behind it. */
.vx-cmp-risk-toggle{position:absolute;bottom:6px;right:8px;background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.45);color:#fff;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:6px 12px;border-radius:14px;cursor:pointer;display:none;z-index:2;line-height:1;transition:background .15s ease,transform .15s ease;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}
.vx-cmp-risk-toggle:hover{background:rgba(255,255,255,.32)}
.vx-cmp-risk-toggle:active{transform:scale(.96)}
.vx-cmp-risk-card.has-overflow .vx-cmp-risk-toggle{display:inline-block}
/* Expanded state — drop the height cap and the fade, let content flow.
   Bottom padding leaves room for the toggle to sit cleanly. */
.vx-cmp-risk-card.is-expanded{height:auto}
.vx-cmp-risk-card.is-expanded .vx-cmp-risk-card-inner{-webkit-mask-image:none;mask-image:none;height:auto;padding-bottom:42px}
.vx-cmp-risk-evidence{font-style:italic;font-size:.8rem;line-height:1.5;margin:0 0 8px;padding-left:10px;border-left:2px solid rgba(255,255,255,.45);color:#fff;text-align:left}
.vx-cmp-risk-meaning{font-size:.86rem;line-height:1.5;color:#fff;text-align:left}
.vx-cmp-risk-sev-label{display:inline-block;font-family:'DM Mono',monospace;font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.85);margin-bottom:6px}
/* 2026-05-04: Matrix-by-dimension layout — replaces the 4-col table.
   Each dimension is its own labeled section bar with 3 vendor cells
   below, preserving row-by-row comparison while keeping the 3-vendor
   column rhythm alignment with the upload row. The "advantage" indicator
   becomes a small badge on the winning vendor's cell instead of a
   highlighted table cell. */
.vx-cmp-matrix-stacked{margin-bottom:1.5rem;border-top:1px solid rgba(44,74,62,.18);border-bottom:1px solid rgba(44,74,62,.18)}
.vx-cmp-matrix-row{display:flex;flex-direction:column}
.vx-cmp-matrix-row+.vx-cmp-matrix-row{border-top:1px solid rgba(44,74,62,.12)}
.vx-cmp-matrix-dim{font-family:'DM Mono',monospace;font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);padding:10px 16px 8px;background:rgba(242,235,224,0.35);border-bottom:1px solid rgba(44,74,62,.08)}
.vx-cmp-matrix-cells{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0}
/* Row height lock + content fade — every matrix cell is a fixed height
   so row top-edges stay aligned across the whole page while scrolling.
   Content that exceeds the height gets a soft mask-image fade so the
   couple sees the headline without misaligned rows. Tuned to ~4.5
   lines of body text visible (enough for the main point + 1-2 lines
   of supporting context). Matches the same mask-image pattern used by
   Insights Feedback for streaming output. */
.vx-cmp-matrix-cell{padding:12px 16px;border-right:1px solid rgba(44,74,62,.12);min-width:0;font-size:.86rem;color:var(--ink,#1c1c1c);line-height:1.5;text-align:left;word-break:break-word;position:relative;height:7em;box-sizing:border-box;overflow:hidden;-webkit-mask-image:linear-gradient(to bottom, black 78%, transparent 100%);mask-image:linear-gradient(to bottom, black 78%, transparent 100%)}
.vx-cmp-matrix-cell:last-child{border-right:none}
.vx-cmp-matrix-cell.is-advantage{background:rgba(58,107,89,.06)}
.vx-cmp-matrix-cell.is-empty{color:var(--text-muted,#88928d);font-style:italic}
.vx-cmp-matrix-adv-badge{display:inline-block;font-family:'DM Mono',monospace;font-size:.54rem;letter-spacing:.12em;text-transform:uppercase;color:var(--green,#2C4A3E);background:rgba(58,107,89,.12);padding:2px 7px;border-radius:10px;margin-bottom:6px;font-weight:500}

@media (max-width:767px){
 /* Mobile: vertical column rails become horizontal section bars between
    stacked vendor blocks so the 3-zone rhythm is preserved top-to-bottom. */
 .vx-cmp-risks-by-vendor{grid-template-columns:1fr}
 .vx-cmp-risks-col{border-right:none;border-bottom:1px solid rgba(44,74,62,.12)}
 .vx-cmp-risks-col:last-child{border-bottom:none}
 .vx-cmp-vendor-cards{grid-template-columns:1fr}
 .vx-cmp-vendor-cards>*{border-right:none;border-bottom:1px solid rgba(44,74,62,.12)}
 .vx-cmp-vendor-cards>*:last-child{border-bottom:none}
 .vx-cmp-matrix-cells{grid-template-columns:1fr}
 .vx-cmp-matrix-cell{border-right:none;border-bottom:1px solid rgba(44,74,62,.08)}
 .vx-cmp-matrix-cell:last-child{border-bottom:none}
}
.vx-cmp-actions-list{background:var(--white);border:1px solid var(--border-g);border-radius:12px;padding:18px 22px;margin-bottom:1rem}
.vx-cmp-actions-list h3{font-family:'Cormorant Garamond',serif;font-size:1.4rem;color:var(--green);margin:0 0 12px;font-weight:500}
.vx-cmp-action{display:flex;gap:14px;padding:12px 0;border-top:1px solid var(--border-g)}
.vx-cmp-action:first-of-type{border-top:none}
.vx-cmp-action-num{font-family:'DM Mono',monospace;font-size:1.3rem;color:var(--gold);font-weight:500;min-width:28px;line-height:1}
.vx-cmp-action-body{flex:1}
.vx-cmp-action-vendor{font-family:'DM Mono',monospace;font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:4px}
.vx-cmp-action-text{font-size:.94rem;color:var(--green);line-height:1.5;margin-bottom:4px;font-weight:500}
.vx-cmp-action-why{font-size:.82rem;color:var(--text-mid);line-height:1.5}
.vx-cmp-history-item{padding:12px 0;border-top:1px solid var(--border-g);font-size:.86rem;color:var(--text-mid);display:flex;gap:12px;align-items:baseline}
.vx-cmp-history-item .vx-cmp-history-meta{flex:1 1 auto;min-width:0}
.vx-cmp-history-item .vx-cmp-history-actions{flex:0 0 auto;display:flex;gap:6px;align-items:center}
.vx-cmp-history-item button{background:transparent;border:1px solid rgba(44,74,62,.22);border-radius:6px;padding:4px 10px;font-size:.74rem;color:var(--green);cursor:pointer}
.vx-cmp-history-item button:hover{background:var(--green-pale)}

/* 2026-05-04: Per-row delete (× button) — subtle until hover, two-tap
   confirm to prevent misclicks. Pairs with a 10-second undo toast.  */
.vx-cmp-history-del{padding:4px 9px!important;font-size:1rem!important;line-height:1;color:var(--text-muted)!important;border-color:rgba(44,74,62,.12)!important;opacity:.45;transition:opacity .15s ease,background .15s ease,border-color .15s ease,color .15s ease}
.vx-cmp-history-item:hover .vx-cmp-history-del{opacity:1}
.vx-cmp-history-del:hover{background:rgba(185,64,64,.06)!important;border-color:rgba(185,64,64,.4)!important;color:#B94040!important}
.vx-cmp-history-del.is-armed{background:#B94040!important;border-color:#B94040!important;color:#fff!important;font-size:.72rem!important;padding:4px 11px!important;opacity:1;letter-spacing:.04em}
@media (hover:none){
 .vx-cmp-history-del{opacity:1}
}

/* "Clear all" link at the bottom of the history panel — same two-tap
   confirm pattern. Sits below the row list, slightly separated. */
.vx-cmp-history-clear-all-row{padding:14px 0 4px;text-align:right;border-top:1px solid var(--border-g)}
.vx-cmp-history-clear-all{background:transparent!important;border:none!important;padding:4px 6px!important;font-family:var(--ff-b,'DM Sans',sans-serif)!important;font-size:.8rem!important;letter-spacing:normal;color:var(--text-muted)!important;cursor:pointer;transition:color .15s ease}
.vx-cmp-history-clear-all:hover{color:#B94040!important;text-decoration:underline;background:transparent!important}
.vx-cmp-history-clear-all.is-armed{color:#B94040!important;text-decoration:underline;font-weight:500}

/* 2026-05-04 — DocReview "Add to Budget" banner. Sits between the gauge
   and the risks grid; populated by renderResults when the model returned
   a positive contract_total_value + inferred_category. */
.vx-dr-stb{margin:0 0 1.25rem;padding:14px 18px;background:rgba(58,107,89,.05);border:1px solid rgba(58,107,89,.22);border-radius:10px;display:flex;flex-direction:column;gap:8px}
.vx-dr-stb-eyebrow{font-family:'DM Mono',monospace;font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
.vx-dr-stb-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.vx-dr-stb-meta{flex:1 1 240px;min-width:0;display:flex;flex-direction:column;gap:3px}
.vx-dr-stb-place{margin:2px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.78rem;line-height:1.5;color:var(--text-mid,#4A4A4A)}
.vx-dr-stb-vendor{font-family:'Cormorant Garamond',serif;font-size:1.1rem;color:var(--green,#2C4A3E);font-weight:500;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vx-dr-stb-detail{display:flex;align-items:baseline;gap:8px;color:var(--text-mid,#5a5a5a);font-size:.9rem;flex-wrap:wrap}
.vx-dr-stb-amount{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--green,#2C4A3E)}
.vx-dr-stb-sep{color:var(--text-muted,#88928d)}
/* Premium: room-block exposure contingency line under the Add-to-Budget card */
.vx-dr-stb-contingency{margin-top:10px;padding:8px 12px;border-left:2.5px solid var(--gold,#C8A96E);background:rgba(200,169,110,.08);border-radius:0 6px 6px 0;font-size:.82rem;line-height:1.5;color:var(--text-mid,#5a5a5a)}
.vx-dr-stb-contingency strong{color:var(--gold-deep,#A07840);font-weight:600}
.vx-dr-stb-cat{font-style:italic}
.vx-dr-stb-btn{flex:0 0 auto;font-family:'DM Sans',sans-serif;font-size:.86rem;font-weight:500;background:var(--green,#2C4A3E);color:#fff;border:none;padding:10px 20px;border-radius:24px;cursor:pointer;transition:background .15s ease,transform .12s ease;white-space:nowrap}
.vx-dr-stb-btn:hover{background:var(--green-dark,#1F3A2F);transform:translateY(-1px);box-shadow:0 3px 12px rgba(44,74,62,.18)}

/* 2026-05-04 — Send-to-Budget toast. Used by DocReview, DocCompare,
   and (future) Vendor IQ Top-5: a message + optional "Open Budget" CTA.
   Same fixed-position bottom-center layout as the DocCompare undo toast
   so the bottom-of-viewport area becomes a consistent "system message"
   zone across the platform.
   2026-08-04 — the two-button CONFIRM variant (.vx-stb-actions/-ok/-cancel)
   was removed with the package-price write it guarded; the lock modal is now
   the only confirmation on this path. Notice-only styles remain. */
.vx-stb-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,16px);background:var(--green,#2C4A3E);color:#fff;padding:14px 20px;border-radius:18px;font-family:'DM Sans',sans-serif;font-size:.92rem;display:flex;align-items:center;gap:18px;box-shadow:0 6px 24px rgba(0,0,0,.22);z-index:10001;opacity:0;transition:opacity .22s ease,transform .22s ease;pointer-events:none;max-width:calc(100vw - 32px);flex-wrap:wrap;line-height:1.45}
.vx-stb-toast.is-visible{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.vx-stb-msg{flex:1 1 auto;min-width:0}
.vx-stb-msg strong{font-weight:500;color:#F4ECD8}
.vx-stb-toast--success .vx-stb-msg{font-weight:400}
.vx-stb-open-budget{background:rgba(255,255,255,.18);border:1px solid rgba(255,255,255,.35);color:#fff;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:6px 13px;border-radius:18px;cursor:pointer;transition:background .15s ease}
.vx-stb-open-budget:hover{background:rgba(255,255,255,.3)}

/* Undo toast — fixed at bottom-center, slides in from below on show.
   Self-contained: dismiss on undo-click or after 10s timeout. */
.vx-cmp-undo-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,16px);background:var(--green,#2C4A3E);color:#fff;padding:11px 16px;border-radius:32px;font-family:'DM Sans',sans-serif;font-size:.86rem;display:flex;align-items:center;gap:14px;box-shadow:0 4px 18px rgba(0,0,0,.16);z-index:10000;opacity:0;transition:opacity .22s ease,transform .22s ease;pointer-events:none}
.vx-cmp-undo-toast.is-visible{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.vx-cmp-undo-msg{flex:0 0 auto}
.vx-cmp-undo-btn{background:rgba(255,255,255,.18)!important;border:1px solid rgba(255,255,255,.3)!important;color:#fff!important;font-family:var(--ff-b,'DM Sans',sans-serif)!important;font-size:.8rem!important;letter-spacing:normal;padding:5px 13px!important;border-radius:18px;cursor:pointer;transition:background .15s ease}
.vx-cmp-undo-btn:hover{background:rgba(255,255,255,.3)!important}
@media (max-width:767px){
 /* 2026-05-04: stack both grids on mobile so column 1 (upload + card) sits
    above column 2 (upload + card) sits above column 3, matching desktop's
    left-to-right column order top-to-bottom. */
 .vx-cmp-zones{grid-template-columns:1fr;gap:10px}
 .vx-cmp-vendor-cards{grid-template-columns:1fr;gap:10px}
}
@media (max-width:767px){
 .vx-cmp-actions{flex-direction:column}
 .vx-cmp-actions button{width:100%}
 .vx-cmp-flags-grid{grid-template-columns:1fr}
}

/* ═══ Profile page (launched from the user-name pill in the header) ═ */
#section-account{padding-bottom:80px}
.vx-profile-wrap{max-width:920px;margin:0 auto;padding:2.5rem 1.5rem 3rem}
.vx-profile-head{display:flex;gap:1.5rem;align-items:flex-start;margin-bottom:2rem;flex-wrap:wrap}
.vx-profile-back{appearance:none;background:transparent;border:1px solid var(--border-g);border-radius:999px;padding:7px 14px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;color:var(--text-mid);cursor:pointer;transition:all .15s;flex-shrink:0}
.vx-profile-back:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-profile-h1{font-family:var(--ff-d);font-size:clamp(2rem,4.5vw,3rem);color:var(--green);font-weight:400;line-height:1.1;margin:0 0 1rem}
.vx-profile-h1 em{color:var(--gold);font-style:italic}
.vx-profile-sub{font-size:1rem;color:var(--text-mid);line-height:1.65;max-width:640px;margin:0}
.vx-profile-welcome{display:flex;align-items:flex-start;gap:16px;padding:1.25rem 1.5rem;margin-bottom:1.5rem;background:linear-gradient(135deg,rgba(200,169,110,.1),rgba(90,140,122,.08));border:1px solid rgba(200,169,110,.35);border-radius:12px}
.vx-profile-welcome[hidden]{display:none}
.vx-profile-welcome-icon{font-size:1.6rem;line-height:1;flex-shrink:0;padding-top:2px}
.vx-profile-welcome h3{font-family:var(--ff-d);font-size:1.2rem;color:var(--green);margin:0 0 6px;font-weight:500}
.vx-profile-welcome p{font-size:.9rem;color:var(--text-mid);line-height:1.55;margin:0}
.vx-profile-welcome a{color:var(--green);border-bottom:1px dotted rgba(44,74,62,.4);text-decoration:none}
.vx-profile-welcome a:hover{border-bottom-color:var(--green)}
.vx-profile-form{display:flex;flex-direction:column;gap:1.5rem}
/* 2026-05-09: min-width:0 overrides the browser-default `min-width:min-content`
   on <fieldset> elements. Without this, a wide child (e.g. a Reports table)
   forces the fieldset wider than its parent form, defeating any inner
   overflow:auto + horizontal-scroll container. The fieldset would otherwise
   "win" against its parent's width and the table never scrolls. */
.vx-profile-fieldset{border:1px solid var(--border-g);border-radius:14px;padding:1.5rem 1.75rem;background:var(--white);box-shadow:0 2px 10px rgba(44,74,62,.04);min-width:0}
.vx-profile-fieldset legend{padding:0 12px;margin-left:-4px;font-family:var(--ff-d);font-size:1.35rem;color:var(--green);font-weight:500}
.vx-profile-fieldset legend em{color:var(--gold);font-style:italic}
.vx-profile-help{font-size:.85rem;color:var(--text-muted);line-height:1.55;margin:0 0 1.25rem;max-width:720px}
.vx-profile-grid{display:grid;gap:14px;margin-top:4px}
.vx-profile-grid-2{grid-template-columns:repeat(2,1fr)}
.vx-profile-grid-3{grid-template-columns:repeat(3,1fr)}
.vx-profile-grid-4{grid-template-columns:repeat(4,1fr)}
.vx-profile-col-span-2{grid-column:span 2}
.vx-profile-field{display:flex;flex-direction:column;gap:5px;min-width:0}
.vx-profile-field>span{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);font-weight:500}
.vx-profile-note{font-weight:400;text-transform:none;letter-spacing:0;color:var(--text-muted);opacity:.75;font-size:.68rem}
.vx-profile-field input,.vx-profile-field select,.vx-profile-field textarea{width:100%;box-sizing:border-box;padding:10px 12px;border:1.5px solid var(--border);border-radius:8px;background:var(--cream);font-family:var(--ff-b);font-size:.95rem;color:var(--ink);transition:border-color .15s,background .15s}
.vx-profile-field input:focus,.vx-profile-field select:focus,.vx-profile-field textarea:focus{outline:none;border-color:var(--green);background:var(--white)}
.vx-profile-toggle{display:flex;align-items:center;gap:10px;margin:1rem 0;padding:.75rem 1rem;background:rgba(200,169,110,.06);border:1px solid rgba(200,169,110,.25);border-radius:10px;cursor:pointer;font-size:.9rem;color:var(--text-mid)}
.vx-profile-toggle input{width:18px;height:18px;accent-color:var(--green);flex-shrink:0}
.vx-profile-toggle strong{color:var(--green)}
.vx-profile-destination{opacity:.5;pointer-events:none;transition:opacity .2s}
.vx-profile-destination.is-active{opacity:1;pointer-events:auto}
.vx-profile-pref-row{display:flex;align-items:flex-start;gap:12px;margin-bottom:12px;flex-wrap:wrap}
.vx-profile-pref-row>label{min-width:90px;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);padding-top:6px}
.vx-profile-chips{display:flex;flex-wrap:wrap;gap:6px;flex:1;min-width:0}
.vx-profile-chips button{appearance:none;background:transparent;border:1px solid var(--border-g);border-radius:999px;padding:6px 12px;font-family:var(--ff-b);font-size:.82rem;color:var(--text-mid);cursor:pointer;transition:all .15s}
.vx-profile-chips button:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-profile-chips button.is-on{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-profile-fieldset-legal{background:rgba(44,74,62,.02)}
.vx-profile-legal-row{display:flex;flex-wrap:wrap;gap:1.25rem;margin-bottom:1rem;font-size:.88rem}
.vx-profile-legal-row a{color:var(--green);text-decoration:none;border-bottom:1px dotted rgba(44,74,62,.3);transition:border-color .15s}
.vx-profile-legal-row a:hover{border-bottom-color:var(--green)}
.vx-profile-legal-actions{display:flex;gap:10px;flex-wrap:wrap}
.vx-profile-signout,.vx-profile-delete{appearance:none;padding:9px 16px;border-radius:8px;font-family:var(--ff-b);font-size:.85rem;cursor:pointer;transition:all .15s}
.vx-profile-signout{background:var(--white);border:1px solid var(--border-g);color:var(--text-mid)}
.vx-profile-signout:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-profile-delete{background:var(--white);border:1px solid rgba(185,64,64,.3);color:#B94040}
.vx-profile-delete:hover{background:rgba(185,64,64,.06);border-color:#B94040}
.vx-profile-save-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1.25rem 0;position:sticky;bottom:0;background:linear-gradient(to top,var(--cream) 60%,rgba(250,247,242,0));margin-top:.5rem;z-index:2}
.vx-profile-save-status{font-size:.85rem;color:var(--text-muted);flex:1}
.vx-profile-save-status.is-ok{color:#3d6a58}
.vx-profile-save-status.is-err{color:#B94040}
.vx-profile-save-btn{min-width:180px;padding:12px 26px !important;min-height:44px}
.vx-profile-save-btn:disabled{opacity:.6;cursor:not-allowed}
/* Soft-force: small "Profile incomplete" nudge on step nodes when new user hasn't saved yet */
.vx-profile-incomplete-dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--gold);margin-left:4px;vertical-align:middle;animation:blink-dot 1.8s ease-in-out infinite}
/* Tablet: keep 2-up where it makes sense, collapse 3/4-up to 2. */
@media (min-width: 620px) and (max-width: 1024px){
 .vx-profile-grid-3{grid-template-columns:repeat(2,1fr)}
 .vx-profile-grid-4{grid-template-columns:repeat(2,1fr)}
 .vx-profile-wrap{padding:2rem 1.5rem}
 .vx-profile-head{gap:1rem}
}
/* Mobile */
@media (max-width:767px){
 .vx-profile-wrap{padding:1.75rem 1.25rem 2rem}
 .vx-profile-fieldset{padding:1.25rem}
 .vx-profile-fieldset legend{font-size:1.15rem}
 .vx-profile-grid-2,.vx-profile-grid-3,.vx-profile-grid-4{grid-template-columns:1fr}
 .vx-profile-col-span-2{grid-column:span 1}
 .vx-profile-save-row{flex-direction:column-reverse;align-items:stretch;position:sticky;bottom:0;padding:.75rem 0 .75rem;background:var(--cream);box-shadow:0 -4px 16px rgba(44,74,62,.08)}
 .vx-profile-save-btn{width:100%}
 .vx-profile-legal-actions{flex-direction:column}
 .vx-profile-legal-actions button{width:100%}
 /* iOS: 16px+ on inputs prevents auto-zoom on focus */
 .vx-profile-field input,.vx-profile-field select,.vx-profile-field textarea{font-size:16px}
 .vx-profile-head{flex-direction:column;gap:1rem}
 .vx-profile-h1{font-size:1.75rem}
 .vx-profile-welcome{flex-direction:column;gap:10px;padding:1rem 1.25rem}
 .vx-profile-welcome h3{font-size:1.05rem}
 .vx-profile-welcome p{font-size:.85rem}
 .vx-profile-pref-row{flex-direction:column;gap:6px}
 .vx-profile-pref-row>label{min-width:0}
 .vx-profile-toggle{font-size:.85rem}
 .vx-profile-destination{margin-top:12px}
}
/* Touch-friendly tap targets */
@media (pointer:coarse){
 .vx-profile-chips button{min-height:36px;padding:7px 14px}
 .vx-profile-save-btn{min-height:48px}
 .vx-profile-back{min-height:36px;padding:8px 16px}
}

/* ═══ Account page (4-tab shell: Settings / Security / Communities / Sign Out) ═══ */
.vx-acc-wrap{max-width:920px;margin:0 auto;padding:2.5rem 1.5rem 3rem}
.vx-acc-head{display:flex;gap:1.25rem;align-items:flex-start;margin-bottom:1.5rem;flex-wrap:wrap}
.vx-acc-head-main{flex:1;min-width:200px}
.vx-acc-h1{font-family:var(--ff-d);font-size:clamp(1.9rem,4vw,2.6rem);color:var(--green);font-weight:400;line-height:1.1;margin:0}
/* Active wedding banner: surfaces which wedding you're editing when
   the account has multiple memberships. Subtle gold underline keeps
   it editorial; not loud. */
/* Global save-all button: prominent green pill on the right of the
   header. Sits next to the save-chip area so it's always reachable
   without scrolling through every fieldset. */
.vx-acc-h1 em{color:var(--gold);font-style:italic}
.vx-acc-back{appearance:none;background:transparent;border:1px solid var(--border-g);border-radius:999px;padding:7px 14px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;color:var(--text-mid);cursor:pointer;transition:all .15s;flex-shrink:0}
.vx-acc-back:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-acc-save-chip{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:6px 12px;border-radius:999px;background:rgba(90,140,122,.14);color:#3d6a58;border:1px solid rgba(90,140,122,.3);align-self:center;transition:opacity .3s}
.vx-acc-save-chip[hidden]{display:none}
.vx-acc-save-chip.is-err{background:rgba(185,64,64,.08);color:#B94040;border-color:rgba(185,64,64,.3)}

/* Tab bar — NorthOaks-inspired: inactive = sage pill, active = underlined green on white */
.vx-acc-tabs{display:flex;gap:6px;border-bottom:1.5px solid var(--border-g);margin-bottom:1.5rem;overflow-x:auto;scrollbar-width:none}
/* 2026-05-09: drag-to-reorder affordances. Only added when sadmin
   hydrates (vx-acc-tabs-draggable class set by VerdeauxTabOrder).
   Subscribers see the default click-to-switch behavior unchanged. */
.vx-acc-tabs-draggable .vx-acc-tab{cursor:grab}
.vx-acc-tabs-draggable .vx-acc-tab:active{cursor:grabbing}
.vx-acc-tab-dragging{opacity:.4}

/* 2026-05-29 — "How I work" pill removed. Stephen: "the expandable help
   is also available." The trust/policy info is reachable via the Help
   slide-out panel (js/vera-help-panel.js) and the FAQ on
   /early-access.html. CSS rules .vx-info-pill / .vx-info-i /
   .vx-info-label / .vx-info-pill-vera / .vx-chat-head .vx-info-pill
   removed. The VerdeauxPolicy module + recommendation-policy.js stay —
   they're harmless and the policy text still serves the FAQ page. */

/* Policy modal CSS retained because nothing on the signed-in app
   currently triggers it, but the VerdeauxPolicy() open() function and
   data-vx-policy-open listener stay live in case any future surface
   wants to summon it. */
.vx-policy-modal-backdrop{position:fixed;inset:0;background:rgba(22,32,50,.45);display:flex;align-items:center;justify-content:center;z-index:9999;padding:20px;animation:vxPolicyFadeIn .22s ease}
@keyframes vxPolicyFadeIn{from{opacity:0}to{opacity:1}}
/* 2026-05-14 — Mobile policy-modal fixes:
   1. Use svh (small viewport height) so the max-height accounts for
      iOS browser chrome / Capacitor WKWebView dynamic safe-area, not
      the unreliable vh which can leave the foot button off-screen
      after the URL bar collapses.
   2. position:relative on the modal itself so the absolute-positioned
      × close button below has the right containing block.
   3. Explicit min-height:0 so the inner scroll region can shrink. */
.vx-policy-modal{position:relative;background:var(--cream);border:1px solid rgba(200,169,110,.32);border-radius:18px;max-width:560px;width:100%;max-height:85svh;overflow:auto;box-shadow:0 24px 64px rgba(28,28,28,.22);padding:0}
/* Top-right × close — always visible regardless of scroll position.
   The visitor previously had to scroll all the way to the foot to
   find the "Got it" button, and on mobile the foot fell below the
   visible viewport, making the modal feel inescapable. The × is the
   universal "I want out" affordance — always tappable, sticky to the
   modal corner via position:sticky inside the scrollable container. */
.vx-policy-modal-x{position:absolute;top:14px;right:14px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;background:rgba(250,247,242,.92);border:1px solid rgba(200,169,110,.32);border-radius:50%;color:var(--text-mid);font-size:18px;line-height:1;cursor:pointer;padding:0;z-index:2;transition:background .15s,color .15s,border-color .15s;-webkit-tap-highlight-color:transparent}
.vx-policy-modal-x:hover,.vx-policy-modal-x:focus-visible{background:var(--green);color:#fff;border-color:var(--green);outline:none}
.vx-policy-modal-head{padding:28px 56px 18px 32px;border-bottom:1px solid rgba(200,169,110,.18)}
.vx-policy-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);font-weight:500;margin-bottom:8px}
.vx-policy-title{font-family:var(--ff-d);font-size:1.6rem;font-weight:400;color:var(--green);margin:0;line-height:1.15}
.vx-policy-title em{font-style:italic;color:var(--gold)}
.vx-policy-modal-body{padding:22px 32px 26px}
.vx-policy-qa + .vx-policy-qa{margin-top:22px;padding-top:22px;border-top:1px solid rgba(200,169,110,.18)}
.vx-policy-q{font-family:var(--ff-d);font-size:1.1rem;font-weight:500;color:var(--green);margin:0 0 10px;line-height:1.35}
.vx-policy-a{font-family:var(--ff-b);font-size:.92rem;color:var(--text-mid);line-height:1.65}
.vx-policy-a p{margin:0 0 10px}
.vx-policy-a p:last-child{margin-bottom:0}
.vx-policy-a strong{color:var(--ink);font-weight:500}
.vx-policy-a em{color:var(--gold-deep);font-style:italic}
.vx-policy-modal-foot{padding:16px 32px 24px;display:flex;justify-content:flex-end;border-top:1px solid rgba(200,169,110,.12)}
.vx-policy-close{appearance:none;font-family:var(--ff-b);font-size:.86rem;background:var(--green);color:#fff;border:1px solid var(--green);padding:9px 22px;border-radius:8px;cursor:pointer;transition:background .15s}
.vx-policy-close:hover{background:#1f3a30}
/* 2026-05-14 — Focus ring for the foot "Got it" button. The
   top-right × already has its own :focus-visible style. */
.vx-policy-close:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:3px}
@media (max-width:560px){
 .vx-policy-modal{max-height:90svh}
 .vx-policy-modal-head{padding:22px 52px 14px 22px}
 .vx-policy-modal-body{padding:18px 22px 22px}
 .vx-policy-modal-foot{padding:14px 22px calc(20px + env(safe-area-inset-bottom, 0px))}
 .vx-policy-title{font-size:1.4rem}
 .vx-policy-modal-x{top:10px;right:10px;width:32px;height:32px}
}
.vx-acc-tabs::-webkit-scrollbar{display:none}
.vx-acc-tab{appearance:none;background:transparent;border:none;padding:12px 18px;font-family:var(--ff-b);font-size:.95rem;color:var(--text-mid);cursor:pointer;display:inline-flex;align-items:center;gap:8px;border-bottom:2px solid transparent;margin-bottom:-1.5px;white-space:nowrap;transition:color .15s,border-color .15s}
/* 2026-05-09: explicit override of the rule above for tabs whose `hidden`
   attribute is set. Otherwise `display:inline-flex` wins against the user-
   agent's `[hidden]{display:none}` and admin-only tabs (Reports, Lab,
   Users) leak to subscribers. */
.vx-acc-tab[hidden]{display:none}
.vx-acc-tab:hover{color:var(--green)}
.vx-acc-tab.is-active{color:var(--green);border-bottom-color:var(--green);font-weight:500}
.vx-acc-tab-signout{margin-left:auto;color:var(--text-muted)}
.vx-acc-progress{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;padding:2px 8px;border-radius:999px;background:rgba(44,74,62,.06);color:var(--text-muted);font-weight:500;min-width:32px;text-align:center}
.vx-acc-tab.is-active .vx-acc-progress{background:rgba(90,140,122,.14);color:#3d6a58}
.vx-acc-progress[hidden]{display:none}
.vx-acc-progress.is-complete{background:rgba(90,140,122,.14);color:#3d6a58}

/* Panels */
.vx-acc-panel{display:none}
.vx-acc-panel.is-active{display:block}

/* Welcome nudge (reuses vx-profile-welcome styles) */

/* Per-fieldset save row (inside each settings/security/communities fieldset)
   2026-05-04: with the "Save this section" button retired, the row is now
   a single inline status indicator. Centered + slightly bolder so testers
   see "All changes saved" / "Saving…" / "✓ Saved just now" clearly. */
.vx-acc-fieldset-save{display:flex;align-items:center;justify-content:flex-end;gap:1rem;margin-top:1rem;padding-top:.85rem;border-top:1px dashed rgba(44,74,62,.1)}
.vx-acc-field-saved{font-size:.82rem;color:var(--text-muted);flex:1;text-align:right;font-family:var(--ff-b);transition:color .2s}
.vx-acc-field-saved.is-ok{color:#3d6a58}
.vx-acc-field-saved.is-err{color:#B94040;font-weight:500}
.vx-acc-field-saved.is-clickable{cursor:pointer;text-decoration:underline}
.vx-acc-field-saved.is-clickable:hover{color:#8a2727}
.vx-acc-field-saved.is-clickable:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:3px;border-radius:4px}
.vx-acc-save-btn{appearance:none;background:var(--green);color:var(--white);border:1px solid var(--green);border-radius:8px;padding:9px 18px;font-family:var(--ff-b);font-size:.85rem;font-weight:500;cursor:pointer;transition:all .15s;min-height:40px}
.vx-acc-save-btn:hover{background:#234e40;border-color:#234e40}
.vx-acc-save-btn:disabled{opacity:.6;cursor:not-allowed}
.vx-acc-save-btn-secondary{background:var(--white);color:var(--text-mid);border:1px solid var(--border-g)}
.vx-acc-save-btn-secondary:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-acc-save-btn-primary{background:var(--gold);border-color:var(--gold);color:#2b2012}
.vx-acc-save-btn-primary:hover{background:#b4944d;border-color:#b4944d;color:#fff}

/* Security: readonly email, method note, 2FA opt-in */
.vx-acc-readonly{background:rgba(44,74,62,.03) !important;color:var(--text-muted) !important;cursor:not-allowed}
.vx-acc-method-note{display:flex;align-items:flex-start;gap:12px;padding:.85rem 1rem;background:var(--cream);border:1px solid var(--border-g);border-radius:10px}
.vx-acc-method-icon{font-size:1.2rem;line-height:1;flex-shrink:0;padding-top:2px;color:var(--green)}
.vx-acc-method-note strong{display:block;color:var(--green);font-weight:500;margin-bottom:2px;font-size:.9rem}
.vx-acc-method-note .vx-profile-note{font-size:.78rem;margin-top:2px}
.vx-acc-2fa-opt{display:inline-flex;align-items:center;gap:8px;font-size:.78rem;color:var(--text-mid);margin-left:auto;flex-shrink:0;cursor:pointer}
.vx-acc-2fa-opt input{width:16px;height:16px;accent-color:var(--green)}

/* Danger zone (Delete my account at bottom of Settings) */
.vx-acc-danger-zone{border-color:rgba(185,64,64,.25) !important;background:rgba(185,64,64,.02) !important}
.vx-acc-danger-zone legend{color:#B94040 !important}
.vx-acc-danger-zone legend em{color:#B94040 !important}
.vx-acc-danger-zone p{font-size:.88rem;color:var(--text-mid);line-height:1.6;margin:0 0 .9rem}
.vx-acc-danger-hint{background:rgba(200,169,110,.08);border-left:3px solid var(--gold);padding:.75rem 1rem;border-radius:0 8px 8px 0;font-size:.85rem !important}
.vx-acc-danger-hint a{color:var(--green);text-decoration:none;border-bottom:1px dotted rgba(44,74,62,.4)}
.vx-acc-danger-hint a:hover{border-bottom-color:var(--green)}
.vx-acc-danger-btn{margin-top:.5rem}

/* ═══ Feedback Log (2026-05-04) ════════════════════════════════════
   Submission form + per-user list + admin (sadmin) all-feedback view.
   Lives on the Account modal, replacing the retired Insight Filters. */
.vx-fb-form{display:flex;flex-direction:column;gap:14px}
.vx-fb-row{display:flex;flex-direction:column;gap:6px}
.vx-fb-label{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted)}
.vx-fb-chips{display:flex;flex-wrap:wrap;gap:6px}
.vx-fb-chip{padding:6px 14px;border:1px solid rgba(44,74,62,.18);background:#fff;color:var(--text-mid);border-radius:100px;font-family:var(--ff-b);font-size:.78rem;cursor:pointer;transition:all .15s}
.vx-fb-chip:hover{border-color:var(--green);color:var(--green)}
.vx-fb-chip.is-active{background:var(--green);color:#fff;border-color:var(--green)}
.vx-fb-select,.vx-fb-textarea{width:100%;padding:9px 12px;border:1px solid var(--border);border-radius:8px;font-family:var(--ff-b);font-size:.92rem;color:var(--ink);background:#fff;box-sizing:border-box}
.vx-fb-textarea{min-height:96px;line-height:1.55;resize:vertical}
.vx-fb-counter{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.06em;color:var(--text-muted);text-align:right}
.vx-fb-actions{display:flex;align-items:center;justify-content:flex-end;gap:1rem;margin-top:.4rem;padding-top:.6rem;border-top:1px dashed rgba(44,74,62,.1)}

/* 2026-05-09: rating-first form. Stars at top, soft labels, App Store feel. */
.vx-fb-stars-row{flex-direction:row;align-items:center;gap:14px}
.vx-fb-stars{display:inline-flex;gap:4px}
.vx-fb-star{appearance:none;background:none;border:0;padding:2px 4px;font-size:1.85rem;line-height:1;color:rgba(44,74,62,.18);cursor:pointer;transition:color .12s,transform .12s;font-family:inherit}
.vx-fb-star:hover{color:var(--gold);transform:translateY(-1px)}
.vx-fb-star.is-on{color:var(--gold-deep)}
.vx-fb-star:focus-visible{outline:2px solid var(--gold);outline-offset:2px;border-radius:4px}
.vx-fb-stars-label{font-family:var(--ff-m);font-size:.7rem;letter-spacing:.06em;color:var(--text-muted);transition:color .15s}
.vx-fb-label-soft{font-family:var(--ff-b);font-size:.85rem;letter-spacing:0;text-transform:none;color:var(--text-mid);font-weight:500}

/* 2026-05-09: bounded vertical scroll so long lists don't push the rest
   of the Account modal off-screen. Used by both the user's own list and
   the sadmin all-feedback admin list. */
.vx-fb-list{display:flex;flex-direction:column;gap:10px;margin-top:8px;max-height:55vh;overflow-y:auto;padding-right:4px}
.vx-fb-item{border:1px solid rgba(200,169,110,.22);border-radius:10px;background:rgba(250,247,242,.45);overflow:hidden;transition:border-color .15s}
.vx-fb-item:hover{border-color:rgba(200,169,110,.4)}
.vx-fb-item-head{display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;background:transparent;border:0;width:100%;text-align:left}
.vx-fb-kind-chip{flex-shrink:0;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:2px 8px;border-radius:100px;font-weight:500}
.vx-fb-kind-chip[data-kind="bug"]      {background:rgba(178,90,90,.12);color:#a25050}
.vx-fb-kind-chip[data-kind="idea"]     {background:rgba(200,169,110,.15);color:var(--gold-deep)}
.vx-fb-kind-chip[data-kind="usability"]{background:rgba(120,140,170,.14);color:#5a6b88}
.vx-fb-kind-chip[data-kind="question"] {background:rgba(90,140,122,.14);color:var(--green)}
.vx-fb-kind-chip[data-kind="other"]    {background:rgba(44,74,62,.06);color:var(--text-mid)}
.vx-fb-status-chip{flex-shrink:0;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:2px 8px;border-radius:100px;font-weight:500;background:rgba(44,74,62,.06);color:var(--text-mid)}
.vx-fb-status-chip[data-status="submitted"]  {background:rgba(44,74,62,.06);color:var(--text-mid)}
.vx-fb-status-chip[data-status="triaged"]    {background:rgba(120,140,170,.14);color:#5a6b88}
.vx-fb-status-chip[data-status="in_progress"]{background:rgba(200,169,110,.18);color:var(--gold-deep)}
.vx-fb-status-chip[data-status="shipped"]    {background:rgba(90,140,122,.16);color:var(--green)}
.vx-fb-status-chip[data-status="wont_fix"]   {background:rgba(178,90,90,.12);color:#a25050}
.vx-fb-status-chip[data-status="duplicate"]  {background:rgba(168,140,140,.12);color:#8a6e6e}
.vx-fb-item-title{flex:1;min-width:0;font-family:var(--ff-b);font-size:.88rem;color:var(--ink);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vx-fb-item-meta{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.06em;color:var(--text-muted);text-transform:uppercase;flex-shrink:0}
.vx-fb-item-body{display:none;padding:0 14px 14px;font-size:.86rem;line-height:1.6;color:var(--ink);white-space:pre-wrap}
.vx-fb-item.is-open .vx-fb-item-body{display:block}
.vx-fb-thread{margin-top:10px;padding-top:10px;border-top:1px dashed rgba(44,74,62,.12);display:flex;flex-direction:column;gap:8px}
.vx-fb-comment{padding:8px 12px;border-radius:8px;background:#fff;border:1px solid rgba(44,74,62,.08);font-size:.84rem;line-height:1.5}
.vx-fb-comment.is-admin{background:rgba(90,140,122,.06);border-color:rgba(90,140,122,.22)}
.vx-fb-comment-meta{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);margin-bottom:3px}
.vx-fb-comment.is-admin .vx-fb-comment-meta{color:var(--green)}
.vx-fb-reply-row{display:flex;gap:8px;align-items:flex-start;margin-top:6px}
.vx-fb-reply-row textarea{flex:1;min-height:50px;padding:7px 10px;border:1px solid var(--border);border-radius:8px;font-family:var(--ff-b);font-size:.86rem;line-height:1.5;resize:vertical}
.vx-fb-reply-row button{flex-shrink:0;padding:7px 14px;border:1px solid var(--green);background:var(--green);color:#fff;border-radius:8px;font-family:var(--ff-b);font-size:.78rem;font-weight:500;cursor:pointer;align-self:flex-end}
.vx-fb-reply-row button:hover{background:var(--green-deep,#244038)}

.vx-fb-empty{padding:18px;text-align:center;font-size:.86rem;color:var(--text-muted);font-style:italic}

/* Admin (sadmin) triage block */
.vx-fb-admin-fieldset legend em{color:var(--gold)}
.vx-fb-admin-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.vx-fb-admin-filter{display:flex;flex-wrap:wrap;gap:5px;flex:1}
.vx-fb-filter-chip{padding:4px 10px;border:1px solid rgba(44,74,62,.15);background:#fff;color:var(--text-mid);border-radius:100px;font-family:var(--ff-b);font-size:.66rem;cursor:pointer;transition:all .15s}
.vx-fb-filter-chip:hover{border-color:var(--green);color:var(--green)}
.vx-fb-filter-chip.is-active{background:var(--green);color:#fff;border-color:var(--green)}
.vx-fb-admin-controls{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;padding-top:10px;border-top:1px dashed rgba(44,74,62,.12)}
.vx-fb-admin-controls label{display:flex;flex-direction:column;gap:3px;font-family:var(--ff-m);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted)}
.vx-fb-admin-controls select,.vx-fb-admin-controls input{padding:6px 10px;border:1px solid var(--border);border-radius:6px;font-family:var(--ff-b);font-size:.82rem;color:var(--ink);background:#fff;text-transform:none;letter-spacing:0}
.vx-fb-admin-controls .vx-fb-dup-input{min-width:180px}
.vx-fb-submitter-tag{display:inline-block;padding:1px 7px;border-radius:100px;background:rgba(44,74,62,.04);color:var(--text-muted);font-family:var(--ff-m);font-size:.58rem;letter-spacing:.04em}

/* ═══ Reports tab — sadmin only (2026-05-04) ════════════════════════
   Repository of admin reports. List sits at top; selected report
   renders into #vxRptRender below. Tabular layouts use plain HTML
   tables with sticky header + zebra rows for readability. */
.vx-rpt-list{display:flex;flex-direction:column;gap:8px;margin-top:6px}
.vx-rpt-card{display:flex;align-items:center;gap:14px;padding:13px 16px;border:1px solid rgba(200,169,110,.22);border-radius:10px;background:rgba(250,247,242,.45);cursor:pointer;text-align:left;width:100%;transition:all .15s}
.vx-rpt-card:hover:not(:disabled){border-color:var(--green);background:#fff;transform:translateY(-1px)}
.vx-rpt-card:disabled{opacity:.55;cursor:not-allowed}
.vx-rpt-card.is-active{border-color:var(--green);background:#fff;box-shadow:0 1px 4px rgba(44,74,62,.06)}
.vx-rpt-card-body{flex:1;min-width:0}
.vx-rpt-card-title{font-family:var(--ff-d);font-size:1.05rem;font-weight:400;color:var(--green);line-height:1.2}
.vx-rpt-card-sub{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);margin-top:3px}
.vx-rpt-card-arrow{color:var(--gold-deep);font-size:1rem;flex-shrink:0}

.vx-rpt-summary{display:flex;flex-wrap:wrap;gap:14px;padding:12px 14px;background:rgba(90,140,122,.05);border:1px solid rgba(90,140,122,.18);border-radius:8px;margin-bottom:14px}
/* 2026-07-19 — section heading inside a report body (Conversion report). */
.vx-rpt-h{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;font-weight:500;color:var(--green,#2C4A3E);margin:18px 0 2px}
.vx-rpt-h:first-child{margin-top:0}
.vx-rpt-summary-stat{display:flex;flex-direction:column;gap:2px}
.vx-rpt-summary-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.vx-rpt-summary-value{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--money-ink,#33352f);line-height:1}

.vx-rpt-toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:10px}
.vx-rpt-toolbar select,.vx-rpt-toolbar input{padding:6px 10px;border:1px solid var(--border);border-radius:6px;font-family:var(--ff-b);font-size:.78rem;color:var(--ink);background:#fff}
.vx-rpt-toolbar .vx-rpt-spacer{flex:1}

/* 2026-05-09: bounded vertical scroll for long reports. The sticky `th`
   below positions against THIS container, so tables now scroll inside
   their own pane while the column headers stay pinned at the top. */
.vx-rpt-table-wrap{overflow:auto;max-height:65vh;border:1px solid var(--border);border-radius:8px;background:#fff}
/* 2026-05-09: width:100% + min-width:max-content lets the table fill the
   wrap when columns fit, but grow beyond it when they don't — so the wrap
   gets a horizontal scrollbar instead of crushing columns into the visible
   width. The wrap already has overflow:auto for both axes. */
.vx-rpt-table{width:100%;min-width:max-content;border-collapse:collapse;font-family:var(--ff-b);font-size:.84rem}
/* 2026-05-28 — Phase 4.2 sadmin Item Strategies admin UI. Inline-edit
   table for public.item_strategies; mirrors the read-only AI cost report
   styling but with form controls per row. */
.vx-is-toolbar{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}
.vx-is-filter{flex:1;min-width:240px;padding:7px 12px;border:1px solid var(--border-g);border-radius:6px;font-family:var(--ff-b);font-size:.86rem}
.vx-is-meta{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted)}
.vx-is-btn{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:7px 14px;border:1px solid var(--border-g);background:transparent;color:var(--charcoal);border-radius:6px;cursor:pointer}
.vx-is-btn:hover{border-color:var(--green);color:var(--green)}
.vx-is-btn.is-primary{background:var(--green);color:#fff;border-color:var(--green)}
.vx-is-btn.is-primary:disabled{background:rgba(44,74,62,.25);border-color:transparent;cursor:default}
.vx-is-table-wrap{overflow:auto;max-height:70vh;border:1px solid var(--border-g);border-radius:8px;background:#fff}
.vx-is-table{width:100%;min-width:max-content;border-collapse:collapse;font-family:var(--ff-b);font-size:.78rem}
.vx-is-table th{position:sticky;top:0;background:var(--cream);font-family:var(--ff-m);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-mid);padding:8px 10px;text-align:left;border-bottom:1px solid var(--border-g);z-index:2}
.vx-is-table td{padding:5px 8px;border-bottom:1px solid rgba(0,0,0,.04);vertical-align:middle}
.vx-is-row.is-dirty{background:rgba(200,169,110,.10)}
.vx-is-id{font-family:var(--ff-m);font-size:.7rem;color:var(--text-mid);white-space:nowrap}
.vx-is-input{width:100%;padding:4px 8px;border:1px solid var(--border-g);border-radius:4px;font-family:var(--ff-b);font-size:.78rem;background:#fff}
.vx-is-input:focus{border-color:var(--green);outline:none;box-shadow:0 0 0 2px rgba(44,74,62,.08)}
.vx-is-note{min-width:340px}
.vx-is-cp{width:60px;text-align:center}
.vx-is-ts{font-family:var(--ff-m);font-size:.62rem;color:var(--text-muted);white-space:nowrap}

/* 2026-05-09: Users panel (sadmin) */
.vx-users-toolbar{display:flex;gap:8px;align-items:center;margin-bottom:10px;flex-wrap:wrap}
.vx-users-search{flex:1;min-width:200px;padding:7px 12px;border:1px solid var(--border);border-radius:6px;font-family:var(--ff-b);font-size:.86rem;color:var(--ink);background:#fff}
.vx-users-search:focus{outline:none;border-color:var(--gold)}
.vx-users-count{font-family:var(--ff-m);font-size:.7rem;color:var(--text-muted);letter-spacing:.06em}
.vx-users-actions{display:flex;gap:4px;flex-wrap:wrap}
.vx-users-action-btn{appearance:none;font-family:var(--ff-b);font-size:.72rem;padding:4px 10px;border-radius:6px;cursor:pointer;border:1px solid var(--border);background:#fff;color:var(--text-mid);white-space:nowrap;transition:all .12s}
.vx-users-action-btn:hover{border-color:var(--text-mid);color:var(--ink)}
.vx-users-action-btn.is-warn:hover{border-color:#C8923A;color:#C8923A}

/* 2026-05-10: Passkeys list inside Account Settings */
.vx-passkeys-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.vx-passkeys-list:empty{display:none}
.vx-passkey-row{display:flex;align-items:center;gap:14px;padding:11px 14px;background:rgba(250,247,242,.6);border:1px solid rgba(200,169,110,.22);border-radius:10px}
.vx-passkey-icon{width:32px;height:32px;flex-shrink:0;border-radius:8px;background:rgba(200,169,110,.18);color:var(--gold-deep);display:inline-flex;align-items:center;justify-content:center;font-size:16px}
.vx-passkey-info{flex:1;min-width:0}
.vx-passkey-label{font-family:var(--ff-b);font-size:.92rem;color:var(--ink);font-weight:500;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.vx-passkey-meta{font-family:var(--ff-m);font-size:.65rem;letter-spacing:.06em;color:var(--text-muted);text-transform:uppercase;margin-top:3px}
.vx-passkey-row .vx-passkey-actions{display:flex;gap:6px;flex-shrink:0}
.vx-passkey-row .vx-passkey-actions button{appearance:none;background:none;border:1px solid var(--border);color:var(--text-mid);font-family:var(--ff-b);font-size:.72rem;padding:5px 10px;border-radius:6px;cursor:pointer;transition:all .12s}
.vx-passkey-row .vx-passkey-actions button:hover{border-color:var(--text-mid);color:var(--ink)}
.vx-passkey-row .vx-passkey-actions button.is-danger:hover{border-color:#B94040;color:#B94040}
.vx-passkey-empty{padding:14px 16px;border:1px dashed rgba(200,169,110,.32);border-radius:10px;background:rgba(250,247,242,.4);font-size:.84rem;color:var(--text-mid);text-align:center}
.vx-passkey-cloud{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:#3D6A58;background:rgba(90,140,122,.12);padding:1px 7px;border-radius:999px}
.vx-users-action-btn.is-danger:hover{border-color:#B94040;color:#B94040;background:rgba(185,64,64,.04)}
.vx-users-action-btn:disabled{opacity:.4;cursor:not-allowed}
.vx-users-role-chip{display:inline-block;padding:1px 8px;border-radius:100px;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}
.vx-users-role-chip[data-role="sadmin"]    {background:rgba(200,169,110,.18);color:var(--gold-deep)}
.vx-users-role-chip[data-role="subscriber"]{background:rgba(44,74,62,.06);color:var(--text-mid)}
.vx-users-role-chip[data-role="banned"]    {background:rgba(185,64,64,.10);color:#B94040}

/* Confirm dialog */
.vx-users-confirm-backdrop{position:fixed;inset:0;background:rgba(22,32,50,.45);display:none;align-items:center;justify-content:center;z-index:9999;padding:20px}
.vx-users-confirm-backdrop.is-on{display:flex}
.vx-users-confirm{background:#fff;border-radius:14px;padding:24px 28px;max-width:480px;width:100%;box-shadow:0 20px 60px rgba(22,32,50,.25)}
.vx-users-confirm h3{font-family:var(--ff-d);font-size:1.4rem;color:var(--green);margin:0 0 8px;font-weight:500}
.vx-users-confirm h3 em{font-style:italic;color:var(--gold-deep)}
.vx-users-confirm p{font-size:.92rem;color:var(--text-mid);line-height:1.55;margin:6px 0 14px}
.vx-users-confirm label{display:block;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);margin:10px 0 4px}
.vx-users-confirm textarea{width:100%;padding:9px 12px;border:1px solid var(--border);border-radius:8px;font-family:var(--ff-b);font-size:.88rem;color:var(--ink);min-height:64px;resize:vertical;box-sizing:border-box}
.vx-users-confirm input[type="text"]{width:100%;padding:9px 12px;border:1px solid var(--border);border-radius:8px;font-family:var(--ff-m);font-size:.88rem;color:var(--ink);box-sizing:border-box}
.vx-users-confirm-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:18px;align-items:center}
/* Inline status row (spinner + message) — appears once admin action fires.
   Sits to the LEFT of the buttons in the actions row so progress is visible
   without hunting. Color shifts based on status class. */
.vx-users-confirm-status{flex:1;display:flex;align-items:center;gap:8px;font-family:var(--ff-m);font-size:.74rem;color:var(--text-mid);min-height:20px}
.vx-users-confirm-status.is-error  {color:#B94040}
.vx-users-confirm-status.is-success{color:#3D6A58}
.vx-users-spinner{width:14px;height:14px;border-radius:50%;border:2px solid rgba(44,74,62,.18);border-top-color:var(--gold-deep);animation:vx-spin .9s linear infinite;flex-shrink:0}
@keyframes vx-spin{to{transform:rotate(360deg)}}
.vx-users-confirm-status.is-success .vx-users-spinner{display:none}
.vx-users-confirm-status.is-error .vx-users-spinner{display:none}
.vx-users-confirm-status .vx-users-status-icon{font-size:14px;line-height:1}
.vx-rpt-table th{position:sticky;top:0;background:rgba(44,74,62,.04);font-family:var(--ff-m);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-mid);font-weight:500;text-align:left;padding:9px 12px;border-bottom:1px solid var(--border);white-space:nowrap;cursor:pointer;user-select:none}
.vx-rpt-table th[data-sort]:hover{background:rgba(44,74,62,.07);color:var(--green)}
.vx-rpt-table th .vx-rpt-sort-arrow{margin-left:4px;color:var(--gold-deep);font-size:.7rem}
.vx-rpt-table td{padding:8px 12px;border-bottom:1px solid rgba(200,169,110,.12);vertical-align:top;color:var(--ink)}
.vx-rpt-table tr:nth-child(even) td{background:rgba(250,247,242,.4)}
.vx-rpt-table tr:hover td{background:rgba(90,140,122,.06)}
.vx-rpt-table td.is-trunc{max-width:280px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vx-rpt-table .vx-fb-kind-chip,.vx-rpt-table .vx-fb-status-chip{display:inline-block;padding:1px 8px;border-radius:100px;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase}

.vx-rpt-actions{display:flex;align-items:center;gap:10px;margin-top:12px;padding-top:10px;border-top:1px dashed rgba(44,74,62,.1)}
.vx-rpt-actions button{padding:7px 16px;border:1px solid rgba(44,74,62,.22);background:#fff;color:var(--text-mid);border-radius:8px;font-family:var(--ff-b);font-size:.78rem;cursor:pointer;transition:all .15s}
.vx-rpt-actions button:hover{border-color:var(--green);color:var(--green)}
.vx-rpt-actions .vx-rpt-meta{flex:1;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted)}

.vx-rpt-empty{padding:18px;text-align:center;font-size:.86rem;color:var(--text-muted);font-style:italic}
/* 2026-05-04: small role badge for the User roster (Usage activity report) */
.vx-rpt-role-badge{display:inline-block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.1em;text-transform:uppercase;padding:2px 7px;border-radius:10px;background:rgba(58,107,89,.12);color:var(--green,#2C4A3E);font-weight:500}

/* Onboarding funnel viz — horizontal bars proportional to top-of-funnel */
.vx-of-funnel{display:flex;flex-direction:column;gap:14px;margin-bottom:10px}
.vx-of-stage{display:flex;flex-direction:column;gap:4px}
.vx-of-stage-row{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.vx-of-stage-label{font-family:var(--ff-d);font-size:1rem;color:var(--green);font-weight:400}
.vx-of-stage-count{font-family:var(--ff-m);font-size:.7rem;letter-spacing:.06em;color:var(--text-mid)}
.vx-of-bar-wrap{height:18px;background:rgba(44,74,62,.04);border-radius:9px;overflow:hidden}
.vx-of-bar{height:100%;background:linear-gradient(90deg,var(--green) 0%,#5a8c7a 100%);border-radius:9px;transition:width .35s ease-out}
.vx-of-stage-meta{display:flex;justify-content:space-between;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.06em;color:var(--text-muted);text-transform:none}
.vx-of-stage-meta strong{color:var(--ink);font-weight:500}

/* ═══ Videos tab (2026-05-05) ════════════════════════════════════════
   Subscriber library + sadmin admin tools. Sub-tab chips reuse the
   visual language of the existing tab strip but are scoped inside the
   panel. Video grid is responsive: 1 col mobile, 2 col tablet, 3 col
   desktop. Sadmin "Scripts" chip embeds heygen-lab.html?embedded=1. */
.vx-vid-subtabs{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 18px;padding-bottom:10px;border-bottom:1px solid rgba(200,169,110,.18)}
.vx-vid-subtab{appearance:none;background:transparent;border:1px solid rgba(200,169,110,.3);color:var(--text-mid);padding:6px 14px;border-radius:100px;font-family:var(--ff-b);font-size:.78rem;cursor:pointer;transition:all .15s}
.vx-vid-subtab:hover{border-color:var(--green);color:var(--green)}
.vx-vid-subtab.is-active{background:var(--green);border-color:var(--green);color:#fff}
.vx-vid-subtab.vx-vid-subtab-admin{margin-left:auto;border-color:var(--gold);color:var(--gold-deep)}
.vx-vid-subtab.vx-vid-subtab-admin.is-active{background:var(--gold-deep);border-color:var(--gold-deep);color:#fff}

.vx-vid-admin-bar{display:flex;justify-content:flex-end;margin-bottom:12px}
.vx-vid-admin-bar button{appearance:none;font-family:var(--ff-b);font-size:.84rem;padding:7px 16px;border-radius:6px;cursor:pointer;border:1px solid var(--green);background:var(--green);color:#fff;transition:all .15s}
.vx-vid-admin-bar button:hover{background:#1f3a30}

/* 2026-05-06: Videos library is a list (not a thumbnail grid). Each row
   has a small play indicator on the left, title + surface tag + optional
   description in the middle, sadmin action buttons on the right.
   Class names preserved so JS click wiring (vx-vid-card[data-vid-id])
   keeps working without changes. */
.vx-vid-grid{display:flex;flex-direction:column;gap:6px;margin-top:6px}

.vx-vid-card{display:flex;align-items:center;gap:14px;padding:11px 14px;background:#fff;border:1px solid rgba(200,169,110,.22);border-radius:10px;cursor:pointer;transition:border-color .15s, transform .15s, box-shadow .15s}
.vx-vid-card:hover{border-color:var(--green);transform:translateY(-1px);box-shadow:0 2px 6px rgba(44,74,62,.05)}
.vx-vid-card-thumb{flex-shrink:0;width:34px;height:34px;border-radius:50%;background:rgba(44,74,62,.06);display:flex;align-items:center;justify-content:center;aspect-ratio:auto;background-image:none!important}
.vx-vid-card-thumb-play{width:auto;height:auto;background:transparent;color:var(--green);font-size:.85rem;box-shadow:none;padding:0}
.vx-vid-card-thumb-empty{font-family:var(--ff-m);font-size:.7rem;color:var(--text-muted);padding:0;text-align:center;line-height:1;letter-spacing:0;text-transform:none}
.vx-vid-card-body{flex:1;min-width:0;padding:0;display:flex;flex-direction:column;gap:2px}
.vx-vid-card-title{font-family:var(--ff-d);font-size:1.02rem;font-weight:400;color:var(--green);line-height:1.25;margin-bottom:0;display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
.vx-vid-card-sub{font-family:var(--ff-m);font-size:.56rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted);display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap;margin:0;padding:0;font-weight:500}
.vx-vid-card-sub > span:first-child{padding:1px 7px;background:rgba(44,74,62,.06);border-radius:100px}
.vx-vid-card-sub .vx-vid-status-draft{color:var(--gold-deep);font-weight:500;padding:1px 7px;background:rgba(200,169,110,.14);border-radius:100px}
.vx-vid-card-desc{font-size:.78rem;color:var(--text-mid);line-height:1.5;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vx-vid-card-actions{display:flex;gap:5px;padding:0;border-top:none;flex-shrink:0}
.vx-vid-card-actions button{appearance:none;background:#fff;border:1px solid rgba(44,74,62,.18);color:var(--text-mid);font-family:var(--ff-b);font-size:.66rem;padding:4px 9px;border-radius:6px;cursor:pointer;transition:all .15s;white-space:nowrap}
.vx-vid-card-actions button:hover{border-color:var(--green);color:var(--green)}
.vx-vid-card-actions button.vx-vid-danger:hover{border-color:#B94040;color:#B94040}
/* 2026-05-24 task #66 — framing chip. Gold accent so sadmin reads it
   as a state toggle (current visual mode), not an action that fires
   irreversibly. Hover lifts it to the gold-deep brand accent. */
.vx-vid-card-actions button.vx-vid-framing{background:rgba(200,169,110,.08);border-color:rgba(200,169,110,.32);color:var(--gold-deep,#A07840);font-family:var(--ff-m);letter-spacing:.06em}
.vx-vid-card-actions button.vx-vid-framing:hover{background:rgba(200,169,110,.16);border-color:var(--gold-deep,#A07840);color:#7d5f30}

@media (max-width:560px){
  .vx-vid-card{flex-wrap:wrap}
  .vx-vid-card-actions{margin-left:auto}
  .vx-vid-card-desc{display:none}
}

.vx-vid-empty{padding:32px 18px;text-align:center;color:var(--text-muted);font-style:italic;font-size:.9rem;border:1px dashed rgba(44,74,62,.15);border-radius:10px}

.vx-vid-add-form{background:rgba(250,247,242,.5);border:1px solid rgba(200,169,110,.3);border-radius:10px;padding:16px;margin-bottom:14px;display:grid;gap:10px;grid-template-columns:1fr 1fr}
.vx-vid-add-form .full{grid-column:1/-1}
.vx-vid-add-form label{display:flex;flex-direction:column;gap:3px;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-mid)}
.vx-vid-add-form input,.vx-vid-add-form select,.vx-vid-add-form textarea{font-family:var(--ff-b);font-size:.86rem;color:var(--ink);padding:7px 10px;border:1px solid rgba(44,74,62,.22);border-radius:6px;background:#fff}
.vx-vid-add-form textarea{resize:vertical;min-height:60px}
.vx-vid-add-form-actions{display:flex;gap:8px;justify-content:flex-end;grid-column:1/-1;margin-top:4px}
.vx-vid-add-form-actions button{appearance:none;font-family:var(--ff-b);font-size:.84rem;padding:8px 16px;border-radius:6px;cursor:pointer;border:1px solid rgba(44,74,62,.22);background:#fff;color:var(--text-mid)}
.vx-vid-add-form-actions button.primary{background:var(--green);border-color:var(--green);color:#fff}
.vx-vid-add-form-actions button.primary:hover{background:#1f3a30}

.vx-vid-modal{position:fixed;inset:0;background:rgba(28,28,28,.86);display:flex;align-items:center;justify-content:center;z-index:9999;padding:20px}
.vx-vid-modal-inner{background:#000;border-radius:10px;max-width:480px;width:100%;max-height:90vh;display:flex;flex-direction:column;overflow:hidden;position:relative}
.vx-vid-modal video{width:100%;max-height:80vh;background:#000;display:block}
.vx-vid-modal-close{position:absolute;top:14px;right:18px;background:rgba(0,0,0,.5);color:#fff;border:none;border-radius:50%;width:34px;height:34px;font-size:1.4rem;line-height:1;cursor:pointer;z-index:1}
.vx-vid-modal-close:hover{background:rgba(0,0,0,.85)}

/* Persistent footer */
.vx-acc-footer{display:flex;justify-content:center;align-items:center;gap:10px;margin-top:2.5rem;padding-top:1.25rem;border-top:1px solid rgba(44,74,62,.08);font-size:.82rem;color:var(--text-muted);flex-wrap:wrap}
.vx-acc-footer a{color:var(--text-muted);text-decoration:none;transition:color .15s}
.vx-acc-footer a:hover{color:var(--green)}
.vx-acc-footer-sep{opacity:.4}

/* Tablet */
@media (min-width: 620px) and (max-width: 1024px){
 .vx-acc-wrap{padding:2rem 1.5rem}
 .vx-acc-head{gap:1rem}
}
/* Mobile */
@media (max-width:767px){
 /* 2026-07-21 — add the safe-area inset so the ← BACK button clears the
    notch-inflated fixed header instead of being clipped under it. */
 .vx-acc-wrap{padding:calc(1.75rem + env(safe-area-inset-top, 0px)) 1.25rem 2rem}
 .vx-acc-h1{font-size:1.6rem}
 .vx-acc-head{flex-direction:row;align-items:center;gap:.75rem;margin-bottom:1.25rem}
 .vx-acc-head-main{flex:1 1 100%;order:3}
 .vx-acc-save-chip{margin-left:auto}
 .vx-acc-tabs{gap:2px}
 .vx-acc-tab{padding:10px 12px;font-size:.85rem}
 .vx-acc-tab-signout{margin-left:0}
 .vx-acc-fieldset-save{flex-direction:column-reverse;align-items:stretch;gap:.6rem}
 .vx-acc-save-btn{width:100%}
 .vx-acc-2fa-opt{margin-left:0}
 .vx-acc-method-note{flex-wrap:wrap}
}
@media (pointer:coarse){
 .vx-acc-save-btn{min-height:44px}
 .vx-acc-tab{min-height:44px}
 .vx-acc-back{min-height:36px}
}

/* 2026-04-30 home rewire: wallpaper card on Wedding Details. Preview
   shows the user's photo with the same 42% cream wash the home screen
   applies, so couples see exactly what they'll get — not the raw
   uploaded image saturation that won't be the final look. */
.vx-wp-card{background:#fff;border:1px solid var(--border-g, #cdc5b6);border-radius:12px;padding:16px;display:flex;flex-direction:column;gap:12px}
.vx-wp-preview{position:relative;width:100%;aspect-ratio:9/16;max-height:340px;background:var(--cream-d, #F0EBE1);border-radius:10px;overflow:hidden;display:flex;align-items:center;justify-content:center}
.vx-wp-preview[data-state="empty"] .vx-wp-preview-img,
.vx-wp-preview[data-state="empty"] .vx-wp-preview-wash{display:none}
.vx-wp-preview[data-state="filled"] .vx-wp-preview-empty{display:none}
.vx-wp-preview-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;text-align:center;color:var(--text-muted, #88928d);font-size:.82rem;padding:20px;font-style:italic}
/* 2026-07-18 — "pending" = a wallpaper IS stored, the preview just
   hasn't resolved yet. Reads like the empty state but never claims
   there's no wallpaper, because Remove is live in this state. */
.vx-wp-preview-pending{display:none;align-items:center;justify-content:center;text-align:center;color:var(--text-muted, #88928d);font-size:.82rem;padding:20px;font-style:italic}
.vx-wp-preview[data-state="pending"] .vx-wp-preview-empty,
.vx-wp-preview[data-state="pending"] .vx-wp-preview-img,
.vx-wp-preview[data-state="pending"] .vx-wp-preview-wash{display:none}
.vx-wp-preview[data-state="pending"] .vx-wp-preview-pending{display:flex}
.vx-wp-preview-img{width:100%;height:100%;object-fit:cover;display:block}
.vx-wp-preview-wash{position:absolute;inset:0;background:rgba(240,235,225,.42);pointer-events:none}
.vx-wp-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.vx-wp-status{font-family:var(--ff-m, 'DM Mono', monospace);font-size:.7rem;letter-spacing:.04em;color:var(--text-muted, #88928d)}
.vx-wp-status.is-error{color:#B94040}
.vx-wp-status.is-ok{color:var(--green, #2C4A3E)}

/* 2026-04-30: three-value budget block — Estimated · Current Plan · Funding,
   plus a single variance line that tells the actual story. */
.vx-wd-budget-trio{display:flex;flex-direction:column;gap:0;border:1px solid var(--border-g,#cdc5b6);border-radius:10px;background:#fff;overflow:hidden}
.vx-wd-budget-row{display:flex;align-items:center;gap:14px;padding:14px 16px;border-bottom:1px solid var(--border-g,#eae5dd)}
.vx-wd-budget-row:last-child{border-bottom:none}
.vx-wd-budget-row-label{flex:1;min-width:0}
.vx-wd-budget-row-name{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;font-weight:500;color:var(--ink,#1C1C1C)}
.vx-wd-budget-row-sub{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;color:var(--text-muted,#88928d);margin-top:2px}
.vx-wd-budget-row-val{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--money-ink,#33352f);text-align:right;flex-shrink:0}
.vx-wd-budget-row-val input{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.4rem;color:var(--green,#2C4A3E);border:1px solid var(--border-g,#cdc5b6);border-radius:6px;padding:4px 8px;background:#fff}
.vx-wd-budget-variance{margin-top:14px;padding:12px 16px;border-radius:10px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;font-weight:500;text-align:center}
.vx-wd-budget-variance.is-under{background:rgba(107,143,113,.12);border:1px solid rgba(107,143,113,.3);color:#3D6355}
.vx-wd-budget-variance.is-near{background:rgba(200,169,110,.12);border:1px solid rgba(200,169,110,.3);color:#a8843a}
.vx-wd-budget-variance.is-over{background:rgba(201,123,106,.10);border:1px solid rgba(201,123,106,.28);color:var(--rose,#C97B6A)}
.vx-wd-budget-variance-text strong{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.1em;font-weight:500}

/* ═══ Cut Advisor structured cards (idea #2, 2026-04-29) ═══════════
   Each AI suggestion is now a card with one-click Apply. */
.vx-cut-summary{font-size:.92rem;color:var(--text-mid);line-height:1.55;margin-bottom:14px;font-style:italic}
.vx-cut-list{display:flex;flex-direction:column;gap:10px}
/* 2026-05-29 (Phase 7) — readout for the balanced-bidirectional case.
   Soft gold accent + slightly larger weight than the strike-1..5 lines
   because this IS the brand promise: memories survive under pressure. */
.vx-cut-strike-readout-phase7{
  background:linear-gradient(180deg,#FCF6E8 0%,#F9EFD4 100%);
  border:1px solid rgba(200,169,110,.50);
  color:var(--green-deep,#2C4A3E);
  padding:11px 14px;
  border-radius:10px;
  font-size:.92rem;
  font-family:var(--ff-d,'Cormorant Garamond',serif);
  font-style:italic;
  line-height:1.45;
  margin-bottom:10px
}
.vx-cut-strike-readout-phase7 b{color:var(--gold-deep,#A07840);font-style:normal;font-weight:600;font-family:var(--ff-b,'DM Sans',sans-serif)}
@media (max-width:480px){
  /* Tighten the Phase 7 readout on mobile — the Cormorant italic at .92rem
     can wrap awkwardly on narrow screens. Drop padding + line-height
     slightly so the brand line stays a 1-2 row pull-quote, not a paragraph. */
  .vx-cut-strike-readout-phase7{padding:10px 12px;font-size:.88rem;line-height:1.4}
}
.vx-cut-card{padding:12px 14px;background:#fff;border:1px solid var(--border);border-left:3px solid var(--gold);border-radius:8px;transition:opacity .2s,transform .2s}
.vx-cut-card.vx-cut-up{border-left-color:#6B8F71}
.vx-cut-card.vx-cut-down{border-left-color:#C97B3A}
.vx-cut-card.is-applied{background:rgba(107,143,113,.08);border-left-color:#3D6355}
.vx-cut-card.is-dismissed{opacity:.4;transform:scale(.98)}
.vx-cut-card-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
.vx-cut-card-cat{font-family:var(--ff-d);font-size:1.05rem;font-weight:500;color:var(--ink);font-style:italic}
.vx-cut-confidence{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600;padding:2px 7px;border-radius:9px;flex-shrink:0}
.vx-cut-confidence.is-high{background:rgba(44,74,62,.1);color:var(--green)}
.vx-cut-confidence.is-moderate{background:rgba(200,169,110,.18);color:var(--gold-deep,#A07840)}
.vx-cut-confidence.is-low{background:rgba(201,123,58,.14);color:var(--amber-risk,#C97B3A)}
/* 2026-05-28 — Phase 2 Strike Cascade chips. Color family matches the
   per-item Memorability Lens chip system: 1-2 = release (terracotta),
   3 = consider (neutral), 4-5 = protected (green). */
.vx-cut-strike{font-family:var(--ff-m);font-size:.55rem;letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:2px 8px;border-radius:9px;flex-shrink:0;border:1px solid transparent}
.vx-cut-strike-1{background:rgba(220,80,80,.06);color:#a23030;border-color:rgba(220,80,80,.22);font-style:italic}
.vx-cut-strike-2{background:rgba(176,123,63,.08);color:#925e2a;border-color:rgba(176,123,63,.22)}
.vx-cut-strike-3{background:rgba(122,116,104,.10);color:var(--charcoal-soft,#7a7468);border-color:rgba(122,116,104,.25)}
.vx-cut-strike-4{background:rgba(58,107,89,.10);color:var(--green-mid,#3a6b59);border-color:rgba(58,107,89,.25)}
.vx-cut-strike-5{background:rgba(44,74,62,.12);color:var(--green,#2C4A3E);border-color:rgba(44,74,62,.30);font-weight:700}
/* 2026-05-29 Phase 7 — investment-side strike chips. Cuts use the warning
   gradient (red → green by severity); investments invert it — the higher
   the strike, the MORE memorable the moment. Gold-deep "MEMORY MAKER"
   chip for strike-5 invests matches the brand promise palette. */
.vx-cut-strike-invest{background:rgba(200,169,110,.14)!important;color:var(--gold-deep,#A07840)!important;border-color:rgba(200,169,110,.40)!important}
.vx-cut-strike-5.vx-cut-strike-invest{background:linear-gradient(180deg,rgba(200,169,110,.20) 0%,rgba(200,169,110,.10) 100%)!important;color:var(--gold-deep,#A07840)!important;border-color:rgba(200,169,110,.55)!important;font-weight:700}
/* Strike readout — the top summary that names how far down the Lens
   the AI had to reach to close the gap. Tone matches strike level. */
.vx-cut-strike-readout{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-style:italic;font-size:.95rem;color:var(--green);background:rgba(250,247,242,.7);border-left:3px solid var(--gold);border-radius:0 8px 8px 0;padding:10px 14px;margin:8px 0 12px;line-height:1.5}
.vx-cut-strike-readout b{font-style:normal;font-family:var(--ff-m);font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;color:var(--gold-deep,#A07840);padding:1px 7px;border-radius:6px;background:rgba(200,169,110,.15)}
.vx-cut-strike-readout-1,.vx-cut-strike-readout-2{border-left-color:#925e2a}
.vx-cut-strike-readout-3{border-left-color:var(--charcoal-soft,#7a7468)}
.vx-cut-strike-readout-4{border-left-color:var(--green-mid,#3a6b59)}
.vx-cut-strike-readout-5{border-left-color:#a23030}
.vx-cut-strike-readout-5 b{color:#a23030;background:rgba(220,80,80,.10)}
/* 2026-05-28 (Stephen "we need an equal number of recommendations being
   removed until balanced or credibility is lost"): the net-balance
   indicator. Green checkmark when applying all proposals would balance
   the budget; red banner when there's still a residual gap. */
.vx-cut-balance{font-family:var(--ff-b);font-size:.84rem;letter-spacing:.01em;padding:9px 14px;border-radius:8px;margin:8px 0 6px;line-height:1.5}
.vx-cut-balance.is-balanced{background:rgba(58,107,89,.08);color:var(--green);border:1px solid rgba(58,107,89,.22)}
.vx-cut-balance.is-over{background:rgba(201,123,106,.07);color:var(--rose,#C97B6A);border:1px solid rgba(201,123,106,.24)}
.vx-cut-balance b{font-family:var(--ff-m);font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;padding:1px 6px;background:rgba(0,0,0,.06);border-radius:5px}
/* 2026-05-28 — Lens bulk affordances INSIDE the Optimize panel. Smaller,
   tighter than the prior toolbar version. Right-aligned so they read as
   actions on the recommendation set rather than primary chrome. */
.vx-cut-lens-bar{display:flex;justify-content:flex-end;gap:8px;margin:8px 0 14px;flex-wrap:wrap}
.vx-cut-lens-btn{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;font-weight:500;padding:7px 13px;border-radius:999px;border:1px solid var(--border-g);background:transparent;cursor:pointer;transition:all .15s ease}
.vx-cut-lens-trim{color:#a23030;border-color:rgba(220,80,80,.32)}
.vx-cut-lens-trim:hover{background:rgba(220,80,80,.08);color:#a23030}
.vx-cut-lens-filter{color:var(--green)}
.vx-cut-lens-filter[aria-pressed="true"]{background:var(--green);color:var(--white,#fff);border-color:var(--green)}
/* 2026-05-28 — Synthetic reduction chip: "Verdeaux added this card to
   close the gap because the AI didn't propose enough cuts." Honest,
   small, gold so it reads as the system stepping in. */
.vx-cut-synth{font-family:var(--ff-m);font-size:.54rem;letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:2px 8px;border-radius:9px;flex-shrink:0;background:rgba(200,169,110,.16);color:var(--gold-deep,#A07840);border:1px solid rgba(200,169,110,.4)}
/* 2026-05-28 (Stephen "show all recommendations… no-argument adjustments
   AND the tough choices"): Recommendations Spectrum — top-of-panel
   grouped view of every suggestion by editorial tier. Each tier shows
   the total dollar impact + per-item one-liners + click-to-scroll to
   the inline Apply card. Mobile-friendly stacking. */
.vx-cut-spectrum{background:rgba(250,247,242,.55);border:1px solid var(--border-g);border-radius:10px;padding:14px 16px;margin:10px 0 14px}
.vx-cut-spectrum-head{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin-bottom:10px;font-weight:600}
.vx-cut-tier{margin-bottom:14px}
.vx-cut-tier:last-child{margin-bottom:0}
.vx-cut-tier-head{display:flex;align-items:baseline;gap:10px;margin-bottom:6px;padding-bottom:4px;border-bottom:1px solid rgba(0,0,0,.06)}
.vx-cut-tier-name{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-style:italic;font-size:1.05rem;color:var(--green);font-weight:500}
.vx-cut-tier-sub{font-family:var(--ff-b);font-size:.72rem;color:var(--text-muted);font-style:italic}
.vx-cut-tier-total{margin-left:auto;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums}
.vx-cut-tier-total.is-down{color:var(--green-mid,#3a6b59)}
.vx-cut-tier-total.is-up{color:var(--amber-risk,#C97B3A)}
.vx-cut-tier-1 .vx-cut-tier-name{color:#3a6b59}
.vx-cut-tier-2 .vx-cut-tier-name{color:var(--green)}
.vx-cut-tier-3 .vx-cut-tier-name{color:#925e2a}
.vx-cut-tier-4 .vx-cut-tier-name{color:var(--gold-deep,#A07840)}
.vx-cut-tier-5 .vx-cut-tier-name{color:var(--charcoal-soft,#7a7468)}
.vx-cut-tier-6 .vx-cut-tier-name{color:#a23030}
.vx-cut-tier-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.vx-cut-spec-item{padding:6px 0;border-bottom:1px dotted rgba(0,0,0,.04)}
.vx-cut-spec-item:last-child{border-bottom:none}
.vx-cut-spec-link{display:flex;align-items:baseline;gap:10px;text-decoration:none;color:inherit;cursor:pointer;padding:2px 0;border-radius:4px;transition:background .15s ease}
.vx-cut-spec-link:hover{background:rgba(200,169,110,.10)}
.vx-cut-spec-cat{font-family:var(--ff-b);font-size:.86rem;color:var(--charcoal);font-weight:500}
.vx-cut-spec-delta{margin-left:auto;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap}
.vx-cut-spec-delta.is-down{color:var(--green-mid,#3a6b59)}
.vx-cut-spec-delta.is-up{color:var(--amber-risk,#C97B3A)}
.vx-cut-spec-why{font-family:'Cormorant Garamond','Cormorant Fallback',Georgia,serif;font-style:italic;font-size:.78rem;color:var(--text-mid,#4A4A4A);line-height:1.5;padding-left:2px;margin-top:2px}
.vx-cut-spec-synth{font-family:var(--ff-m);font-size:.5rem;letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:1px 6px;border-radius:6px;color:var(--gold-deep,#A07840);background:rgba(200,169,110,.16);margin-left:6px}
.vx-cut-card.is-inline.is-pulse{animation:vxCutPulse 1.5s ease-out 1}
@keyframes vxCutPulse{0%{box-shadow:0 0 0 4px rgba(200,169,110,.32)}100%{box-shadow:0 0 0 0 rgba(200,169,110,0)}}
.vx-cut-amounts{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-family:var(--ff-b,'DM Sans',sans-serif);font-variant-numeric:tabular-nums}
.vx-cut-from{font-size:var(--fs-amount,.9rem);font-weight:500;color:var(--text-muted);text-decoration:line-through}
.vx-cut-arrow{color:var(--text-muted)}
.vx-cut-to{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--money-ink,#33352f)}
.vx-cut-delta{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;padding:1px 7px;border-radius:8px;font-weight:500;font-variant-numeric:tabular-nums;margin-left:auto}
.vx-cut-delta.up{background:rgba(107,143,113,.15);color:#3D6355}
.vx-cut-delta.down{background:rgba(201,123,58,.14);color:#C97B3A}
.vx-cut-delta.flat{background:rgba(28,28,28,.06);color:var(--text-mid)}
.vx-cut-just{font-size:.84rem;color:var(--text-mid);line-height:1.55;margin-bottom:10px}
.vx-cut-actions{display:flex;gap:8px;justify-content:flex-end}
.vx-cut-apply{appearance:none;background:var(--green);color:#fff;border:none;font-family:var(--ff-b);font-size:.78rem;font-weight:500;padding:6px 14px;border-radius:6px;cursor:pointer;transition:background .15s}
.vx-cut-apply:hover{background:#1f3a30}
.vx-cut-apply:disabled{opacity:.7;cursor:default}
.vx-cut-skip{appearance:none;background:transparent;border:1px solid var(--border-g);color:var(--text-muted);font-family:var(--ff-b);font-size:.76rem;padding:6px 12px;border-radius:6px;cursor:pointer}
.vx-cut-skip:hover{color:var(--text-mid);border-color:var(--text-mid)}

/* ═══ Category-level locks (Stephen smoke-test #4, 2026-04-29) ═════
   Inline lock CTA on each Budget section header. When locked, shows a
   gold badge with the contracted $ amount + vendor name + Edit/Unlock
   controls. Modal pops via _openLockModal — vendor + amount + notes. */
.vxc-lock-chrome{margin-top:8px;padding-top:8px;border-top:1px dashed rgba(200,169,110,.3)}
.vxc-lock-cta{appearance:none;display:inline-flex;align-items:center;gap:6px;background:transparent;border:1px dashed rgba(200,169,110,.5);color:var(--gold-deep,#A07840);font-family:var(--ff-b);font-size:.74rem;padding:5px 12px;border-radius:14px;cursor:pointer;transition:all .15s}
.vxc-lock-cta:hover{background:rgba(200,169,110,.1);border-color:var(--gold)}
.vxc-lock-cta-icon{font-size:.85rem}
/* 2026-07-28 (Stephen) — controls row for Edit/Unlock/Lock after they move OFF the clean header
   into the expand box (locked Details panel / unlocked line-items). Quiet dashed divider +
   right-aligned actions, so the expand reads info-first, actions-last. */
#section-budget .vxc-lock-expand-controls{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;align-items:center;margin-top:14px;padding-top:12px;border-top:1px dashed rgba(200,169,110,.3)}
#section-budget .vxc-lock-expand-controls .vxc-lock-edit,#section-budget .vxc-lock-expand-controls .vxc-lock-unlock,#section-budget .vxc-lock-expand-controls .vxc-lock-cta{margin:0}
/* 2026-05-01 polish: gradient + border dropped, vertical padding
   tightened so the locked-row height matches the planned-row chevron
   height. Dollar/vendor/Edit/Unlock items still flow horizontally. */
.vxc-lock-badge{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:0 0 0 12px;background:transparent;border:none;border-radius:0}   /* 2026-07-28 (Stephen): dropped the 10px right padding (leftover from when Edit/Unlock lived in the badge) so the BOOKED $ right-aligns with the in-process $ — fixes the money column "wave" */
/* 2026-07-08 (Stephen, device pass, round 2) — phones: every category
   header becomes the same two-row shape. Row 1: title left, $ amount
   right. Row 2: all controls (Edit/Unlock, Skip all, reset, Lock, chips)
   right-justified, sized as secondary to the title. Works for BOTH card
   types with zero markup change: the planned head's meta div flattens via
   display:contents so its children take head-level flex order, and a
   full-width ::after breaker (order 4) starts row 2; the locked head's
   badge keeps its amount-over-buttons grid, top-aligned with the title. */
@media (max-width:600px){
  /* locked cards */
  .vxc-lock-badge{display:grid;grid-template-columns:auto 1fr;justify-content:end;align-items:center;gap:6px 8px;min-width:128px}
  /* Amounts flush to the card's right edge — the 1fr cell stretches but
     text sat left, so different-width sums ended at different x. */
  .vxc-lock-badge .vxc-lock-amount{text-align:right}
  .vxc-lock-badge .vxc-lock-edit,.vxc-lock-badge .vxc-lock-unlock{width:100%;text-align:center}
  .vxb-section.is-locked .vxb-section-head{align-items:flex-start}
  .vxb-section.is-locked .vxb-section-title,
  .vxb-section.is-locked .vxb-chevron{margin-top:3px} /* baseline with badge row 1 */

  /* planned cards — flatten meta, order into two rows */
  .vxb-section.is-planned .vxb-section-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;row-gap:8px}
  .vxb-section.is-planned .vxb-section-meta{display:contents}
  .vxb-section.is-planned .vxb-section-title{order:1}
  .vxb-section.is-planned .vxb-chevron{order:2}
  /* 2026-07-08 (Stephen) — one "state slot" directly before the amount on
     row 1, matching where locked cards show the ✦ status star: planned
     cards put the ↺ reset there instead. The ↺ keeps its circled-button
     look so it still reads as tappable next to the plain ✦ glyph. */
  .vxb-section.is-planned .vxb-reset-medians{order:3;margin-left:auto}
  .vxb-section.is-planned .vxb-amount{order:4}
  .vxb-section.is-planned .vxb-section-head::after{content:"";order:5;flex-basis:100%;height:0}
  .vxb-section.is-planned .vxb-amount-tag{order:6}
  .vxb-section.is-planned .vxb-aside-pill{order:6}
  .vxb-section.is-planned .vxb-item-count{order:7}
  .vxb-section.is-planned .vxb-bulk-toggle{order:8}
  .vxb-section.is-planned .vxc-lock-chrome{order:9;margin:0;padding:0;border:none}

  /* controls read secondary to the 0.9rem titles instead of louder */
  .vxc-lock-edit,.vxc-lock-unlock,.vxb-bulk-toggle,.vxb-reset-medians{font-size:.78rem;padding:3px 10px}
  .vxc-lock-cta-mini{font-size:.78rem}
}
.vxc-lock-icon{color:var(--green);font-size:.95rem;flex-shrink:0}
.vxc-lock-amount{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.9rem;font-weight:400;color:var(--green);font-style:normal}
.vxc-lock-vendor{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.9rem;font-weight:400;color:var(--text-mid);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Bundled-envelope itemized breakdown (e.g. Venue & Catering = venue + caterer) */
.vxc-lock-components{display:flex;flex-direction:column;gap:2px;padding:4px 12px 2px 30px;margin-top:2px}
.vxc-lock-comp{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.78rem;color:var(--text-muted,#8a8a80);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Phase A — read-only Details panel (components + contingency) after lock */
.vxc-lock-details-toggle{appearance:none;background:transparent;border:none;color:var(--gold-deep,#A07840);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.82rem;font-weight:500;padding:3px 8px;cursor:pointer}
.vxc-lock-details-toggle:hover{text-decoration:underline}
.vxc-lock-details{padding:8px 12px 6px 30px;margin-top:4px;border-top:1px dashed rgba(44,74,62,.12)}
.vxc-lock-det-label{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted,#8a8a80);margin-bottom:4px}
.vxc-lock-comp-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;color:var(--text-mid,#5a5a52);padding:2px 0}
.vxc-lock-comp-role{font-size:.68rem;color:var(--text-muted,#8a8a80);text-transform:uppercase;letter-spacing:.05em}
.vxc-lock-comp-amt{font-family:var(--ff-m,'DM Mono',monospace);color:var(--green,#2C4A3E);white-space:nowrap}
.vxc-lock-det-contingency{margin-top:8px;padding:6px 10px;border-left:2.5px solid var(--gold,#C8A96E);background:rgba(200,169,110,.08);border-radius:0 6px 6px 0;font-size:.8rem;line-height:1.5;color:var(--text-mid,#5a5a52)}
/* Phase B — per-line coverage rows (covered-by-contract vs estimate+lock) */
.vxc-lock-lines-label{margin-top:10px}
.vxc-lock-line-row{display:flex;align-items:baseline;gap:8px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;padding:2px 0}
.vxc-lock-line-name{flex:1 1 auto;color:var(--text-mid,#5a5a52)}
.vxc-lock-line-tag{color:var(--green,#2C4A3E);font-weight:500;white-space:nowrap}
.vxc-lock-line-est{font-family:var(--ff-m,'DM Mono',monospace);color:var(--text-muted,#9a9a90);white-space:nowrap}
.vxc-lock-line-row.is-notplan{opacity:.55}
.vxc-lock-line-row.is-notplan .vxc-lock-line-est{font-style:italic;text-transform:none}
.vxc-lock-line-lockbtn{appearance:none;background:transparent;border:1px solid rgba(200,169,110,.55);color:var(--gold-deep,#A07840);border-radius:999px;font-size:.7rem;font-weight:500;padding:1px 9px;cursor:pointer;white-space:nowrap}
.vxc-lock-line-lockbtn:hover{background:rgba(200,169,110,.12)}
.vxc-lock-line-note{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;font-style:italic;color:var(--gold-deep,#A07840);line-height:1.4;margin:0 0 6px 2px}
.vxc-lock-edit,.vxc-lock-unlock{appearance:none;background:transparent;border:1px solid rgba(44,74,62,.18);color:var(--text-mid);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.9rem;font-weight:400;padding:3px 10px;border-radius:6px;cursor:pointer}
.vxc-lock-edit:hover{border-color:var(--green);color:var(--green)}
.vxc-lock-unlock:hover{border-color:#B94040;color:#B94040}
.vxb-section.is-cat-locked .vxb-slider-wrap{opacity:.55;pointer-events:none}
.vxb-section.is-cat-locked .vxb-items{opacity:.6;pointer-events:none}
.vxb-section.is-cat-locked .vxb-section-totals .vxb-bulk-toggle{opacity:.5;pointer-events:none}
/* Modal */
.vxc-lock-modal-host{position:fixed;inset:0;z-index:9500;display:flex;align-items:center;justify-content:center;padding:18px;opacity:0;pointer-events:none;transition:opacity .22s}
.vxc-lock-modal-host.is-open{opacity:1;pointer-events:auto}
.vxc-lock-modal-backdrop{position:absolute;inset:0;background:rgba(28,28,28,.45);backdrop-filter:blur(2px);cursor:pointer}
/* 2026-07-11 (Stephen, small-screen live test) — the modal grew taller than
   the viewport (conflict banner + coverage checklist) and clipped BOTH the
   title and the Save/Cancel buttons with no way to scroll. Cap the height
   and let the card scroll internally; centering stays intact because the
   card can no longer exceed the viewport. */
.vxc-lock-modal{position:relative;width:100%;max-width:440px;max-height:min(88vh,88dvh);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;background:#fff;border-radius:14px;padding:22px 24px 18px;box-shadow:0 20px 60px rgba(28,28,28,.25);transform:translateY(8px);transition:transform .22s var(--ease,cubic-bezier(.4,0,.2,1))}
.vxc-lock-modal-host.is-open .vxc-lock-modal{transform:translateY(0)}
.vxc-lock-modal-eyebrow{display:flex;align-items:center;justify-content:space-between;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--green);font-weight:600;margin-bottom:6px}
.vxc-lock-modal-close{appearance:none;background:none;border:none;color:var(--text-muted);font-size:.95rem;cursor:pointer;padding:2px 7px;border-radius:5px}
.vxc-lock-modal-close:hover{color:var(--ink);background:rgba(28,28,28,.05)}
.vxc-lock-modal-h{font-family:var(--ff-d);font-size:1.35rem;font-weight:500;color:var(--green);font-style:italic;margin:0 0 8px;line-height:1.25}
.vxc-lock-modal-sub{font-size:.84rem;color:var(--text-mid);line-height:1.55;margin:0 0 16px}
/* Overlap/ambiguity prompt inside the lock modal (bundled-envelope, v1.1) */
.vxc-lock-conflict{border:1px solid rgba(200,169,110,.5);background:rgba(200,169,110,.08);border-radius:10px;padding:12px 14px;margin:0 0 16px}
.vxc-lock-conflict-head{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;font-weight:600;color:var(--gold-deep,#A07840);margin-bottom:4px}
.vxc-lock-conflict-row{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;color:var(--text-dark,#2c2c2c);margin-bottom:6px}
.vxc-lock-conflict-q{font-size:.84rem;color:var(--text-mid);line-height:1.5;margin-bottom:10px}
.vxc-lock-conflict-choices{display:flex;gap:8px;flex-wrap:wrap}
.vxc-lock-choice{appearance:none;background:#fff;border:1px solid rgba(44,74,62,.22);color:var(--text-mid);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;padding:6px 12px;border-radius:7px;cursor:pointer}
.vxc-lock-choice:hover{border-color:var(--gold,#C8A96E)}
.vxc-lock-choice.is-active{background:var(--gold,#C8A96E);border-color:var(--gold,#C8A96E);color:#fff;font-weight:500}
/* Vera quick-check confirm pop-up (two-stage scan, confidence-gated) */
.vx-vera-confirm-head{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.vx-vera-confirm-av{border-radius:50%;object-fit:cover;flex-shrink:0;box-shadow:0 0 0 2px rgba(200,169,110,.4)}
.vx-vera-confirm-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
/* 2026-06-04 — _vxVeraConfirm(): on-brand replacement for window.confirm() */
.vx-veraconfirm .vx-vera-confirm-head{margin-bottom:12px}
.vx-veraconfirm-h{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.5rem;font-style:italic;color:var(--green,#2C4A3E);margin:0 0 8px;line-height:1.2}
.vx-veraconfirm-body{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;line-height:1.55;color:var(--text-mid,#5a5a52);margin:0 0 18px}
.vx-veraconfirm-actions{display:flex;justify-content:flex-end;gap:10px;flex-wrap:wrap}
.vx-veraconfirm-cancel{appearance:none;background:transparent;border:1px solid rgba(44,74,62,.2);color:var(--text-mid,#5a5a52);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;padding:8px 16px;border-radius:8px;cursor:pointer}
.vx-veraconfirm-cancel:hover{border-color:var(--green,#2C4A3E);color:var(--green,#2C4A3E)}
.vx-veraconfirm-ok{appearance:none;background:var(--green,#2C4A3E);border:1px solid var(--green,#2C4A3E);color:#fff;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;font-weight:500;padding:8px 18px;border-radius:8px;cursor:pointer}
.vx-veraconfirm-ok:hover{background:var(--green-deep,#22382F)}
.vx-veraconfirm-ok.is-danger{background:#B94040;border-color:#B94040}
.vx-veraconfirm-ok.is-danger:hover{background:#A03636}
/* Meal-style setup prompt options */
.vx-meal-options{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px}
.vx-meal-opt{appearance:none;background:transparent;border:1px solid rgba(44,74,62,.2);color:var(--text-mid,#5a5a52);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.88rem;padding:8px 14px;border-radius:999px;cursor:pointer;transition:all .15s}
.vx-meal-opt:hover{border-color:var(--green,#2C4A3E);color:var(--green,#2C4A3E)}
.vx-meal-opt.is-active{background:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E);color:#fff;font-weight:500}
.vx-vera-confirm .vxc-lock-modal-h em{font-style:italic;color:var(--green,#2C4A3E)}
#vxVeraPick{margin:0 0 14px}
.vxc-lock-modal-field{display:block;margin-bottom:12px}
.vxc-lock-covers{margin:0 0 14px;border:1px solid var(--border-g);border-radius:8px;padding:10px 12px;background:var(--cream)}
.vxc-lock-covers-label{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);font-weight:600;margin-bottom:6px}
.vxc-lock-covers-label span{display:block;text-transform:none;letter-spacing:0;font-weight:400;font-size:.72rem;color:var(--text-muted);margin-top:2px}
.vxc-lock-cover-row{display:flex;align-items:center;gap:8px;padding:3px 0;font-family:var(--ff-b);font-size:.86rem;color:var(--ink);cursor:pointer}
.vxc-lock-cover-row input{width:15px;height:15px;flex:0 0 auto;accent-color:var(--gold-deep,#A07840)}
/* 2026-07-11 — simplified coverage checklist: muted per-row amount + the
   collapsed long-tail expander. */
.vxc-lock-cover-row em{margin-left:auto;font-style:normal;font-family:var(--ff-m);font-size:.72rem;color:var(--text-muted)}
/* 2026-07-11 — inner scroll region for the coverage rows: the checklist
   scrolls, the modal doesn't have to. Bottom fade hints at more content. */
.vxc-lock-covers-scroll{max-height:min(30vh,220px);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding-right:2px;mask-image:linear-gradient(to bottom,#000 calc(100% - 14px),rgba(0,0,0,.25));-webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 14px),rgba(0,0,0,.25))}
.vxc-lock-covers-more{appearance:none;background:transparent;border:none;padding:6px 0 2px;font-family:var(--ff-b);font-size:.78rem;color:var(--gold-deep,#A07840);cursor:pointer;text-align:left}
.vxc-lock-covers-more:hover{text-decoration:underline}
/* 2026-07-11 — "Additional items (often bundled)" expander on the locked-
   category line-by-line list (same register as the checklist expander). */
.vxc-lock-lines-more{appearance:none;background:transparent;border:none;padding:6px 0 2px;font-family:var(--ff-b);font-size:.78rem;color:var(--gold-deep,#A07840);cursor:pointer;text-align:left;display:block}
.vxc-lock-lines-more:hover{text-decoration:underline}
.vxc-lock-modal-field>span{display:block;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);font-weight:600;margin-bottom:4px}
.vxc-lock-modal-field>span em{font-style:normal;text-transform:none;letter-spacing:0;font-weight:400;color:var(--text-muted);font-size:.72rem}
.vxc-lock-modal-hint{display:block;margin-top:4px;font-family:var(--ff-b);font-style:normal;font-size:.72rem;line-height:1.45;color:var(--text-muted)}
.vxc-lock-modal-field input,.vxc-lock-modal-field textarea{width:100%;padding:8px 11px;border:1px solid var(--border-g);border-radius:7px;font-family:var(--ff-b);font-size:.88rem;color:var(--ink);background:var(--cream)}
.vxc-lock-modal-field input:focus,.vxc-lock-modal-field textarea:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.18)}
.vxc-lock-modal-amt{display:flex;align-items:center;gap:6px}
.vxc-lock-modal-amt>span{font-family:var(--ff-d);font-size:1.1rem;color:var(--text-mid);flex-shrink:0}
/* 2026-07-11 (Stephen, small-screen round 3) — the action row is STICKY at
   the card's bottom: when tall content (conflict banner + checklist) makes
   the modal scroll, Save/Cancel stay visible instead of living below the
   fold. Solid background + negative margins re-cover the card padding so
   scrolled content slides underneath cleanly. */
.vxc-lock-modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;padding-top:12px;border-top:1px solid var(--border-g);position:sticky;bottom:-18px;background:#fff;margin-left:-24px;margin-right:-24px;padding-left:24px;padding-right:24px;padding-bottom:18px;margin-bottom:-18px}
.vxc-lock-modal-cancel{appearance:none;background:transparent;border:1px solid var(--border-g);color:var(--text-mid);font-family:var(--ff-b);font-size:.82rem;padding:7px 14px;border-radius:7px;cursor:pointer}
.vxc-lock-modal-save{appearance:none;background:var(--green);color:#fff;border:none;font-family:var(--ff-b);font-size:.82rem;font-weight:500;padding:7px 18px;border-radius:7px;cursor:pointer}
.vxc-lock-modal-save:hover{background:#1f3a30}
.vxc-lock-modal-save:disabled{opacity:.5;cursor:not-allowed}
.vxc-lock-modal-err{margin-top:6px;font-size:.78rem;color:#a23030}
/* 2026-07-21 — "Set aside for now" option: a quiet alternative to locking,
   set apart from the contract fields with a top divider. When checked, the
   card dims the vendor/amount/notes fields so it's clear they no longer apply
   and the primary action becomes "Set aside". */
.vxc-lock-setaside{display:flex;align-items:flex-start;gap:10px;margin:14px 0 2px;padding-top:14px;border-top:1px dashed var(--border-g);cursor:pointer}
.vxc-lock-setaside input{width:16px;height:16px;flex:0 0 auto;margin-top:2px;accent-color:var(--gold-deep,#A07840)}
.vxc-lock-setaside-txt{display:block}
.vxc-lock-setaside-txt strong{display:block;font-family:var(--ff-b);font-size:.86rem;font-weight:500;color:var(--ink)}
.vxc-lock-setaside-txt em{display:block;font-style:normal;font-family:var(--ff-b);font-size:.76rem;color:var(--text-muted);margin-top:2px;line-height:1.4}
.vxc-lock-modal.is-setaside-mode .vxc-lock-modal-field,
.vxc-lock-modal.is-setaside-mode .vxc-lock-covers{opacity:.4;pointer-events:none;transition:opacity .15s}

/* ═══ Decision-rationale toast (idea #4, 2026-04-29) ═══════════════
   Slides in from bottom-right when the couple makes a real call (signs
   a vendor, applies a what-if). Non-blocking, dismissible, optional. */
.vx-dec-toast-host{position:fixed;right:18px;bottom:18px;z-index:9000;display:flex;flex-direction:column;gap:10px;pointer-events:none}
.vx-dec-toast{pointer-events:auto;width:340px;max-width:calc(100vw - 36px);background:#fff;border:1px solid rgba(200,169,110,.35);border-radius:12px;padding:14px 16px;box-shadow:0 8px 32px rgba(44,74,62,.18);transform:translateX(380px);opacity:0;transition:transform .28s var(--ease,cubic-bezier(.4,0,.2,1)),opacity .28s var(--ease,cubic-bezier(.4,0,.2,1))}
.vx-dec-toast.is-visible{transform:translateX(0);opacity:1}
.vx-dec-toast-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.vx-dec-toast-eyebrow{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--green);font-weight:600}
.vx-dec-toast-close{appearance:none;background:none;border:none;color:var(--text-muted);font-size:.85rem;cursor:pointer;padding:2px 6px;border-radius:4px}
.vx-dec-toast-close:hover{color:var(--ink);background:rgba(28,28,28,.06)}
.vx-dec-toast-context{font-size:.86rem;color:var(--ink);font-weight:500;line-height:1.45;margin-bottom:6px}
.vx-dec-toast-q{font-family:var(--ff-d);font-style:italic;font-size:.95rem;color:var(--green);margin-bottom:6px}
.vx-dec-toast-input{width:100%;padding:8px 10px;border:1px solid var(--border-g);border-radius:6px;font-family:var(--ff-b);font-size:.84rem;line-height:1.5;color:var(--ink);background:var(--cream);resize:vertical;min-height:48px}
.vx-dec-toast-input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.18)}
.vx-dec-toast-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:8px}
.vx-dec-skip{appearance:none;background:transparent;border:1px solid var(--border-g);color:var(--text-mid);font-family:var(--ff-b);font-size:.78rem;padding:6px 12px;border-radius:6px;cursor:pointer}
.vx-dec-skip:hover{border-color:var(--text-mid);color:var(--ink)}
.vx-dec-save{appearance:none;background:var(--green);color:#fff;border:none;font-family:var(--ff-b);font-size:.78rem;font-weight:500;padding:6px 14px;border-radius:6px;cursor:pointer}
.vx-dec-save:hover{background:#1f3a30}
.vx-dec-save:disabled{opacity:.55;cursor:not-allowed}
.vx-dec-toast-err{margin-top:6px;font-size:.74rem;color:#a23030}
@media(max-width:600px){
 .vx-dec-toast-host{right:10px;bottom:10px;left:10px}
 .vx-dec-toast{width:auto}
}

/* ═══ Risk-pattern depth panel (idea #8 v0, 2026-04-29) ════════════
   Renders inside the contract gauge area. Calibrates the risk score
   against the live red_flag_patterns table so couples see what the
   number is grounded in, not just a number. */
.vx-rcp{margin-top:14px;padding:12px 14px;background:rgba(200,169,110,.08);border:1px solid rgba(200,169,110,.22);border-radius:10px}
.vx-rcp-header{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.vx-rcp-eyebrow{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--green);font-weight:600}
.vx-rcp-source{font-family:var(--ff-m);font-size:.6rem;color:var(--text-soft,#7A7A7A);text-transform:uppercase;letter-spacing:.04em;font-style:italic}
.vx-rcp-summary{font-size:.84rem;color:var(--text-mid);line-height:1.6;margin:0 0 10px}
.vx-rcp-summary strong{color:var(--green);font-weight:600}
.vx-rcp-summary .vx-rcp-warn{color:#B94040}
.vx-rcp-summary .vx-rcp-clean{color:#6B8F71}
.vx-rcp-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:7px}
.vx-rcp-match{padding:8px 11px;background:#fff;border-radius:6px;border-left:3px solid var(--gold);font-size:.78rem;line-height:1.55}
.vx-rcp-match.is-high{border-left-color:#B94040}
.vx-rcp-match.is-mid{border-left-color:#C97B3A}
.vx-rcp-match-head{display:flex;align-items:baseline;gap:8px;margin-bottom:3px}
.vx-rcp-sev{flex-shrink:0;font-family:var(--ff-m);font-size:.58rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600;padding:1px 6px;border-radius:3px;background:rgba(28,28,28,.06);color:var(--text-mid)}
.vx-rcp-match.is-high .vx-rcp-sev{background:rgba(185,64,64,.12);color:#B94040}
.vx-rcp-match.is-mid  .vx-rcp-sev{background:rgba(201,123,58,.14);color:#C97B3A}
.vx-rcp-phrase{font-style:italic;color:var(--ink);font-weight:500;font-size:.84rem;line-height:1.45}
.vx-rcp-cost{font-size:.74rem;color:var(--text-mid);margin-bottom:3px}
.vx-rcp-cost strong{color:var(--ink);font-weight:600}
.vx-rcp-evidence{font-size:.74rem;color:var(--text-soft,#7A7A7A);font-style:italic;padding-left:8px;border-left:2px solid rgba(28,28,28,.1);margin-top:3px}

/* ═══ Decision-quality cues — confidence + info-value (idea #1) ═════ */
.vx-cmp-confidence{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:.85rem;padding:.55rem .85rem;border-radius:8px;font-size:.78rem}
.vx-cmp-confidence.is-high{background:rgba(44,74,62,.06);border:1px solid rgba(44,74,62,.18)}
.vx-cmp-confidence.is-moderate{background:rgba(200,169,110,.1);border:1px solid rgba(200,169,110,.25)}
.vx-cmp-confidence.is-low{background:rgba(201,123,58,.08);border:1px solid rgba(201,123,58,.22)}
.vx-cmp-confidence-tag{font-family:var(--ff-m);text-transform:uppercase;letter-spacing:.06em;font-size:.66rem;font-weight:600;flex-shrink:0;padding:2px 8px;border-radius:10px;background:#fff}
.vx-cmp-confidence.is-high .vx-cmp-confidence-tag{color:var(--green)}
.vx-cmp-confidence.is-moderate .vx-cmp-confidence-tag{color:var(--gold-deep,#A07840)}
.vx-cmp-confidence.is-low .vx-cmp-confidence-tag{color:var(--amber-risk,#C97B3A)}
.vx-cmp-confidence-why{color:var(--text-mid);line-height:1.5;flex:1;min-width:200px}
.vx-cmp-infovalue-list{list-style:none;padding:0;margin:0 0 1rem;display:flex;flex-direction:column;gap:.5rem}
.vx-cmp-infovalue-list li{display:flex;flex-direction:column;gap:.2rem;padding:.65rem .9rem;background:rgba(44,74,62,.04);border-left:2.5px solid var(--gold);border-radius:0 8px 8px 0}
.vx-cmp-iv-fact{font-family:var(--ff-b);font-size:.86rem;color:var(--ink);font-weight:500}
.vx-cmp-iv-shift{font-family:var(--ff-b);font-size:.78rem;color:var(--text-mid);font-style:italic}

/* ═══ Personalization tags ═══════════════════════════════════════
   Pill row appended to every AI output to surface which profile fields
   were used. Idea #5 from the 2026-04-29 product review. */
.vx-personal-tags{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin:.85rem 0 0;padding:.55rem .8rem;background:rgba(200,169,110,.1);border:1px solid rgba(200,169,110,.22);border-radius:8px;font-size:.72rem;line-height:1.5}
.vx-personal-tags-label{font-family:var(--ff-m);color:var(--green);text-transform:uppercase;letter-spacing:.06em;font-size:.62rem;margin-right:2px;font-weight:600}
.vx-personal-tag{display:inline-block;padding:1px 8px;background:#fff;border:1px solid rgba(200,169,110,.4);border-radius:11px;color:var(--text-mid);font-family:var(--ff-b);font-size:.7rem}
.vx-personal-tags-more{font-family:var(--ff-m);color:var(--text-soft);font-size:.62rem;margin-left:2px;align-self:center}
.vx-personal-tags-empty{background:rgba(44,74,62,.04);border-color:rgba(44,74,62,.12);border-style:dashed}
.vx-personal-tag-empty{display:inline-block;padding:1px 8px;background:transparent;border:none;color:var(--text-soft);font-family:var(--ff-b);font-style:italic;font-size:.7rem}
.vx-chat-msg-assistant .vx-personal-tags{margin-top:.55rem;background:rgba(44,74,62,.04);border-color:rgba(44,74,62,.1)}

/* ═══ Verdeaux Chat (replaces Find-similar 2026-04-29) ════════════
   Multi-turn chat panel. Lives at the top of section-ideas (Chat
   page). Assistant bubbles align left in cream-on-green; user bubbles
   align right in green-on-cream. Citations render as clickable
   superscripts. */
.vx-chat{max-width:1100px;margin:0 auto 1.75rem;padding:1.5rem 1.75rem 1.75rem;background:linear-gradient(135deg,rgba(200,169,110,.08),rgba(90,140,122,.06));border:1px solid rgba(200,169,110,.3);border-radius:14px;box-shadow:0 1px 0 rgba(44,74,62,.02),0 2px 12px rgba(44,74,62,.05)}
/* 2026-05-06 — anchor the chat composer to the bottom of the viewport
 * area (Claude-style). The chat container fills the viewport minus the
 * top chrome stack (~240px = header 74 + profile bar 48 + step bar +
 * bridge padding); thread takes the flex remainder and scrolls
 * internally; form sits flush at the bottom and never moves. min-height
 * keeps it usable on short viewports, dvh handles iOS address-bar collapse.
 *
 * IMPORTANT: scoped to #section-ideas so other surfaces using the same
 * .vx-chat shell aren't affected. min-height: 0 cascades through the
 * flex chain so the inner thread can shrink and become scrollable —
 * without it, flex's auto-sizing keeps the thread at content height
 * and the form drifts off-screen as messages accumulate. */
/* 2026-05-06 Phase 5b regression fix v2 — the chat root has BOTH classes
 * (.vx-chat .vx-chat-grid) on the SAME element. The earlier chat-anchor
 * CSS set display:flex on .vx-chat which overrode display:grid from
 * .vx-chat-grid, killing the two-column layout. Children stacked as flex
 * column items and the main column collapsed to its content height (~52px).
 * Fix: don't touch display on .vx-chat — let .vx-chat-grid keep display:grid.
 * Set explicit height on the container, force the grid row to fill the
 * height, and put the flex-column behavior on .vx-chat-main internally so
 * the thread can still overflow-scroll. */
#section-ideas .vx-chat{height:calc(100dvh - 240px);min-height:480px}
/* 2026-07-27 (Stephen) — the empty Chat card was mostly dead space (a full
   viewport-tall panel with just the ☰ + input). While the thread is empty
   (#vxChatThread still [hidden]) collapse it to content height; the moment a message
   posts (hidden removed) it returns to the full chat-window height above.
   2026-07-28 — un-scoped from the demo (was body.vx-demo-active): the markup is
   identical for logged-in users, who hit the same dead panel before their first
   message. Universal now (Stephen: the demo simplifications should be our brand). */
#section-ideas .vx-chat:has(#vxChatThread[hidden]){height:auto;min-height:0}
/* Empty thread still reserves space (its .vx-chat-thread display:flex overrides [hidden]);
   truly hide it + drop the form's top margin so the input sits right under the intro. */
#section-ideas .vx-chat:has(#vxChatThread[hidden]) #vxChatThread[hidden]{display:none}
#section-ideas .vx-chat:has(#vxChatThread[hidden]) .vx-chat-form{margin-top:0}
/* 2026-05-09: when a Vera workflow is active, the fixed-bottom concierge
   footer (~140px desktop) overlaps the chat input because .vx-chat is
   viewport-sized, not section-sized. Shrink the chat panel by the footer
   height so the input always lands above the workflow card. Same fix
   would apply to any future viewport-pinned panel in section-ideas. */
body.vx-concierge-active #section-ideas .vx-chat{height:calc(100dvh - 240px - 150px);min-height:360px}
@media (max-width:640px){
 body.vx-concierge-active #section-ideas .vx-chat{height:calc(100dvh - 200px - 220px);min-height:300px}
}
#section-ideas .vx-chat-grid{grid-template-rows:minmax(0,1fr)}
#section-ideas .vx-chat-main{display:flex;flex-direction:column;min-height:0;height:100%}
/* 2026-05-06 Phase 5b — chat-intro fade-on-first-send. The page-title
 * block above the chat card ("Ask anything about your wedding." + sub)
 * is helpful on a brand-new account but takes valuable vertical space
 * once the user is engaged. Mirrors the welcome-video pattern: shown
 * once per user, dismissed on first meaningful action (first message
 * sent), persisted via user_profiles.chat_intro_dismissed_at. While
 * visible, transitions are armed so the dismissal is a clean fade-and-
 * collapse rather than a layout jump. The .vx-chat-intro-fading class
 * triggers the transition; .vx-chat-intro-hidden is the end state
 * (used directly by returning users so there's no fade-in flash). */
#section-ideas .page-title{transition:opacity .55s ease-out, max-height .65s ease-out, margin .55s ease-out, padding .55s ease-out;overflow:hidden;max-height:300px}
#section-ideas .page-title.vx-chat-intro-fading{opacity:0;max-height:0;margin-top:0;margin-bottom:0;padding-top:0;padding-bottom:0;pointer-events:none}
#section-ideas .page-title.vx-chat-intro-hidden{display:none}

/* 2026-05-06 Phase 5b — standard chat layout (Claude/ChatGPT pattern).
 * Input pinned at the BOTTOM of .vx-chat-main, transcript fills the
 * space above. Stephen tested input-at-top briefly but the messaging
 * convention is more familiar to users and the bottom-pinned input
 * keeps the next-action affordance directly under the freshest reply.
 * Auto-scroll keeps the newest message just above the input; the
 * streaming smart-follow logic in _send / _consumeStream stops the
 * yank-back behavior that the older per-delta scroll caused. */
#section-ideas .vx-chat-thread{flex:1;max-height:none;margin:1.1rem 0 0;overflow-y:auto;padding:.25rem .15rem}
#section-ideas .vx-chat-form{flex-shrink:0;margin-top:.85rem}
@media (max-width:640px){
 /* Mobile chrome is taller in proportion; give the chat more breathing room
    by allowing it to shrink, but cap top offset for typical mobile chrome. */
 #section-ideas .vx-chat{height:calc(100dvh - 200px);min-height:420px}
}
.vx-chat-head{margin-bottom:.85rem}
.vx-chat-head .hero-eyebrow{margin:0 0 .3rem;font-size:.6rem}
.vx-chat-h2{font-family:var(--ff-d);font-size:clamp(1.25rem,2.8vw,1.7rem);color:var(--green);font-weight:400;line-height:1.2;margin:0 0 .4rem}
.vx-chat-h2 em{color:var(--gold);font-style:italic}
.vx-chat-sub{font-size:.86rem;color:var(--text-mid);line-height:1.55;margin:0;max-width:640px}
/* 2026-05-04: bare head (hamburger only) — hero copy now lives in the
   page-title block above the chat card, matching Contract IQ. The
   hamburger keeps a small footprint so the thread/form starts cleanly. */
.vx-chat-head-bare{margin-bottom:.5rem;align-items:center;min-height:0}
.vx-chat-head-bare .vx-chat-sidebar-open{margin-left:-4px}
@media (min-width:769px){
 .vx-chat-head-bare{display:none}
}
/* 2026-05-03 chat layout v3 — 2-column grid (sidebar + main).
   Mirrors the gen-Z muscle memory from ChatGPT, Claude, Gemini. */
.vx-chat-grid{display:grid;grid-template-columns:280px 1fr;gap:0;padding:0;overflow:hidden}
.vx-chat-grid .vx-chat-main{padding:1.5rem 1.75rem 1.75rem;min-width:0}
.vx-chat-sidebar{display:flex;flex-direction:column;background:rgba(250,247,242,.6);border-right:1px solid rgba(200,169,110,.18);max-height:calc(85vh - 2rem);min-height:480px}
.vx-chat-sidebar-head{display:flex;align-items:center;gap:8px;padding:14px 16px 10px}
.vx-chat-sidebar-title{flex:1;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep)}
.vx-chat-sidebar-close{display:none;background:transparent;border:0;color:var(--text-muted);font-size:1.2rem;line-height:1;cursor:pointer;padding:4px 8px;border-radius:4px}
.vx-chat-sidebar-open{display:none;background:transparent;border:0;color:var(--green);font-size:1.2rem;line-height:1;cursor:pointer;padding:4px 10px;border-radius:6px;flex-shrink:0;align-self:start;margin-right:.5rem;transition:background .15s}
.vx-chat-sidebar-open:hover{background:rgba(44,74,62,.06)}
/* Top action labels — minimal menu-item styling, not buttons. + New and
   − Delete sit inline like links, separated by a thin dot. − Delete
   toggles delete mode and gets a small accent when active. The destructive
   "Delete (N)" pill lives in the sidebar foot, only visible in delete
   mode (per 2026-05-04 v5 layout request). */
.vx-chat-sidebar-actions{display:flex;align-items:center;gap:10px;padding:6px 16px 10px;border-bottom:1px solid rgba(200,169,110,.15)}
.vx-chat-action-link{background:transparent;border:0;padding:2px 0;font-family:var(--ff-b);font-size:.78rem;font-weight:500;color:var(--text-mid);cursor:pointer;transition:color .15s;letter-spacing:.01em;line-height:1.2}
.vx-chat-action-link:hover{color:var(--ink)}
.vx-chat-action-new{color:var(--green)}
.vx-chat-action-new:hover{color:var(--green-deep,#244038)}
.vx-chat-action-delete:hover{color:#a25050}
.vx-chat-action-delete.is-active{color:#a25050;font-weight:600}
.vx-chat-action-sep{color:rgba(44,74,62,.22);font-size:.7rem;line-height:1.2;user-select:none}
.vx-chat-sidebar-foot{padding:10px 14px 14px;border-top:1px solid rgba(178,90,90,.18);background:rgba(178,90,90,.04);flex-shrink:0}
.vx-chat-delete-confirm{display:block;width:100%;padding:9px 12px;border:1px solid #a25050;background:#a25050;color:#fff;border-radius:8px;font-family:var(--ff-b);font-size:.78rem;font-weight:500;cursor:pointer;transition:all .15s;letter-spacing:.01em}
.vx-chat-delete-confirm:disabled{opacity:.45;cursor:not-allowed}
.vx-chat-delete-confirm:not(:disabled):hover{background:#8c4242;border-color:#8c4242}
.vx-chat-history-list{flex:1;overflow-y:auto;padding:8px 10px 14px;display:flex;flex-direction:column;gap:2px;min-height:0}
.vx-chat-history-row{position:relative;display:flex;align-items:center;gap:8px;padding:8px 12px;background:transparent;border:1px solid transparent;border-radius:6px;cursor:pointer;transition:all .15s;text-align:left;width:100%;overflow:hidden}
.vx-chat-history-row:hover{background:rgba(255,255,255,.9);border-color:rgba(44,74,62,.08)}
.vx-chat-history-row.is-active{background:rgba(90,140,122,.08);border-color:rgba(90,140,122,.25)}
.vx-chat-history-row-title{flex:1;font-family:var(--ff-b);font-size:.82rem;font-weight:500;color:var(--ink);line-height:1.35;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;mask-image:linear-gradient(to right,#000 calc(100% - 18px),transparent 100%);-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 18px),transparent 100%)}
.vx-chat-history-row.is-selectable{padding-left:8px}
.vx-chat-history-row-check{flex-shrink:0;width:14px;height:14px;border:1.5px solid rgba(44,74,62,.35);border-radius:3px;background:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:.7rem;color:transparent;transition:all .12s}
.vx-chat-history-row.is-checked .vx-chat-history-row-check{background:#a25050;border-color:#a25050;color:#fff}
.vx-chat-history-empty{padding:14px 6px;font-size:.76rem;color:var(--text-muted);font-style:italic;text-align:center}
.vx-chat-sidebar-backdrop{display:none;position:fixed;inset:0;background:rgba(28,28,28,.4);z-index:99;animation:vx-fade-in .2s ease-out}
.vx-chat-head{display:flex;align-items:flex-start;gap:8px}
.vx-chat-head-text{flex:1;min-width:0;margin-bottom:.85rem}
@keyframes vx-fade-in{from{opacity:0}to{opacity:1}}
@media (max-width:768px){
 .vx-chat-grid{grid-template-columns:1fr}
 .vx-chat-grid .vx-chat-main{padding:1.25rem 1.25rem 1.5rem}
 .vx-chat-sidebar{position:fixed;top:0;left:0;bottom:0;width:min(86vw,320px);max-height:none;height:100vh;z-index:100;background:var(--cream,#FAF7F2);border-right:1px solid rgba(200,169,110,.3);box-shadow:2px 0 24px rgba(28,28,28,.18);transform:translateX(-100%);transition:transform .25s ease-out}
 .vx-chat-sidebar.is-open{transform:translateX(0)}
 .vx-chat-sidebar-close{display:inline-flex}
 .vx-chat-sidebar-open{display:inline-flex}
 .vx-chat-sidebar-backdrop.is-open{display:block}
 .vx-chat-history-row-title{font-size:.86rem}
}
.vx-chat-thread{display:flex;flex-direction:column;gap:.85rem;margin:1.1rem 0;max-height:60vh;overflow-y:auto;padding:.25rem .15rem}
.vx-chat-msg{max-width:88%;padding:.75rem 1rem;border-radius:14px;font-size:.92rem;line-height:1.6;color:var(--ink);box-shadow:0 1px 3px rgba(44,74,62,.05)}
.vx-chat-msg p{margin:0 0 .55rem}
.vx-chat-msg p:last-child{margin-bottom:0}
.vx-chat-msg strong{color:var(--green);font-weight:600}
.vx-chat-msg-user{align-self:flex-end;background:var(--green);color:var(--cream);border-bottom-right-radius:4px}
.vx-chat-msg-user strong{color:var(--cream)}
.vx-chat-msg-assistant{align-self:flex-start;background:#fff;border:1px solid rgba(200,169,110,.28);border-bottom-left-radius:4px}
.vx-chat-msg-assistant.is-streaming::after{content:"▋";display:inline-block;color:var(--gold);animation:vx-chat-blink 1s steps(2,end) infinite;margin-left:1px}
@keyframes vx-chat-blink{50%{opacity:0}}
.vx-cite{color:var(--gold);cursor:pointer;font-weight:600;font-size:.7em;margin:0 1px;text-decoration:none}
.vx-cite:hover{color:var(--green);text-decoration:underline}
/* 2026-05-07 — inline chat links written by the AI (markdown [text](href))
   for handing off to other tabs. Subtle gold underline echoes the cite
   markers; hover deepens to green. Internal-link routing handled in
   _handleChatLinkClick — these never page-reload. */
.vx-chat-link{color:var(--green);text-decoration:underline;text-decoration-color:rgba(200,169,110,.55);text-underline-offset:2px;font-weight:500;cursor:pointer;transition:color .12s,text-decoration-color .12s}
.vx-chat-link:hover{color:#1f3a30;text-decoration-color:var(--gold)}
.vx-chat-msg-sources{margin-top:.65rem;padding:.5rem .65rem;background:rgba(44,74,62,.04);border-radius:8px;font-size:.78rem;color:var(--text-mid)}
.vx-chat-msg-sources summary{cursor:pointer;font-family:var(--ff-m);font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;color:var(--green);outline:none}
.vx-chat-msg-sources ol{margin:.5rem 0 0;padding-left:1.4rem;line-height:1.6}
.vx-chat-msg-sources li::marker{color:var(--gold)}
.vx-chat-msg-sources a{color:var(--green);text-decoration:underline;text-decoration-color:rgba(44,74,62,.3)}
.vx-chat-msg-sources a:hover{text-decoration-color:var(--gold)}
.vx-chat-msg-sources .vx-src-domain{display:inline-block;margin-left:.4rem;color:var(--text-soft);font-family:var(--ff-m);font-size:.68rem}
/* 2026-08-05 (Stephen) — the retrieval stamp. Gold pill so the DATE is the thing
   the eye lands on in the summary row: it is the part a couple can actually
   evaluate, where "freshness" is invisible to them. Deliberately quiet — this is
   a fact we're recording, not a badge we're boasting with. */
.vx-chat-msg-sources summary .vx-src-checked{display:inline-block;margin-left:.5rem;padding:1px 7px;border-radius:20px;background:rgba(200,169,110,.16);color:var(--gold-deep,#A07840);font-family:var(--ff-m);font-size:.6rem;letter-spacing:.05em;text-transform:none;font-weight:500;vertical-align:1px}
.vx-chat-quickstart{margin:.85rem 0 .25rem}
.vx-chat-quickstart-label{font-family:var(--ff-m);font-size:.66rem;color:var(--text-mid);text-transform:uppercase;letter-spacing:.08em;margin-bottom:.5rem}
.vx-chat-chips{display:flex;flex-wrap:wrap;gap:.4rem}
.vx-chat-chip{appearance:none;background:#fff;border:1px solid rgba(200,169,110,.4);color:var(--green);font-family:var(--ff-b);font-size:.78rem;padding:.45rem .8rem;border-radius:18px;cursor:pointer;line-height:1.3;transition:all .15s ease}
.vx-chat-chip:hover{background:var(--green);color:var(--cream);border-color:var(--green)}
.vx-chat-form{display:flex;flex-direction:column;gap:.5rem;margin-top:.85rem}
.vx-chat-form textarea{width:100%;padding:.7rem .85rem;border:1px solid rgba(44,74,62,.2);border-radius:10px;font-family:var(--ff-b);font-size:.92rem;color:var(--ink);background:#fff;resize:vertical;min-height:50px;line-height:1.5}
.vx-chat-form textarea:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.18)}
.vx-chat-form textarea:disabled{opacity:.6;background:rgba(44,74,62,.03)}
.vx-chat-actions{display:flex;align-items:center;gap:.65rem}
.vx-chat-count{flex:1;font-family:var(--ff-m);font-size:.66rem;color:var(--text-soft)}
.vx-chat-new{appearance:none;background:transparent;border:1px solid rgba(44,74,62,.2);color:var(--text-mid);font-family:var(--ff-b);font-size:.74rem;padding:.4rem .75rem;border-radius:6px;cursor:pointer}
.vx-chat-new:hover{border-color:var(--green);color:var(--green)}
.vx-chat-share{appearance:none;background:transparent;border:1px solid rgba(44,74,62,.18);color:var(--text-mid);font-family:var(--ff-b);font-size:.74rem;padding:.4rem .65rem;border-radius:6px;cursor:pointer}
.vx-chat-share:hover{border-color:var(--gold);color:var(--gold-deep)}
.vx-chat-btn{appearance:none;background:var(--green);color:var(--cream);border:none;font-family:var(--ff-b);font-size:.86rem;font-weight:600;padding:.55rem 1.25rem;border-radius:8px;cursor:pointer;transition:background .15s ease}
.vx-chat-btn:hover{background:#1f3a30}
.vx-chat-btn:disabled{opacity:.55;cursor:not-allowed}
.vx-chat-error{margin-top:.6rem;padding:.6rem .85rem;background:rgba(220,80,80,.08);border:1px solid rgba(220,80,80,.25);border-radius:8px;color:#a23030;font-size:.82rem}
.vx-chat-thinking{display:flex;align-items:center;gap:.55rem;color:var(--text-mid);font-size:.82rem;font-style:italic;padding:.4rem 0}
.vx-chat-thinking-dot{width:6px;height:6px;background:var(--gold);border-radius:50%;animation:vx-chat-pulse 1.2s ease-in-out infinite}
.vx-chat-thinking-dot:nth-child(2){animation-delay:.15s}
.vx-chat-thinking-dot:nth-child(3){animation-delay:.3s}
@keyframes vx-chat-pulse{0%,80%,100%{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1.1)}}
@media (max-width:600px){
 .vx-chat{padding:1.1rem 1rem 1.25rem}
 .vx-chat-msg{max-width:94%;font-size:.87rem;padding:.65rem .85rem}
 .vx-chat-thread{max-height:55vh}
 .vx-chat-chips{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.4rem;-webkit-overflow-scrolling:touch}
 .vx-chat-chip{flex-shrink:0;font-size:.74rem;padding:.4rem .7rem}
}

/* ═══ Multi-vendor mention card (chat, 2026-05-05) ════════════════════
   Renders below the assistant's bubble when 1-3 specific vendors are
   detected in the user message OR assistant reply. Each row has its own
   "+ Add" button so the user can pick exactly which to track. The
   first detected vendor also drives Slices 4-6 (peer signal, geography,
   archetype) for the most-relevant vendor only. */
.vx-chat-mvc{position:relative;margin:8px 0 16px;padding:14px 16px 16px;border:1px solid rgba(200,169,110,.3);border-radius:12px;background:#fff;max-width:560px;font-family:var(--ff-b);box-shadow:0 1px 4px rgba(44,74,62,.04)}
.vx-chat-mvc-head{font-family:var(--ff-d);font-size:1rem;font-weight:400;color:var(--green);padding-right:24px;line-height:1.3}
.vx-chat-mvc-head em{color:var(--gold);font-style:italic}
.vx-chat-mvc-sub{font-size:.78rem;color:var(--text-mid);margin-top:4px;line-height:1.5}
.vx-chat-mvc-list{margin-top:12px;display:flex;flex-direction:column;gap:8px}
.vx-chat-mvc-row{display:flex;align-items:center;gap:10px;padding:9px 11px;border:1px solid rgba(44,74,62,.08);border-radius:8px;background:rgba(250,247,242,.45);transition:background .12s,border-color .12s}
.vx-chat-mvc-row:hover{background:#fff;border-color:rgba(200,169,110,.35)}
.vx-chat-mvc-row-info{flex:1;min-width:0}
.vx-chat-mvc-name{font-size:.88rem;color:var(--ink);font-weight:500;line-height:1.3;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.vx-chat-mvc-rating{font-size:.7rem;color:var(--text-muted);font-weight:400;font-family:var(--ff-m)}
.vx-chat-mvc-address{font-size:.72rem;color:var(--text-muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vx-chat-mvc-add{flex-shrink:0;padding:7px 14px;border:1px solid var(--green);background:var(--green);color:#fff;border-radius:40px;font-family:var(--ff-b);font-size:.74rem;font-weight:500;cursor:pointer;transition:background .12s,transform .12s}
.vx-chat-mvc-add:hover:not(:disabled){background:#1f3a30;transform:translateY(-1px)}
.vx-chat-mvc-add:disabled{opacity:.7;cursor:default;transform:none}
.vx-chat-mvc-row-added{background:rgba(90,140,122,.08);border-color:rgba(90,140,122,.35)}
.vx-chat-mvc-row-added .vx-chat-mvc-add{background:#5a8c7a;border-color:#5a8c7a}
.vx-chat-mvc-dismiss{position:absolute;top:8px;right:10px;background:transparent;border:0;color:var(--ink-faint);font-size:1.1rem;line-height:1;cursor:pointer;padding:2px 6px;border-radius:4px;transition:color .12s,background .12s}
.vx-chat-mvc-dismiss:hover{color:var(--ink);background:rgba(44,74,62,.06)}
/* 2026-05-06 Phase 3 — bulk Add-all CTA + status. Sits between the
   sub-line and the per-vendor list. Button mirrors .vx-chat-mvc-add
   sizing but spans wider; status appears inline as count or final
   "Open Vendor+ →" deep link. */
.vx-chat-mvc-bulk{display:flex;align-items:center;gap:10px;margin-top:10px;padding-top:10px;border-top:1px dashed rgba(44,74,62,.1)}
.vx-chat-mvc-add-all{flex-shrink:0;padding:7px 16px;border:1px solid var(--gold);background:var(--gold);color:#fff;border-radius:40px;font-family:var(--ff-b);font-size:.74rem;font-weight:500;cursor:pointer;transition:background .12s,transform .12s}
.vx-chat-mvc-add-all:hover:not(:disabled){background:#b89a5e;border-color:#b89a5e;transform:translateY(-1px)}
.vx-chat-mvc-add-all:disabled{opacity:.7;cursor:default;transform:none}
.vx-chat-mvc-bulk-status{font-family:var(--ff-m);font-size:.72rem;color:var(--text-muted);letter-spacing:.04em}
.vx-chat-mvc-bulk-nav{color:var(--green);text-decoration:underline;font-family:var(--ff-b);font-size:.78rem;font-weight:500;letter-spacing:0}
.vx-chat-mvc-bulk-nav:hover{color:#1e3329}

/* ═══ 2026-05-06 Phase 5b — auto-fire wait + reveal cards ═══
 *  - Wait card: subtle sage tint, narrating progress fades through
 *    fixed beats while per-vendor dots flip from amber to green as
 *    the deeper-dive jobs land.
 *  - Reveal card: drop-in animation on the "Ready when you are.
 *    Take me there →" link so the swap feels like a gift, not a
 *    spinner finishing.
 */
.vx-chat-autofire-wait{background:linear-gradient(180deg,rgba(90,140,122,.06),rgba(200,169,110,.04));border-color:rgba(90,140,122,.28)}
.vx-chat-autofire-wait .vx-chat-mvc-head{color:var(--green);display:flex;align-items:center;gap:8px}
.vx-chat-wait-spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--gold,#C8A96E);animation:vx-wait-pulse 1.4s ease-in-out infinite;font-size:0;color:transparent}
@keyframes vx-wait-pulse{0%,100%{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1.15)}}
.vx-chat-wait-narration{transition:opacity .25s ease-out;min-height:1.4em;font-style:italic;color:var(--text-mid)}
.vx-chat-wait-row{align-items:center}
.vx-chat-wait-row .vx-chat-mvc-address{transition:color .2s}
.vx-chat-wait-dot{width:9px;height:9px;border-radius:50%;background:rgba(200,169,110,.5);box-shadow:0 0 0 2px rgba(200,169,110,.18);flex-shrink:0;transition:background .25s,box-shadow .25s,transform .25s;animation:vx-wait-pulse 1.6s ease-in-out infinite}
.vx-chat-wait-row-done .vx-chat-wait-dot{background:#5a8c7a;box-shadow:0 0 0 2px rgba(90,140,122,.22);animation:none;transform:scale(1.05)}
.vx-chat-wait-row-done .vx-chat-mvc-address{color:var(--green)}
.vx-chat-reveal{animation:vx-reveal-in .55s cubic-bezier(.18,.85,.33,1.05) both}
.vx-chat-reveal .vx-chat-reveal-cta{animation:vx-reveal-link-in .7s .15s cubic-bezier(.2,.9,.3,1.05) both}
.vx-chat-reveal .vx-chat-mvc-bulk-nav{font-family:var(--ff-d);font-size:.95rem;font-weight:400;color:var(--green);text-decoration:none;border-bottom:1px solid var(--gold,#C8A96E);padding-bottom:2px;letter-spacing:.005em}
.vx-chat-reveal .vx-chat-mvc-bulk-nav:hover{color:#1e3329;border-bottom-color:#1e3329}
@keyframes vx-reveal-in{from{opacity:.4;transform:scale(.985)}to{opacity:1;transform:scale(1)}}
@keyframes vx-reveal-link-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}

/* ═══ 2026-05-07 — Always-on elicitation cards (Apply / Search proposal) ═══
   Stronger visual treatment than passive observation cards: cream-tinted
   background + sage left-accent + small-caps eyebrow signal "your input
   shapes this." Prevents the "lost in long scrolls" issue Stephen flagged
   where cards visually blended into AI message bubbles. */
.vx-chat-mvc-elicit{background:linear-gradient(180deg,rgba(250,247,242,.92),rgba(242,235,224,.7));border:1px solid rgba(200,169,110,.32);border-left:3px solid #5a8c7a;box-shadow:0 1px 4px rgba(44,74,62,.07),0 0 0 1px rgba(255,255,255,.4) inset}
.vx-chat-mvc-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:6px}
.vx-chat-mvc-elicit-row{padding:12px 0;border-bottom:1px dashed rgba(44,74,62,.1)}
.vx-chat-mvc-elicit-row:first-child{padding-top:8px}
.vx-chat-mvc-elicit-row:last-child{border-bottom:0;padding-bottom:0}
.vx-chat-mvc-elicit-cat{font-family:var(--ff-d);font-size:1rem;font-weight:500;color:var(--green);line-height:1.3}
.vx-chat-mvc-elicit-source{font-style:italic;font-size:.78rem;color:var(--text-muted);margin-top:3px;line-height:1.45}
.vx-chat-mvc-elicit-fields{display:grid;grid-template-columns:140px 1fr;gap:10px;margin-top:10px;align-items:end}
.vx-chat-mvc-elicit-field{display:flex;flex-direction:column;gap:4px;min-width:0}
.vx-chat-mvc-elicit-label{font-family:var(--ff-m);font-size:.62rem;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:var(--text-mid)}
.vx-chat-mvc-elicit-label em{font-style:normal;color:var(--text-muted);font-weight:400;letter-spacing:.04em;text-transform:none}
.vx-chat-mvc-elicit-amt-wrap{position:relative;display:flex;align-items:center}
.vx-chat-mvc-elicit-dollar{position:absolute;left:9px;font-size:.86rem;color:var(--text-muted);pointer-events:none;font-family:var(--ff-b)}
.vx-chat-mvc-elicit-amount{flex:1;width:100%;padding:7px 10px 7px 20px;border:1px solid rgba(44,74,62,.18);border-radius:7px;font-family:var(--ff-b);font-size:.92rem;background:#fff;color:var(--ink)}
.vx-chat-mvc-elicit-amount:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.18)}
.vx-chat-mvc-elicit-amount:disabled{opacity:.65;background:rgba(250,247,242,.55);cursor:default}
.vx-chat-mvc-elicit-note{padding:7px 10px;border:1px solid rgba(44,74,62,.18);border-radius:7px;font-family:var(--ff-b);font-size:.86rem;background:#fff;color:var(--ink);width:100%}
.vx-chat-mvc-elicit-note:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 2px rgba(200,169,110,.18)}
.vx-chat-mvc-elicit-note:disabled{opacity:.65;background:rgba(250,247,242,.55);cursor:default}
.vx-chat-mvc-elicit-note::placeholder{color:rgba(44,74,62,.35);font-style:italic}
.vx-chat-mvc-elicit-cta{margin-top:11px;display:flex;justify-content:flex-end}
.vx-chat-mvc-elicit-cta .vx-chat-mvc-add{padding:8px 18px;font-size:.78rem}
.vx-chat-mvc-elicit-row-applied .vx-chat-mvc-elicit-cat{color:#5a8c7a}
.vx-chat-mvc-elicit-row-applied .vx-chat-mvc-elicit-source{opacity:.7}
.vx-chat-mvc-elicit-delta{margin-top:8px;font-family:var(--ff-m);font-size:.7rem;color:#5a8c7a;letter-spacing:.04em;font-weight:500}
.vx-chat-mvc-elicit-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.vx-chat-mvc-elicit-chip{display:inline-flex;align-items:center;padding:3px 10px;border-radius:100px;background:rgba(90,140,122,.1);color:#3b6e5a;font-family:var(--ff-m);font-size:.66rem;letter-spacing:.04em;font-weight:500}

/* 2026-05-07 — Claude.ai-style prompt: clean question + numbered choices
   with subtle hairline dividers between rows. Drop the cream/sage elicit
   visual when the prompt shape is in use — neutral white container with
   light dividers reads as a structured Y/N call rather than a styled card. */
.vx-chat-mvc.vx-chat-mvc-prompt{background:#fff;border:1px solid rgba(44,74,62,.1);border-left:1px solid rgba(44,74,62,.1);box-shadow:0 1px 2px rgba(44,74,62,.04)}
.vx-chat-mvc-prompt{outline:none}
.vx-chat-mvc-prompt:focus-visible{box-shadow:0 0 0 2px rgba(200,169,110,.45),0 1px 2px rgba(44,74,62,.04)}
.vx-chat-mvc-prompt .vx-chat-mvc-eyebrow{display:none}
.vx-chat-mvc-prompt-q{font-family:var(--ff-d);font-size:1.05rem;font-weight:500;color:var(--ink);padding-right:24px;line-height:1.35;margin-bottom:8px}
.vx-chat-mvc-prompt-q em{color:var(--gold);font-style:italic}
.vx-chat-mvc-prompt-list{display:flex;flex-direction:column;margin-top:4px;border-top:1px solid rgba(44,74,62,.06)}
.vx-chat-mvc-prompt-row{display:flex;align-items:center;gap:12px;padding:11px 4px;border-bottom:1px solid rgba(44,74,62,.06);background:transparent;cursor:pointer;transition:background .12s;outline:none;font-family:var(--ff-b)}
.vx-chat-mvc-prompt-row:hover,
.vx-chat-mvc-prompt-row.is-focused,
.vx-chat-mvc-prompt-row:focus-visible{background:rgba(250,247,242,.6)}
.vx-chat-mvc-prompt-row.is-focused .vx-chat-mvc-prompt-arrow{color:var(--green);transform:translateX(2px)}
.vx-chat-mvc-prompt-num{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:5px;background:rgba(44,74,62,.05);color:var(--text-mid);font-family:var(--ff-m);font-size:.72rem;font-weight:500}
.vx-chat-mvc-prompt-label{flex:1;min-width:0;font-size:.92rem;color:var(--ink);font-weight:400;line-height:1.4}
.vx-chat-mvc-prompt-ctx{flex-shrink:0;font-family:var(--ff-m);font-size:.68rem;color:var(--text-muted);letter-spacing:.04em;margin-left:auto}
.vx-chat-mvc-prompt-arrow{flex-shrink:0;font-size:.95rem;color:rgba(44,74,62,.3);transition:color .12s,transform .12s}
.vx-chat-mvc-prompt-foot{display:flex;align-items:center;gap:8px;margin-top:0}
.vx-chat-mvc-prompt-elsewise{flex:1;border-bottom:0}
.vx-chat-mvc-prompt-elsewise .vx-chat-mvc-prompt-num{background:transparent;color:var(--text-muted);font-size:.85rem}
.vx-chat-mvc-prompt-elsewise .vx-chat-mvc-prompt-label{color:var(--text-mid);font-weight:400}
.vx-chat-mvc-prompt-skip{flex-shrink:0;background:transparent;border:1px solid rgba(44,74,62,.18);color:var(--text-mid);font-family:var(--ff-b);font-size:.74rem;padding:.35rem .8rem;border-radius:6px;cursor:pointer;transition:border-color .12s,color .12s}
.vx-chat-mvc-prompt-skip:hover{border-color:var(--green);color:var(--green)}
.vx-chat-mvc-prompt-keys{margin-top:10px;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.04em;color:var(--text-soft);text-align:center}

/* 2026-05-08 — Recommendation card candidate read. Sits between question
   and numbered options. Restrained typography — the candidate is the visual
   anchor but the prompt list is what gets tapped, so it shouldn't compete.
   Cream/sage tint differentiates the read from the row backgrounds. */
.vx-chat-rec-candidate{margin:6px 0 12px;padding:11px 12px;background:rgba(250,247,242,.7);border:1px solid rgba(200,169,110,.22);border-radius:8px}
.vx-chat-rec-name{font-family:var(--ff-d);font-size:1rem;font-weight:500;color:var(--green);line-height:1.3}
.vx-chat-rec-meta{font-family:var(--ff-m);font-size:.7rem;color:var(--text-mid);letter-spacing:.04em;margin-top:3px}
.vx-chat-rec-blurb{font-size:.82rem;color:var(--ink);line-height:1.5;margin-top:6px;font-style:italic}
.vx-chat-rec-actioned{opacity:.78}
@media (max-width:520px){
 .vx-chat-mvc-elicit-fields{grid-template-columns:1fr;gap:8px}
 .vx-chat-mvc-prompt-ctx{display:none}
 .vx-chat-mvc-prompt-keys{display:none}
}

/* ═══ Find-similar-situations card (Insights page, above the grid) ═══ */
.vx-similar{max-width:1100px;margin:0 auto 1.75rem;padding:1.5rem 1.75rem 1.75rem;background:linear-gradient(135deg,rgba(200,169,110,.08),rgba(90,140,122,.06));border:1px solid rgba(200,169,110,.3);border-radius:14px;box-shadow:0 1px 0 rgba(44,74,62,.02),0 2px 12px rgba(44,74,62,.05)}
.vx-similar-head{margin-bottom:.85rem}
.vx-similar-head .hero-eyebrow{margin:0 0 .3rem;font-size:.6rem}
.vx-similar-h2{font-family:var(--ff-d);font-size:clamp(1.25rem,2.8vw,1.7rem);color:var(--green);font-weight:400;line-height:1.2;margin:0 0 .4rem}
.vx-similar-h2 em{color:var(--gold);font-style:italic}
.vx-similar-sub{font-size:.86rem;color:var(--text-mid);line-height:1.55;margin:0;max-width:640px}
.vx-similar-form{margin-top:1rem}
.vx-similar-form textarea{width:100%;box-sizing:border-box;padding:12px 14px;border:1.5px solid var(--border-g);border-radius:10px;background:var(--white);font-family:var(--ff-b);font-size:.92rem;color:var(--ink);line-height:1.5;resize:vertical;min-height:54px;transition:border-color .15s,background .15s}
.vx-similar-form textarea:focus{outline:none;border-color:var(--green);background:#fff;box-shadow:0 0 0 3px rgba(90,140,122,.12)}
.vx-similar-actions{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-top:.6rem}
.vx-similar-count{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.vx-similar-btn{appearance:none;background:var(--green);color:var(--white);border:1px solid var(--green);border-radius:8px;padding:10px 22px;font-family:var(--ff-b);font-size:.86rem;font-weight:500;cursor:pointer;transition:all .15s;min-height:40px;min-width:110px}
.vx-similar-btn:hover{background:#234e40;border-color:#234e40}
.vx-similar-btn:disabled{opacity:.6;cursor:not-allowed}
.vx-similar-result{margin-top:1.25rem;padding-top:1rem;border-top:1px dashed rgba(44,74,62,.15)}
.vx-similar-result[hidden]{display:none}
.vx-similar-loading{display:flex;align-items:center;gap:10px;font-size:.86rem;color:var(--text-mid);padding:.75rem 0}
.vx-similar-loading[hidden]{display:none}
.vx-similar-spinner{width:14px;height:14px;border:2px solid rgba(90,140,122,.25);border-top-color:var(--green);border-radius:50%;animation:vx-similar-spin .8s linear infinite;flex-shrink:0}
@keyframes vx-similar-spin{to{transform:rotate(360deg)}}
.vx-similar-error{padding:.75rem 1rem;background:rgba(185,64,64,.06);border:1px solid rgba(185,64,64,.3);border-radius:8px;color:#B94040;font-size:.86rem}
.vx-similar-error[hidden]{display:none}
.vx-similar-body[hidden]{display:none}
.vx-similar-query-line{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-bottom:.85rem;padding:.5rem .75rem;background:rgba(44,74,62,.04);border-radius:6px;word-break:break-word}
.vx-similar-query-line strong{color:var(--green);font-weight:500;text-transform:none;letter-spacing:0;font-family:var(--ff-b);font-size:.84rem;display:block;margin-top:2px}
.vx-similar-summary{font-size:.94rem;color:var(--ink);line-height:1.65;white-space:pre-wrap}
.vx-similar-summary p{margin:0 0 .75rem}
.vx-similar-summary p:last-child{margin-bottom:0}
.vx-similar-summary sup.vx-cite{color:var(--green);font-weight:500;font-size:.72em;cursor:pointer;margin-left:1px}
.vx-similar-summary sup.vx-cite:hover{text-decoration:underline}
.vx-similar-sources{margin-top:1rem;padding-top:.75rem;border-top:1px solid rgba(44,74,62,.08)}
.vx-similar-sources summary{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);cursor:pointer;padding:.25rem 0;font-weight:500;list-style:none}
.vx-similar-sources summary::-webkit-details-marker{display:none}
.vx-similar-sources summary::before{content:"▸";display:inline-block;margin-right:6px;transition:transform .15s}
.vx-similar-sources[open] summary::before{transform:rotate(90deg)}
.vx-similar-sources ol{margin:.5rem 0 0;padding-left:1.5rem;font-size:.84rem;color:var(--text-mid);line-height:1.55}
.vx-similar-sources ol li{margin-bottom:.55rem}
.vx-similar-sources ol li a{color:var(--green);text-decoration:none;border-bottom:1px dotted rgba(44,74,62,.3)}
.vx-similar-sources ol li a:hover{border-bottom-color:var(--green)}
.vx-similar-sources .vx-src-domain{font-family:var(--ff-m);font-size:.56rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-left:6px}
.vx-similar-sources .vx-src-why{display:block;font-size:.78rem;color:var(--text-muted);margin-top:2px;font-style:italic}
/* Meta header strip — date / time / read-time. Mobile-friendly: small,
 typographic, doesn't compete with the synthesis itself. */
.vx-similar-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 .85rem;font-family:var(--ff-m);font-size:.66rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted)}
.vx-similar-meta .vx-meta-when{color:var(--text-mid)}
.vx-similar-meta .vx-meta-read{color:var(--gold-deep);font-weight:500}
.vx-similar-meta .vx-meta-dot{color:var(--text-muted);opacity:.6}

/* Summary truncation on mobile + tablet only. The wrap clips to roughly
 half a phone screen and a soft gradient fades into a "Read full answer"
 button — gradient affordance reads cleaner than "...". Desktop ignores
 this whole block so power users see everything in one shot. */
.vx-similar-summary-wrap{position:relative}
.vx-similar-expand{display:none;align-items:center;justify-content:center;gap:6px;width:100%;margin:.5rem 0 0;padding:10px 14px;appearance:none;background:var(--green-pale,rgba(44,74,62,.05));color:var(--green);border:1px solid var(--green);border-radius:8px;font-family:var(--ff-b);font-size:.82rem;font-weight:500;cursor:pointer;transition:all .15s}
.vx-similar-expand:hover{background:var(--green);color:var(--white)}
.vx-similar-expand .vx-expand-chevron{transition:transform .2s ease}
.vx-similar-expand[aria-expanded="true"] .vx-expand-chevron{transform:rotate(180deg)}

@media (max-width:1024px){
 .vx-similar-summary-wrap{max-height:280px;overflow:hidden;transition:max-height .25s ease}
 .vx-similar-summary-wrap.is-expanded{max-height:none}
 .vx-similar-summary-wrap::after{content:"";position:absolute;left:0;right:0;bottom:0;height:90px;background:linear-gradient(to bottom, rgba(255,255,255,0) 0%, var(--white,#fff) 75%);pointer-events:none;transition:opacity .2s ease}
 .vx-similar-summary-wrap.is-expanded::after{opacity:0}
 .vx-similar-expand{display:flex}
}

.vx-similar-clear{appearance:none;background:transparent;color:var(--text-mid);border:1px solid var(--border-g);border-radius:8px;padding:8px 14px;font-family:var(--ff-b);font-size:.78rem;cursor:pointer;transition:all .15s}
.vx-similar-clear:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}

/* Save / Share / Print row — added 2026-04-25. Wraps on small screens. */
.vx-similar-actions-row{display:flex;flex-wrap:wrap;align-items:center;gap:.55rem;margin-top:1rem}
.vx-similar-act{appearance:none;display:inline-flex;align-items:center;gap:6px;background:transparent;color:var(--text-mid);border:1px solid var(--border-g);border-radius:8px;padding:8px 12px;font-family:var(--ff-b);font-size:.78rem;cursor:pointer;transition:all .15s}
.vx-similar-act:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vx-similar-act:disabled{opacity:.55;cursor:default;background:transparent;color:var(--text-mid);border-color:var(--border-g)}
.vx-similar-act-primary{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-similar-act-primary:hover{background:var(--green-deep,var(--green));border-color:var(--green-deep,var(--green));color:var(--white);filter:brightness(.95)}
.vx-similar-act-primary.is-saved{background:transparent;color:var(--green);border-color:var(--green)}
.vx-similar-act-primary.is-saved:hover{filter:none;cursor:default}
.vx-similar-act svg{flex-shrink:0}
.vx-similar-act-status{font-family:var(--ff-m);font-size:.7rem;color:var(--green);margin-top:.55rem;letter-spacing:.04em}
.vx-similar-act-status.is-err{color:var(--danger,#a85a3c)}

@media (max-width:767px){
 .vx-similar{padding:1.25rem 1.25rem 1.5rem;margin-bottom:1.25rem}
 .vx-similar-h2{font-size:1.15rem}
 .vx-similar-sub{font-size:.82rem}
 .vx-similar-actions{flex-direction:column-reverse;align-items:stretch;gap:.6rem}
 .vx-similar-btn{width:100%}
 .vx-similar-form textarea{font-size:16px}
 /* On phones, stack the action buttons full-width so each is easy to thumb. */
 .vx-similar-actions-row{flex-direction:column;align-items:stretch}
 .vx-similar-act,.vx-similar-clear{width:100%;justify-content:center}
}

/* Print: show only the Find Similar synthesis + sources. Strip site
 chrome so the user gets a clean printable / save-as-PDF page. */
@media print {
 body * { visibility: hidden !important; }
 #section-ideas .vx-similar,
 #section-ideas .vx-similar * { visibility: visible !important; }
 #section-ideas .vx-similar { position: absolute; left: 0; top: 0; width: 100%; padding: 0; margin: 0; box-shadow: none; border: 0; background: white; }
 #section-ideas .vx-similar-form,
 #section-ideas .vx-similar-loading,
 #section-ideas .vx-similar-actions-row,
 #section-ideas .vx-similar-act-status,
 #section-ideas .vx-similar-expand,
 #section-ideas .vx-similar-clear { display: none !important; }
 #section-ideas .vx-similar-sources { background: white !important; border: 1px solid #ccc !important; }
 #section-ideas .vx-similar-sources[open] summary { font-weight: 600; }
 /* Always show the full summary in print, regardless of mobile clipping. */
 #section-ideas .vx-similar-summary-wrap { max-height: none !important; overflow: visible !important; }
 #section-ideas .vx-similar-summary-wrap::after { display: none !important; }
}

/* ═══ Ideas preferences-from-Profile hint (shown when chips auto-applied) ═ */
.ideas-prefs-hint{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;margin:0 auto 12px;background:rgba(200,169,110,.08);border:1px solid rgba(200,169,110,.3);border-radius:999px;font-size:.82rem;color:var(--text-mid);max-width:fit-content;color:#8A6B2B}
.ideas-prefs-hint[hidden]{display:none}
.ideas-prefs-hint svg{color:var(--gold)}
.ideas-prefs-hint strong{color:var(--green);font-weight:500}
.ideas-prefs-change{color:var(--green);margin-left:4px;text-decoration:none;border-bottom:1px dotted rgba(44,74,62,.4);font-weight:500}
.ideas-prefs-change:hover{border-bottom-color:var(--green)}
@media (max-width: 620px){
 .ideas-prefs-hint{font-size:.76rem;padding:6px 12px;flex-wrap:wrap;max-width:100%;text-align:left;justify-content:flex-start}
}

/* ═══ Ideas mode-badge (Live / Cached / ✨ Personalized) ════════════ */
.rd-mode-badge{display:inline-flex;align-items:center;gap:4px;font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;padding:2px 8px;border-radius:40px;font-weight:500;margin-right:4px;transition:all .2s}
.rd-mode-cached{background:rgba(44,74,62,.08);color:#6b7075;border:1px solid rgba(44,74,62,.15)}
.rd-mode-live{background:rgba(90,140,122,.14);color:#3d6a58;border:1px solid rgba(90,140,122,.35)}
.rd-mode-live::before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;background:#3d6a58;animation:blink-dot 1.6s ease-in-out infinite}
.rd-mode-personalized{background:linear-gradient(135deg,rgba(200,169,110,.18),rgba(90,140,122,.14));color:#8A6B2B;border:1px solid rgba(200,169,110,.4)}
.rd-mode-personalized::before{content:"✦";font-size:.7rem;line-height:1}
#rdModeDetail{font-size:.78rem;color:var(--text-muted);margin-left:2px}
/* ✨ Personalized row — Verdeaux's "we curated this for you" mark.
 Recolored 2026-04-25: previous brown-gold-on-cream was muted against
 the gold-tinted card border; switched to high-contrast Verdeaux green
 with a clean white pill so the badge reads cleanly on phones too.
 The card border itself stays gold-toned to keep the warm "premium"
 vibe — just the badge text + match-reason callout switch to green. */
.reddit-card.is-personalized{border:1.5px solid rgba(200,169,110,.45);box-shadow:0 3px 14px rgba(200,169,110,.12)}
.reddit-card-match-reason{font-size:.78rem;color:var(--green);font-style:italic;line-height:1.5;margin-top:6px;padding:6px 10px;background:rgba(44,74,62,.05);border-left:2px solid var(--green);border-radius:0 6px 6px 0}

/* ═══ Responsive gaps identified in the Phase C sweep ════════════════ */
/* Tablet range (768–1279): Phase 5 Outreach + Phase 7 Compare need a
 comfortable intermediate layout, not desktop-wide and not mobile-stacked. */
@media (min-width:768px) and (max-width:1279px){
 .vx-outreach-grid{grid-template-columns:repeat(2,1fr)}
 /* 2026-05-04: removed `.vx-cmp-zones { grid-template-columns: repeat(2,1fr) }`
    + 3rd-zone-spans-full override. The upload row is now locked to the
    page-title canonical width (820px), so 3 equal columns fit cleanly at
    every desktop/tablet size; only mobile (<768px) stacks vertically. */
 .vx-cmp-flags-grid{grid-template-columns:repeat(2,1fr)}
 .vx-outreach-toolbar{gap:.75rem}
 .vx-outreach-draft-actions{gap:10px}
}
/* Foundation sub-grid (Budget step 1) — had no mobile override */
@media (max-width:767px){
 .foundation-sub-grid{grid-template-columns:repeat(2,1fr);gap:8px}
}
@media (max-width:480px){
 .foundation-sub-grid{grid-template-columns:1fr}
 /* The Phase 8 Account modal + Delete-my-data modal already use
 flex column + 100% width action buttons on narrow screens, but
 ensure the modal card itself doesn't exceed the viewport. */
 #vxAccountModal>div,#vxOutreachModal>div,.vdx-hide-modal-card{max-width:100%!important;padding:20px!important}
 #vxAccountModal input[type="text"]{font-size:16px} /* prevent iOS zoom */
 /* Stripe-style inputs readable on 360 */
 input[type="text"],input[type="email"],input[type="number"],input[type="date"],textarea{font-size:16px}
}
/* Touch-friendly tap targets across new Phase 4–8 surfaces */
@media (pointer:coarse){
 .vendor-lock-btn{min-height:32px;padding:6px 12px}
 .vx-outreach-card-checkbox{width:20px;height:20px}
 .vx-cmp-zone-choose{min-height:40px}
 .vx-outreach-draft-actions button,.vx-outreach-draft-actions a.vx-outreach-btn{min-height:44px}
 .vx-cmp-actions button{min-height:44px}
}

/* ═══ 2026-05-03 Hidden vendors modal ═════════════════════════════════
   Reachable from two surfaces: a category-scoped link in the Vendor IQ
   Personalize panel ("View 3 hidden vendors"), and the cross-category
   "Manage hidden vendors" button in Account Settings → Privacy. Restoring
   flips wedding_vendor_seeds.status from 'hidden' back to 'active' and
   nulls the hide_reason fields, so the next search picks the vendor up. */
.vx-hv-modal{position:fixed;inset:0;background:rgba(24,28,31,.55);backdrop-filter:blur(3px);z-index:10000;display:flex;align-items:center;justify-content:center;padding:20px;animation:vx-fade-in .18s ease-out}
.vx-hv-modal[hidden]{display:none}
.vx-hv-card{background:#fff;border-radius:14px;max-width:560px;width:100%;max-height:85vh;display:flex;flex-direction:column;box-shadow:0 20px 60px rgba(0,0,0,.25);overflow:hidden}
.vx-hv-head{display:flex;align-items:flex-start;gap:12px;padding:22px 26px 4px}
.vx-hv-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);margin:0 0 4px}
.vx-hv-title{font-family:'Cormorant Garamond',serif;font-size:1.35rem;color:var(--green);margin:0;font-weight:500;line-height:1.2}
.vx-hv-close{margin-left:auto;background:transparent;border:0;color:var(--text-muted);font-size:1.4rem;line-height:1;cursor:pointer;padding:2px 8px;border-radius:4px;flex-shrink:0}
.vx-hv-close:hover{background:rgba(44,74,62,.06);color:var(--ink)}
.vx-hv-help{font-size:.84rem;color:var(--text-mid);line-height:1.55;margin:8px 26px 14px;padding:0}
.vx-hv-body{flex:1;overflow-y:auto;padding:0 14px 18px}
.vx-hv-loading,.vx-hv-empty{padding:32px 12px;text-align:center;font-size:.86rem;color:var(--text-muted);font-style:italic}
.vx-hv-group{margin:8px 0 16px}
.vx-hv-group-label{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted);padding:6px 12px 4px;border-bottom:1px solid rgba(200,169,110,.15);margin-bottom:4px}
.vx-hv-row{display:flex;align-items:flex-start;gap:12px;padding:11px 12px;border:1px solid transparent;border-radius:8px;transition:background .15s}
.vx-hv-row:hover{background:rgba(250,247,242,.55);border-color:rgba(200,169,110,.18)}
.vx-hv-row-body{flex:1;min-width:0}
.vx-hv-row-name{font-family:var(--ff-b);font-size:.92rem;font-weight:500;color:var(--ink);line-height:1.3;margin:0 0 3px;overflow:hidden;text-overflow:ellipsis}
.vx-hv-row-meta{font-family:var(--ff-m);font-size:.66rem;letter-spacing:.05em;color:var(--text-muted);text-transform:uppercase;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.vx-hv-row-reason{display:inline-block;padding:1px 8px;border-radius:100px;background:rgba(200,169,110,.12);color:var(--gold-deep);font-weight:500;letter-spacing:.04em;text-transform:none;font-size:.7rem}
.vx-hv-restore{flex-shrink:0;padding:6px 12px;border:1px solid rgba(44,74,62,.22);background:#fff;color:var(--green);border-radius:6px;font-family:var(--ff-b);font-size:.74rem;font-weight:500;cursor:pointer;transition:all .15s}
.vx-hv-restore:hover{background:var(--green);color:#fff;border-color:var(--green)}
.vx-hv-restore:disabled{opacity:.5;cursor:not-allowed}
.vx-hv-restore.is-restored{background:rgba(90,140,122,.1);color:var(--green-mid);border-color:rgba(90,140,122,.25)}

/* Per-category footer link in the Personalize panel */
.vx-cmp-pers-hidden-link{margin-top:14px;padding-top:12px;border-top:1px dashed rgba(200,169,110,.25);font-size:.78rem;color:var(--text-mid);text-align:center}
.vx-cmp-pers-hidden-link button{background:transparent;border:0;color:var(--gold-deep);font-family:var(--ff-b);font-size:.78rem;cursor:pointer;padding:4px 8px;border-radius:4px;text-decoration:underline;text-decoration-color:rgba(200,169,110,.4);text-underline-offset:3px}
.vx-cmp-pers-hidden-link button:hover{color:var(--green);text-decoration-color:var(--green)}
.vx-cmp-pers-hidden-link button:disabled{opacity:.55;cursor:default;text-decoration:none}

@media (max-width:480px){
 .vx-hv-card{max-height:92vh}
 .vx-hv-head{padding:18px 18px 2px}
 .vx-hv-help{margin:8px 18px 12px}
 .vx-hv-body{padding:0 8px 14px}
 .vx-hv-row{flex-wrap:wrap}
 .vx-hv-restore{margin-left:auto}
}

/* ═══ 2026-05-03 Slice 2 Switch-assessment modal ═════════════════════
   Four-card layout: Gain / Owe / Timing / Verdict. Each card has a tiny
   eyebrow label + body. Editorial restraint design language — Cormorant
   Garamond display heading, DM Sans body, generous whitespace. Loading
   state has a slow-pulse spinner since Opus typically takes 6-12s. */
.vx-sa-modal{position:fixed;inset:0;background:rgba(24,28,31,.6);backdrop-filter:blur(3px);z-index:10001;display:flex;align-items:center;justify-content:center;padding:20px;animation:vx-fade-in .18s ease-out}
.vx-sa-modal[hidden]{display:none}
.vx-sa-card{background:#fff;border-radius:14px;max-width:680px;width:100%;max-height:88vh;display:flex;flex-direction:column;box-shadow:0 20px 60px rgba(0,0,0,.28);overflow:hidden}
.vx-sa-head{display:flex;align-items:flex-start;gap:12px;padding:24px 28px 6px}
.vx-sa-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);margin:0 0 4px}
.vx-sa-title{font-family:'Cormorant Garamond',serif;font-size:1.55rem;color:var(--green);margin:0;font-weight:500;line-height:1.2;letter-spacing:.005em}
.vx-sa-title em{color:var(--gold);font-style:italic}
.vx-sa-close{margin-left:auto;background:transparent;border:0;color:var(--text-muted);font-size:1.5rem;line-height:1;cursor:pointer;padding:2px 8px;border-radius:4px;flex-shrink:0}
.vx-sa-close:hover{background:rgba(44,74,62,.06);color:var(--ink)}
.vx-sa-meta{padding:0 28px 14px;display:flex;flex-wrap:wrap;gap:18px;font-size:.78rem;color:var(--text-mid);line-height:1.5;border-bottom:1px solid rgba(200,169,110,.18)}
.vx-sa-meta-item{display:flex;flex-direction:column;gap:1px;min-width:0}
.vx-sa-meta-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted)}
.vx-sa-meta-value{font-family:var(--ff-b);font-size:.86rem;font-weight:500;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vx-sa-meta-arrow{align-self:center;color:var(--gold-deep);font-size:1rem;line-height:1;padding:0 4px}
.vx-sa-body{flex:1;overflow-y:auto;padding:18px 28px 6px;display:flex;flex-direction:column;gap:16px}
.vx-sa-part{padding:16px 18px;border:1px solid rgba(200,169,110,.22);border-radius:10px;background:rgba(250,247,242,.45)}
.vx-sa-part[data-part="gain"]    {border-left:3px solid #5a8c7a}
.vx-sa-part[data-part="owe"]     {border-left:3px solid #C8A96E}
.vx-sa-part[data-part="timing"]  {border-left:3px solid #8a7ea2}
.vx-sa-part[data-part="verdict"] {border-left:3px solid var(--green);background:rgba(44,74,62,.04)}
.vx-sa-part-eyebrow{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;color:var(--text-muted);margin:0 0 4px;display:flex;align-items:center;gap:8px}
.vx-sa-part-eyebrow strong{color:var(--green);font-weight:500;letter-spacing:.18em}
.vx-sa-part-eyebrow .vx-sa-part-num{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;background:var(--green);color:#fff;font-family:var(--ff-d);font-size:.7rem;font-style:italic;font-weight:500}
.vx-sa-part-body{font-family:var(--ff-b);font-size:.93rem;line-height:1.65;color:var(--ink);margin:0;white-space:pre-wrap}
.vx-sa-loading{padding:40px 20px;display:flex;flex-direction:column;align-items:center;gap:14px}
.vx-sa-loading-spinner{width:32px;height:32px;border:2px solid rgba(200,169,110,.2);border-top-color:var(--green);border-radius:50%;animation:vx-sa-spin 1s linear infinite}
@keyframes vx-sa-spin{to{transform:rotate(360deg)}}
.vx-sa-loading-text{font-family:'Cormorant Garamond',serif;font-style:italic;color:var(--text-mid);font-size:1rem;text-align:center;line-height:1.45;margin:0;max-width:380px}
.vx-sa-error{padding:18px;background:rgba(178,90,90,.06);border:1px solid rgba(178,90,90,.22);border-radius:10px;color:#a25050;font-size:.88rem;line-height:1.5}
.vx-sa-error-retry{margin-top:10px;padding:6px 14px;border:1px solid #a25050;background:#fff;color:#a25050;border-radius:6px;font-family:var(--ff-b);font-size:.78rem;cursor:pointer}
.vx-sa-error-retry:hover{background:#a25050;color:#fff}
.vx-sa-foot{display:flex;align-items:center;gap:14px;padding:14px 28px 18px;border-top:1px solid rgba(200,169,110,.18);background:rgba(250,247,242,.4)}
.vx-sa-foot-note{flex:1;font-family:var(--ff-m);font-size:.66rem;letter-spacing:.06em;color:var(--text-muted);line-height:1.4}
.vx-sa-done{padding:9px 22px;border:1px solid var(--green);background:var(--green);color:#fff;border-radius:40px;font-family:var(--ff-b);font-size:.82rem;font-weight:500;cursor:pointer;transition:all .15s}
.vx-sa-done:hover{background:var(--green-deep);border-color:var(--green-deep)}

@media (max-width:480px){
 .vx-sa-card{max-height:94vh}
 .vx-sa-head{padding:18px 18px 4px}
 .vx-sa-meta{padding:0 18px 12px;gap:12px}
 .vx-sa-body{padding:14px 18px 4px}
 .vx-sa-foot{padding:12px 18px 14px;flex-wrap:wrap}
 .vx-sa-meta-arrow{display:none}
}

/* ═══ Phase 5 — couples / bridal-party UI ═══════════════════════════ */

/* Onboarding choice modal (start new vs join existing) */
#vx-onboard-choice{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(28,28,28,.55);backdrop-filter:blur(4px);z-index:9998;padding:20px}
#vx-onboard-choice .vx-onb-card{background:var(--white);border-radius:var(--radius-lg);max-width:420px;width:100%;padding:32px 30px;box-shadow:0 12px 40px rgba(28,28,28,.18);text-align:center}
#vx-onboard-choice h2{font-family:var(--ff-d);font-size:1.6rem;color:var(--green);margin:0 0 .5rem;font-weight:500}
#vx-onboard-choice h2 em{color:var(--gold);font-style:italic}
#vx-onboard-choice p{font-size:.9rem;color:var(--text-mid);margin:0 0 1.5rem;line-height:1.5}
.vx-onb-btn{display:block;width:100%;padding:14px 18px;border:1px solid var(--border-g);border-radius:12px;background:var(--white);font-family:var(--ff-b);font-size:.95rem;color:var(--green);cursor:pointer;transition:all .15s;margin-bottom:10px;text-align:left}
.vx-onb-btn:hover{background:var(--green-pale);border-color:var(--green);transform:translateY(-1px)}
.vx-onb-btn-primary{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-onb-btn-primary:hover{background:var(--green-deep);color:var(--white)}
.vx-onb-btn-icon{font-family:var(--ff-d);font-size:1.4rem;color:var(--gold);margin-right:.5rem;font-style:italic}
#vxOnbCodeForm{display:none;flex-direction:column;gap:8px;margin-top:.75rem;text-align:left}
#vxOnbCodeForm input{padding:10px 14px;border:1.5px solid var(--border-g);border-radius:8px;font-family:var(--ff-m);font-size:1rem;letter-spacing:.15em;text-transform:uppercase;background:var(--cream);color:var(--charcoal)}
#vxOnbCodeForm input:focus{outline:none;border-color:var(--green);background:var(--white)}
#vxOnbCodeForm button{padding:10px;border-radius:8px;border:none;background:var(--green);color:var(--white);font-family:var(--ff-b);font-size:.9rem;cursor:pointer}
#vxOnbErr{display:none;font-size:.8rem;color:var(--rose);background:var(--rose-pale);padding:8px 12px;border-radius:8px;margin-bottom:.75rem}

/* Invite-partner card (in Account Settings) */
.vx-invite-card{background:linear-gradient(135deg,var(--gold-pale) 0%,var(--cream) 100%);border:1px solid var(--gold-light);border-radius:var(--radius-lg);padding:20px 24px;margin:18px 0}
.vx-invite-card h4{font-family:var(--ff-d);font-size:1.15rem;color:var(--green);margin:0 0 6px;font-weight:500}
.vx-invite-card h4 em{font-style:italic;color:var(--gold)}
.vx-invite-card p{font-size:.85rem;color:var(--text-mid);margin:0 0 14px;line-height:1.55}
.vx-invite-row{display:flex;gap:8px;align-items:center}
.vx-invite-code{flex:1;padding:11px 14px;background:var(--white);border:1.5px solid var(--gold-light);border-radius:8px;font-family:var(--ff-m);font-size:1.1rem;letter-spacing:.2em;text-align:center;color:var(--green);font-weight:500}
.vx-invite-copy,.vx-invite-share{padding:11px 14px;border:1px solid var(--border-g);border-radius:8px;background:var(--white);color:var(--green);font-family:var(--ff-b);font-size:.8rem;cursor:pointer;transition:all .15s;white-space:nowrap}
.vx-invite-copy:hover,.vx-invite-share:hover{background:var(--green-pale);border-color:var(--green)}
.vx-invite-members{margin-top:12px;font-size:.78rem;color:var(--text-muted);font-family:var(--ff-m);letter-spacing:.04em}
.vx-invite-members strong{color:var(--green);font-weight:500}
.vx-invite-member-list{list-style:none;padding:0;margin:6px 0 0;display:flex;flex-direction:column;gap:4px}
.vx-invite-member-list li{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--border-g)}
.vx-invite-member-list li:last-child{border-bottom:none}
.vx-invite-member-list li>span:first-child{flex:1;color:var(--ink);font-family:var(--ff-b);font-size:.82rem}
.vx-invite-remove-btn{font-family:var(--ff-b);font-size:.72rem;padding:3px 9px;border:1px solid var(--border-g);border-radius:6px;background:transparent;color:var(--danger,#b94040);cursor:pointer;white-space:nowrap;transition:all .15s}
.vx-invite-remove-btn:hover{background:rgba(185,64,64,.07);border-color:var(--danger,#b94040)}
.vx-invite-role-row{margin-top:8px}
.vx-role-chips{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 8px}
.vx-role-chip{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.75rem;font-weight:500;color:var(--text-mid);background:rgba(44,74,62,.04);border:1px solid rgba(44,74,62,.18);border-radius:20px;padding:4px 12px;cursor:pointer;transition:all .15s;white-space:nowrap;line-height:1.5}
.vx-role-chip:hover{border-color:var(--green);color:var(--green);background:rgba(44,74,62,.07)}
.vx-role-chip.is-selected{background:var(--green);color:var(--white,#fff);border-color:var(--green)}
.vx-invite-role-input{width:100%;padding:8px 12px;border:1px solid var(--border-g);border-radius:8px;font-family:var(--ff-b);font-size:.84rem;color:var(--ink);background:var(--white)}

/* ── Scoped permissions by role ── */
/* Non-creator: hide member management controls */
body:not(.vx-role-creator) .vx-invite-remove-btn{display:none}
body:not(.vx-role-creator) #vxInviteCreatorTools{display:none!important}
/* helper + viewer cannot invite others — role chips and code row are blocked */
body.vx-role-helper .vx-invite-role-row,body.vx-role-viewer .vx-invite-role-row{display:none}
/* partner / member / coordinator keep full invite UI (role chips + share buttons) */
body.vx-role-helper .vx-invite-code-row,body.vx-role-viewer .vx-invite-code-row{opacity:.45;pointer-events:none}
/* Viewer: all form save buttons disabled, inputs read-only */
body.vx-role-viewer .vx-acc-save-btn{opacity:.4;pointer-events:none}
body.vx-role-viewer input:not([type=button]):not([type=submit]),body.vx-role-viewer textarea,body.vx-role-viewer select{pointer-events:none;background:rgba(44,74,62,.03)}
/* Budget: member/helper can view but not edit allocations */
body.vx-role-member #section-budget input[type=range],body.vx-role-helper #section-budget input[type=range]{pointer-events:none;opacity:.6}
body.vx-role-member #section-budget button.generate-btn,body.vx-role-helper #section-budget button.generate-btn,body.vx-role-member #section-budget .budget-save,body.vx-role-helper #section-budget .budget-save{opacity:.4;pointer-events:none}
/* Read-only banner shown for viewer/helper roles */
.vx-role-notice{display:none;align-items:center;gap:8px;background:rgba(200,169,110,.1);border:1px solid rgba(200,169,110,.3);border-radius:8px;padding:8px 14px;margin:0 2rem 1rem;font-family:var(--ff-b);font-size:.8rem;color:var(--text-mid)}
body.vx-role-viewer .vx-role-notice,body.vx-role-helper .vx-role-notice{display:flex}

/* Last-edited badge under each saved section */
.vx-edited-badge{font-size:.72rem;color:var(--text-muted);margin-top:.4rem;font-style:italic;font-family:var(--ff-b)}
.vx-edited-badge strong{color:var(--green-mid);font-weight:500;font-style:normal}

/* ═══ Budget divergence banner (Phase 3d) ══════════════════════════════
   Slides down from the top whenever a vendor lock or interview pricing
   answer pushes a category's floor materially. Gold accent for non-
   urgent (floor moved but still under target); rose accent for urgent
   (floor now exceeds target). Auto-dismisses after 9s; user can
   dismiss with × or click "Review Budget" to navigate to step 1. */
.vx-div-banner{position:fixed;top:18px;left:50%;transform:translateX(-50%);z-index:9500;display:flex;align-items:center;gap:14px;background:var(--white,#fff);border:1px solid rgba(200,169,110,.5);border-left:4px solid var(--gold,#C8A96E);border-radius:14px;box-shadow:0 12px 36px rgba(28,28,28,.18),0 2px 8px rgba(28,28,28,.06);padding:16px 16px 16px 20px;min-width:380px;max-width:min(640px,94vw);font-family:var(--ff-b,'DM Sans',sans-serif);animation:vx-div-slide-in .35s cubic-bezier(.22,.61,.36,1)}
.vx-div-banner.is-over{border:1px solid rgba(201,123,106,.5);border-left:4px solid var(--rose,#C97B6A)}
.vx-div-banner.is-leaving{animation:vx-div-slide-out .32s cubic-bezier(.55,.06,.68,.19) forwards}
.vx-div-banner-icon{flex-shrink:0;width:36px;height:36px;border-radius:50%;background:rgba(200,169,110,.15);color:var(--gold-deep,#A07840);display:flex;align-items:center;justify-content:center;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-size:1.1rem;font-style:italic;font-weight:500}
.vx-div-banner.is-over .vx-div-banner-icon{background:rgba(201,123,106,.14);color:var(--rose,#C97B6A)}
.vx-div-banner-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.vx-div-banner-headline{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-size:1.05rem;font-weight:500;color:var(--charcoal,#1C1C1C);line-height:1.3}
.vx-div-banner.is-over .vx-div-banner-headline{color:var(--rose,#C97B6A)}
.vx-div-banner-sub{font-size:.74rem;color:var(--text-muted,#88928d);line-height:1.4;font-family:var(--ff-m,'DM Mono',monospace);letter-spacing:.01em}
.vx-div-banner-cta{flex-shrink:0;appearance:none;background:var(--green,#2C4A3E);color:var(--white,#fff);border:none;border-radius:24px;padding:8px 16px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;letter-spacing:.02em;cursor:pointer;transition:background .15s ease,transform .12s ease}
.vx-div-banner-cta:hover{background:var(--green-mid,#3a6b59);transform:translateY(-1px)}
.vx-div-banner-cta:active{transform:translateY(0)}
.vx-div-banner-close{flex-shrink:0;appearance:none;background:none;border:none;width:24px;height:24px;font-size:1.2rem;color:var(--text-muted,#88928d);cursor:pointer;line-height:1;padding:0;margin-left:-4px;transition:color .12s ease}
.vx-div-banner-close:hover{color:var(--charcoal,#1C1C1C)}
@keyframes vx-div-slide-in{from{opacity:0;transform:translate(-50%,-30px)}to{opacity:1;transform:translate(-50%,0)}}
@keyframes vx-div-slide-out{from{opacity:1;transform:translate(-50%,0)}to{opacity:0;transform:translate(-50%,-30px)}}
@media (max-width:560px){
  .vx-div-banner{top:12px;min-width:0;width:calc(100vw - 24px);padding:14px 12px 14px 16px;flex-wrap:wrap;gap:10px}
  .vx-div-banner-cta{order:3;width:100%}
  .vx-div-banner-close{order:2}
}

/* ═══ Hydrate overlay — premium post-sign-in loading state ═════════════
   Distinct from #verdeaux-auth-overlay (which is the email-entry modal).
   Appears the moment the magic link resolves, dismisses when wedding
   data + community intel are ready (or after a 1.6s ceiling). The bar
   fill advances at hydrate milestones — Loading → Reading profile →
   Loading budget & vendors → Pulling community intel → Ready. */
/* 2026-05-01 Slice 5.7 polish: overlay background bumped to 100% opacity
   so the page underneath (post-navigation Chat / Budget / etc.) and any
   corner toasts (Supabase realtime confirms, _toast notifications, etc.)
   stay completely hidden until the overlay actively fades out. The blur
   is kept for premium feel but no longer needs to mask see-through. */

/* 2026-05-15 (REVERTED same day) — Top sync banner removed. Tried a
   thin top banner instead of the full-screen overlay for returning
   users with cached chrome, but the banner created a false-affordance
   bug: the underlying UI looked interactive (wallpaper + tiles + name
   all painted from cache) so users tapped icons and got nothing —
   the actual data wasn't loaded yet. Full-screen overlay blocks input
   during the wait, which is the correct behavior. Cache work itself
   is preserved (instant wallpaper paint after overlay dismisses,
   no pre-auth signedUrl noise) — only the banner UX is reverted. */

/* Skeleton states — Insights priorities + other landing cards.
   Premium shimmer matches the existing .reddit-card-skel ideas-shimmer
   keyframe so the whole landing page reads as one coherent loading state. */
.mh-pri-skel{display:flex;flex-direction:column;gap:8px;padding:4px 0}
.mh-pri-skel-row{height:46px;border-radius:10px;background:linear-gradient(90deg, var(--cream-d, #F0EBE1) 0%, rgba(255,255,255,0.6) 50%, var(--cream-d, #F0EBE1) 100%);background-size:200% 100%;animation:ideas-shimmer 1.6s ease-in-out infinite}

/* ═══ Phase 3a Budget v2 — xlsx-driven items rebuild ═══════════════════
   Replaces the hand-rolled .calc-section blocks. One section per
   Verdeaux category with: title row + slider (target spend) + per-item
   rows (checkbox + name + microcopy + inline-editable amount). */
.vxb-root{display:flex;flex-direction:column;gap:18px;margin-bottom:20px}
.vxb-section{background:var(--white,#fff);border:1px solid var(--border,#eae5dd);border-radius:var(--radius-lg,16px);padding:22px 26px;box-shadow:0 2px 16px rgba(44,74,62,.04);scroll-margin-top:88px}
.vxb-section-head{display:flex;flex-direction:column;gap:12px;padding-bottom:14px;border-bottom:1px solid var(--border,#eae5dd);margin-bottom:8px;cursor:pointer;transition:border-color .18s ease;user-select:none;text-align:left;background:transparent;border-top:none;border-left:none;border-right:none;font:inherit;color:inherit;width:100%;padding-top:0;padding-left:0;padding-right:0}
.vxb-section-head:hover{border-bottom-color:rgba(44,74,62,.25)}
.vxb-section-head:focus-visible{outline:2px solid var(--green,#2C4A3E);outline-offset:4px;border-radius:4px}
/* Collapsed-by-default: hide the items list + drop the head's bottom
   border so the section reads as a single row. Expand reveals items
   with a smooth 220ms slide. */
.vxb-section:not(.is-expanded) .vxb-items{max-height:0;overflow:hidden;opacity:0;pointer-events:none;margin:0;padding:0}
.vxb-section.is-expanded .vxb-items{max-height:none;opacity:1;animation:vxb-expand-in .22s ease-out}
.vxb-section:not(.is-expanded) .vxb-section-head{border-bottom:none;margin-bottom:0;padding-bottom:0}
@keyframes vxb-expand-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
/* Chevron rotates 90° when expanded — pure CSS, no extra DOM */
/* 2026-05-01 Slice 5.7 polish: bigger, more obvious chevron — was a thin
   1.4rem character that read as decoration. Now a 32px circular target
   with a darker fill so the affordance is unmistakable. */
/* Chevron sized to match the locked-badge content height (~26px) so the
   planned row's visual heft matches a locked row of the same width. */
.vxb-chevron{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.6rem;color:var(--green,#2C4A3E);background:rgba(44,74,62,.06);border-radius:50%;font-style:italic;transition:transform .22s cubic-bezier(.22,.61,.36,1),background .15s;margin-left:6px;flex-shrink:0;line-height:1}
.vxb-section-head:hover .vxb-chevron{background:rgba(44,74,62,.12)}
.vxb-section.is-expanded .vxb-chevron{transform:rotate(90deg);color:var(--gold,#C8A96E);background:rgba(200,169,110,.12)}
/* 2026-06-04 — a locked row expands via its header chevron (retired the
   separate "Details" button). Re-show the chevron that .is-locked hides, make
   the header read clickable, and rotate the chevron when the line-by-line
   panel is open (mirrors the .is-expanded rotation on unlocked rows). */
.vxb-section.is-cat-locked .vxc-lock-chevron{display:inline-flex}
.vxb-section.is-cat-locked .vxb-locked-head{cursor:pointer}
.vxb-section.is-cat-locked .vxb-locked-head:hover .vxc-lock-chevron{background:rgba(44,74,62,.12)}
.vxb-section.is-det-open .vxc-lock-chevron{transform:rotate(90deg);color:var(--gold,#C8A96E);background:rgba(200,169,110,.12)}
/* "5 of 18 selected" item-count summary chip */
.vxb-item-count{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted,#88928d);font-style:italic;padding:2px 9px;background:rgba(44,74,62,.04);border-radius:100px;border:1px solid rgba(44,74,62,.06)}
.vxb-section[data-state="planned"] .vxb-item-count{color:var(--green-mid,#3a6b59);background:var(--green-pale,#EAF0ED);border-color:rgba(58,107,89,.15)}
.vxb-section[data-state="skipped"] .vxb-item-count{color:var(--text-muted,#88928d);background:var(--cream-warm,#F0EBE1)}
.vxb-section[data-state="partial"] .vxb-item-count{color:var(--gold-deep,#A07840);background:var(--gold-pale,#F4ECD8);border-color:rgba(200,169,110,.25)}
/* "Your budget" foundation section — reuses the .vxb-section pattern
   so the page reads as one coherent list. Body collapses with the same
   220ms slide as line-item lists. Default-expanded on first paint. */
.vxb-section-foundation{margin-bottom:18px}
.vxb-section-foundation .vxb-section-title em{font-style:italic;color:var(--gold,#C8A96E);font-weight:400}
.vxb-foundation-summary{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted,#88928d);font-style:italic;padding:2px 9px;background:rgba(44,74,62,.04);border-radius:100px;border:1px solid rgba(44,74,62,.06)}
.vxb-section-foundation:not(.is-expanded) .vxb-foundation-body{max-height:0;overflow:hidden;opacity:0;pointer-events:none;margin:0;padding:0}
.vxb-section-foundation.is-expanded .vxb-foundation-body{max-height:none;opacity:1;animation:vxb-expand-in .22s ease-out;padding-top:8px}
.vxb-section-foundation:not(.is-expanded) .vxb-section-head{border-bottom:none;margin-bottom:0;padding-bottom:0}
.vxb-section-foundation .vxb-foundation-body .guest-row{margin-top:14px}
.vxb-section-title-row{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px}
.vxb-section-title{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-cat-title,.9rem);font-weight:600;color:var(--money-ink,#33352f);margin:0}
/* 2026-06-02 (Stephen) — nested line-item sub-group ("Miscellaneous Items
   (uncommon catering)" inside Venue & Catering). NOT a card — integrated into
   the section: just a top divider. The header reuses the section's exact
   chrome classes (.vxb-section-meta / .vxb-amount / .vxb-amount-tag /
   .vxb-bulk-toggle / .vxb-reset-medians) so the title font, state pill,
   Skip-all + reset buttons are pixel-identical to a real category header. The
   chevron badge matches .vxb-chevron and rotates + turns gold on open. The
   line items inside render identically to the section's other rows. */
.vxb-subgroup{margin:0;border-top:1px solid var(--border,#eae5dd)}
.vxb-subgroup-head{display:flex;align-items:center;gap:9px;padding:16px 0 14px;cursor:pointer;user-select:none;background:transparent;border:none;width:100%;text-align:left;font:inherit;color:inherit;flex-wrap:wrap}
/* Match the planned-section title exactly (DM Sans / charcoal / 0.9rem). */
.vxb-subgroup-title{font-family:var(--ff-b,'DM Sans',sans-serif);color:var(--charcoal,#2C2C2C);font-size:0.9rem;font-weight:400;line-height:1.2;margin:0;align-self:center}
/* Match .vxb-chevron sizing so the affordance reads identically. */
.vxb-subchevron{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.6rem;font-style:italic;color:var(--green,#2C4A3E);background:rgba(44,74,62,.06);border-radius:50%;transition:transform .22s cubic-bezier(.22,.61,.36,1),background .15s,color .15s;flex-shrink:0;line-height:1}
.vxb-subgroup-head:hover .vxb-subchevron{background:rgba(44,74,62,.12)}
/* ⚑ A SUBGROUP ROW READS AS A LINE ITEM, BECAUSE THAT IS WHAT IT IS. Stephen:
   "Other stationary is still broken." Removing its orphaned ✦ Lock stopped the
   overlap but left two differences from the items directly above it:

     · its chevron is a 26px CIRCLE with a tinted background and the green
       display face, where `.vxb-item-expand` is the same box with a transparent
       background, the muted colour and 1.35rem — so this one row shouted;
     · its meta is a category-header construct with no auto margin and the head
       has no right padding, so `$0` stopped ~146px short of the column every
       amount above it lands in.

   Both matched to `.vxb-item` / `.vxb-item-expand` rather than to numbers picked
   here, so the row moves with the items it sits among. */
#section-budget .vxb-subchevron{background:transparent;color:var(--text-muted,#88928d);
  /* 1.15rem / 22px, matching `#section-budget .vxb-item-name-row .vxb-item-expand`
     — the MORE SPECIFIC of the two item-chevron rules, and therefore the one
     that actually renders beside this row. Measured: items 18.4px. */
  font-size:1.15rem;width:22px;height:22px}
#section-budget .vxb-subgroup-head:hover .vxb-subchevron{background:transparent;
  color:var(--green,#2C4A3E)}
#section-budget .vxb-subgroup.is-expanded .vxb-subchevron{background:transparent}
/* ⚑ SPECIFICITY, MEASURED — and the note 600 lines below called this exact
   trap: "Three layers govern this head." A subgroup lives INSIDE
   `.vxb-section.is-planned`, so

     #section-budget .vxb-section.is-planned .vxb-section-meta{order:5;margin-left:0}

   written for the CATEGORY head, reaches the SUBGROUP head's meta as a
   descendant. That is (1,3,0). An obvious `#section-budget .vxb-subgroup-head
   .vxb-section-meta` is only (1,2,0) and loses — silently, with the amount
   stranded at x=297 against the items' 377.

   ⚑ HOW IT WAS FOUND, because reading the file did not do it: a plain ID rule
   injected at runtime moved nothing, the same rule with !important moved it to
   377. That gap is a specificity loss, never a typo — and it named the layer to
   look in. Matching the section class takes this to (1,4,0), which beats the
   rule on merit rather than shouting !important over it. */
#section-budget .vxb-section.is-planned .vxb-subgroup-head .vxb-section-meta{
  margin-left:auto;width:auto;justify-content:flex-end}
.vxb-subgroup.is-expanded .vxb-subchevron{transform:rotate(90deg);color:var(--gold,#C8A96E);background:rgba(200,169,110,.12)}
/* State-pill colours keyed to the SUB-GROUP's own data-state, overriding the
   parent .vxb-section[data-state] rules (these come later → win on ties). */
.vxb-subgroup[data-state="planned"] .vxb-amount-tag{color:var(--green-mid,#3a6b59);background:var(--green-pale,#EAF0ED)}
.vxb-subgroup[data-state="skipped"] .vxb-amount-tag{color:var(--text-muted,#88928d);background:var(--cream-warm,#F0EBE1)}
.vxb-subgroup[data-state="partial"] .vxb-amount-tag{color:var(--gold-deep,#A07840);background:var(--gold-pale,#F4ECD8)}
/* Disabled Lock — present for visual symmetry with section headers, but these
   items lock with the caterer (Venue & Catering contract), so it's greyed +
   inert. cursor:not-allowed signals disabled while keeping the title tooltip. */
.vxb-subgroup-items{display:none}
.vxb-subgroup.is-expanded .vxb-subgroup-items{display:block}
.vxb-section-totals{display:flex;align-items:center;gap:8px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;letter-spacing:.04em;color:var(--text-mid,#4A4A4A);flex-wrap:wrap}
/* Bulk-toggle button — premium skip/include all action per section.
   Label flips between "Skip all" and "Include all" based on current
   state. Visual treatment: subtle ghost button that lifts on hover. */
/* 2026-04-30: hide bulk toggle, item count, and SKIPPED/PARTIAL pills
   on Budget — Scouting is now the surface for category planned/skipped
   decisions. Skipped categories on Budget appear dimmed so couples
   know data is still there, just not active. */
/* 2026-05-01 Slice 5.7 polish: per-category Skip pill restored.
   Previously hidden; promoted as a visible affordance so couples can
   skip a category they're not doing without unchecking 18 line items.
   Toggle propagates through VerdeauxBudget.bulkToggleCategory →
   getCategoryState → Scouting tile filter (verdeaux-local.html:6389). */
.vxb-bulk-toggle{display:inline-flex;align-items:center;gap:4px;background:transparent;border:1px solid var(--border-g,#cdc5b6);color:var(--text-muted,#88928d);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.9rem;letter-spacing:normal;text-transform:none;padding:4px 12px;border-radius:100px;cursor:pointer;transition:all .15s ease;font-weight:400}
.vxb-bulk-toggle:hover{background:var(--cream-warm,#F0EBE1);border-color:rgba(44,74,62,.25);color:var(--charcoal,#2C2C2C)}
/* 2026-05-26 — Reset to Wedding Report median. Same pill shape as
   the bulk-toggle so the section header reads as a cohesive control
   group, but with a subtle gold accent so it's distinguishable from
   the Skip-all toggle. Hidden on locked categories. */
.vxb-reset-medians{display:inline-flex;align-items:center;gap:4px;background:transparent;border:1px solid rgba(200,169,110,.32);color:var(--gold-deep,#A07840);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.9rem;letter-spacing:normal;text-transform:none;padding:4px 12px;border-radius:100px;cursor:pointer;transition:all .15s ease;font-weight:400}
.vxb-reset-medians:hover{background:rgba(200,169,110,.10);border-color:rgba(200,169,110,.55);color:var(--gold-deep,#A07840)}
.vxb-section.is-locked .vxb-reset-medians{display:none}
/* 2026-05-27 (Stephen): category-level reset now ICON-ONLY to save row
   chrome. Tooltip carries the meaning. Matches line-item ↺ language. */
.vxb-reset-medians-icon{
  width:28px;height:28px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:1rem;line-height:1;
  border-radius:50%;
}
/* 2026-05-27 (Stephen): per-line ↺ reset icon. Sits inside
   .vxb-item-amount next to the input. Since 2026-05-28 ("expose ↺ on
   every field") it renders whenever a benchmark median is computable
   or the line is unit-pinned — never on contract-locked lines (see
   _refreshItemRow in verdeaux-budget.js). 24x24 desktop,
   28x28 on mobile for the touch target. Terracotta accent so it
   reads as "undo my edit" against the gold category-level icon. */
.vxb-item-reset{
  width:24px;height:24px;padding:0;margin-right:8px;
  display:inline-flex;align-items:center;justify-content:center;
  background:transparent;
  border:1px solid rgba(200,146,58,.30);
  color:#C8923A;
  border-radius:50%;
  cursor:pointer;
  font-size:.85rem;line-height:1;
  transition:all .15s ease;
  flex-shrink:0;
}
.vxb-item-reset:hover{
  background:#FBF3E5;
  border-color:#C8923A;
  color:#8B6420;
}
.vxb-item-reset:active{ transform:scale(0.92); }
/* 2026-05-27 (Stephen "numbers stay visually in a column"): invisible
   spacer that occupies the same width as .vxb-item-reset when an item
   has no override. Keeps the $ prefix + input right-edge aligned
   across rows regardless of whether the ↺ icon is present. */
.vxb-item-reset-spacer{
  display:inline-block;
  width:24px;
  margin-right:8px;
  flex-shrink:0;
}
@media (max-width: 600px){
  .vxb-item-reset,.vxb-item-reset-spacer{width:28px;margin-right:10px;}
  .vxb-item-reset{font-size:.95rem;}
}
.vxb-section[data-state="skipped"] .vxb-bulk-toggle{color:var(--green-mid,#3a6b59);border-color:rgba(58,107,89,.3);background:var(--green-pale,#EAF0ED)}
.vxb-section.is-locked .vxb-bulk-toggle{display:none} /* locked categories aren't skippable */
.vxb-item-count{display:none}
.vxb-section[data-state="skipped"] .vxb-section-title{color:var(--text-muted,#88928d)}
.vxb-section[data-state="skipped"]{opacity:.55}
.vxb-section[data-state="skipped"]:hover{opacity:.85;transition:opacity .18s ease}
/* 2026-07-28 (Stephen) — dim BOOKED categories uniformly. A booked category is DONE, so it should
   recede (draw the eye to still-open decisions) regardless of its data-state. Before this, only
   booked categories that ALSO happened to be data-state="skipped" dimmed (the rule above); ones
   closed via a photo-contract review or manual entry stay data-state="partial" and read full-
   strength (e.g. Attire, Planner) — so the shading looked arbitrary. Key off the explicit is-booked
   status tag so EVERY booked category gets the same dimmed treatment as the skipped ones (opacity +
   muted title + hover reveal). The [data-state="skipped"] dim stays for genuine exclusions, so the
   signal reads "dim = resolved (booked or excluded), full = still an open decision". :has() is
   already relied on here (the empty-Chat collapse). */
#section-budget .vxb-section:has(.vxb-status-tag.is-booked) .vxb-section-title{color:var(--text-muted,#88928d)}
#section-budget .vxb-section:has(.vxb-status-tag.is-booked){opacity:.55}
#section-budget .vxb-section:has(.vxb-status-tag.is-booked):hover{opacity:.85;transition:opacity .18s ease}
/* 2026-05-26 — Keep skipped categories expandable. When the couple
   deselects every line item (e.g., turning each segmented control off
   to refine later), the category dims to $0/skipped but tapping the
   header should still reveal the line items so they can refine. The
   :not(.is-expanded) qualifier lets the expand override the hide. */
.vxb-section[data-state="skipped"]:not(.is-expanded) .vxb-items{display:none}
/* 2026-04-30 v3: keep the slider interactive on skipped tiles. The
   slider becoming a one-way trap was the root of "category locked"
   when all items are unchecked. Touching the slider now lifts the
   tile back to 'planned' (via getCategoryState reading the target). */
.vxb-section[data-state="skipped"] .vxb-slider-wrap{opacity:.55}
/* Highlight pulse when a skipped Interview tile click routes the couple
   here — gives a brief visual anchor so they know which section to act on. */
.vxb-section.vxb-section-flash{animation:vxb-flash 1.4s ease-out}
@keyframes vxb-flash{0%{box-shadow:0 0 0 0 rgba(200,169,110,.6),0 2px 16px rgba(44,74,62,.04);background:rgba(200,169,110,.06)}50%{box-shadow:0 0 0 4px rgba(200,169,110,.18),0 2px 16px rgba(44,74,62,.04);background:rgba(200,169,110,.03)}100%{box-shadow:0 2px 16px rgba(44,74,62,.04);background:transparent}}
.vxb-floor-label,.vxb-target-label{color:var(--text-muted,#88928d);font-style:italic;text-transform:uppercase;font-size:.55rem;letter-spacing:.1em}
.vxb-floor-val{color:var(--text-mid,#4A4A4A);font-weight:500;font-size:.85rem}
.vxb-target-val{color:var(--green,#2C4A3E);font-weight:600;font-size:.95rem}
.vxb-arrow{color:var(--border-g,#cdc5b6);font-size:.9rem}
.vxb-slider-wrap{display:flex;flex-direction:column;gap:6px}
/* 2026-04-29: explicit track styling. Without ::-webkit-slider-runnable-track,
   iOS Safari renders its native blue/green progress fill on top of our
   background — so even when value=0 the track looked half-filled. We drive
   the fill ourselves via --vxb-pct, set in JS on render + input. Also
   touch-action:manipulation lets horizontal slider drags win over the
   vertical scroll gesture on iOS instead of getting stuck at the start. */
.vxb-slider{width:100%;-webkit-appearance:none;appearance:none;height:18px;background:transparent;border-radius:100px;outline:none;cursor:pointer;padding:0;margin:0;touch-action:manipulation}
.vxb-slider::-webkit-slider-runnable-track{-webkit-appearance:none;appearance:none;height:6px;border-radius:100px;background:linear-gradient(to right,var(--green,#2C4A3E) 0,var(--green,#2C4A3E) var(--vxb-pct,0%),var(--cream-warm,#F0EBE1) var(--vxb-pct,0%),var(--cream-warm,#F0EBE1) 100%)}
.vxb-slider::-moz-range-track{height:6px;border-radius:100px;background:var(--cream-warm,#F0EBE1)}
.vxb-slider::-moz-range-progress{height:6px;border-radius:100px;background:var(--green,#2C4A3E)}
.vxb-slider::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:50%;background:var(--green,#2C4A3E);cursor:pointer;border:3px solid var(--white,#fff);box-shadow:0 2px 6px rgba(44,74,62,.2);margin-top:-6px}
.vxb-slider::-moz-range-thumb{width:18px;height:18px;border-radius:50%;background:var(--green,#2C4A3E);cursor:pointer;border:3px solid var(--white,#fff);box-shadow:0 2px 6px rgba(44,74,62,.2)}
.vxb-slider-warn{display:none;font-family:var(--ff-m,monospace);font-size:.68rem;letter-spacing:.04em;color:var(--rose,#C97B6A);background:rgba(185,64,64,.06);border:1px solid rgba(185,64,64,.2);border-radius:8px;padding:6px 10px;margin-top:2px}
.vxb-slider-warn.is-active{display:block}
/* Phase 3a polish — manual-only sections (catering_external,
   ceremonysite, hotel, marriagelicense). Lighter weight visually
   since they have no item rows to anchor the section. Hint line
   tells couples WHEN to use the section ("Only if your venue does
   NOT include food service"). */
.vxb-section-manual{padding-bottom:18px}
.vxb-section-manual .vxb-section-head{padding-bottom:0;border-bottom:none;margin-bottom:0}
.vxb-section-hint{font-family:var(--ff-b,sans-serif);font-size:.78rem;color:var(--text-muted,#88928d);font-style:italic;line-height:1.5;margin:-4px 0 8px}

/* Item rows */
.vxb-items{display:flex;flex-direction:column;margin-top:8px}

/* (2026-08-04 — the .vxb-package-* row styles and the .is-package-mode
   "indicative breakdown" treatment were REMOVED with the package-price input
   itself. A category is pinned by its LOCK, which renders the locked section
   shape and its own chrome; nothing emits these classes any more.) */

/* 2026-05-26 — Feature A: grid bumped from 36px → 168px first column to
   accommodate the new 3-tier segmented control (Must/Nice/Skip). Replaces
   the old binary checkbox. Item row keeps the same .is-selected opacity
   dim for skip-state visual cue. */
.vxb-item{display:grid;grid-template-columns:128px minmax(0,1fr) 130px;align-items:center;gap:14px;padding:11px 0;border-bottom:1px dashed var(--border,#eae5dd);transition:opacity .15s ease}
.vxb-item:last-child{border-bottom:none}
.vxb-item:not(.is-selected){opacity:.55}
/* 2026-08-07 — a line the couple asked for that the plan did NOT fund reads
   like the lines around it that are also not in the total, rather than like the
   funded ones. Stephen, on $4,440 in black above a $0 category: "it is
   misleading." The couple's choice is not discarded — it is still their
   priority and the engine still hears it — the row simply stops claiming a
   place in a total it does not have. The tooltip says which. */
.vxb-item.is-selected.is-unfunded{opacity:.55}
/* MATCH THE NEIGHBOURS, which are dimmed TWICE. An untouched row gets .55 on
   the row and another .62 on its name and amount — about .34 together. A line
   with an explicit priority is not .is-untouched, so it stopped at .55 and read
   as darker than the lines beside it that are equally not in the total.
   Stephen: "it is not black but it does not match Limo." Same two layers here,
   so an unfunded line sits at the same weight as every other line the category
   does not count. */
.vxb-item.is-selected.is-unfunded .vxb-item-name,
.vxb-item.is-selected.is-unfunded .vxb-item-amount{opacity:.62}
.vxb-item-check{display:flex;align-items:center;justify-content:flex-start;cursor:pointer}
/* 2026-05-26 — Feature A: 3-tier segmented priority control. Sits in the
   first column of each .vxb-item row. Three segments rendered as a
   pill group; active segment fills with the brand color matching its
   semantic (Must=gold, Nice=sage, Skip=muted). Hover lifts non-active
   segments to a hint background. */
.vxb-item-priority{display:inline-flex;border:1px solid rgba(44,74,62,.14);border-radius:100px;background:rgba(250,247,242,.6);padding:2px;overflow:hidden}
.vxb-pri-seg{display:inline-flex;align-items:center;gap:3px;border:0;background:transparent;color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.08em;text-transform:uppercase;padding:5px 9px;border-radius:100px;cursor:pointer;transition:background .15s ease,color .15s ease;font-weight:500}
.vxb-pri-seg:hover{background:rgba(44,74,62,.05);color:var(--green,#2C4A3E)}
.vxb-pri-seg .vxb-pri-icon{font-size:.7rem;line-height:1}
.vxb-pri-seg.vxb-pri-must.is-active{background:var(--gold,#C8A96E);color:#fff}
.vxb-pri-seg.vxb-pri-nice.is-active{background:var(--green-mid,#3a6b59);color:#fff}
.vxb-pri-seg.vxb-pri-skip.is-active{background:rgba(28,28,28,.32);color:#fff}
/* Untouched state — no segment active, row reads as "awaiting a decision"
   rather than "Skip by default". The whole row text dims so the eye moves
   past it to items the couple has already weighed in on. */
.vxb-item.is-untouched .vxb-item-name,
.vxb-item.is-untouched .vxb-item-amount{opacity:.62}
.vxb-item.is-untouched .vxb-item-priority{border-style:dashed;background:transparent}
/* 2026-05-27 (Stephen "Skip still shows MSRP"): Skip items still
   display their I value so couples see what they're declining, but
   read as "out of the deal" — strike through the amount and dim
   slightly. The visible price is the MSRP; the strike says "not
   in your total". Selector matches data-priority="skip" set by the
   item-row render via _itemPriority. */
.vxb-item[data-priority="skip"] .vxb-item-name{opacity:.55}
/* ⚑ 2026-09-03 — THE STRIKE CAME OFF, the grey stayed. Stephen: "any line item
   estimate that is not included should be gray not a line through the estimate."
   The comment above described the strike as saying "not in your total" — the
   colour says that on its own, and a struck number reads as a price we corrected
   rather than one the couple set aside. */
.vxb-item[data-priority="skip"] .vxb-amount-input{color:var(--text-muted,#7A7A7A);opacity:.7}
/* Mobile/narrow rows: collapse segment labels to icon-only so the row
   doesn't run off-screen. The icon + active-fill alone reads the state. */
@media (max-width: 560px){
  /* 2026-06-10 — these used to live in the 720px block; preserved here now that
     the tablet rule is range-scoped to 561–720. */
  .vxb-section{padding:18px 16px}
  /* 2026-07-04 — the phone .vxb-amount-input width lives in the ≤560 block AFTER
     the base .vxb-amount-input rule (~L8217). A width set HERE is dead: the base
     comes later in source order at equal specificity and wins even inside this
     media query (same trap as the 2026-06-10 pill-overlap bug below). */
  .vxb-section-totals{font-size:.62rem}
  /* 2026-06-10 (Stephen) — on phones strip each line to the ESSENTIALS:
     Tier pill · Skip · Title · Budget. The descriptor / strategy / override
     pills, the "% of couples" util line, and the ↺ revert + ⓘ info buttons
     are detail the DESKTOP carries; on mobile they overflowed the narrow
     amount column and collided with the title's pills. Editable ×N count
     chips stay (they're a functional budget lever, not decoration). */
  .vxb-item-name-row .vxb-pill,
  .vxb-item-name-row .vxb-strat,
  .vxb-item-name-row .vxb-ov-chip{display:none}
  .vxb-item-util{display:none}
  /* Scoped to .vxb-item-amount (two classes) so these beat their single-class
     base rules regardless of source order — .vxb-mc-info's base display is
     defined LATER in the file, so an unscoped .vxb-mc-info{display:none} lost
     the cascade and the ⓘ kept showing on mobile. */
  .vxb-item-amount .vxb-item-reset,
  .vxb-item-amount .vxb-item-reset-spacer,
  .vxb-item-amount .vxb-mc-info{display:none}
  /* band column is a single stacked pill (~58px); with ↺/ⓘ gone the amount
     column only carries $ + input, so it can tighten and the name gets the
     reclaimed width. */
  .vxb-item{grid-template-columns:58px minmax(0,1fr) 94px;gap:10px;align-items:start}
  .vxb-pri-seg .vxb-pri-lbl{display:none}
  .vxb-pri-seg{padding:5px 8px}
  /* 2026-06-27 (mobile fix #3) — the editable ×N count chip (.vxb-mc-inline)
     is nowrap + no-shrink, so on phones it overran the 94px amount column.
     Let the amount column wrap so the chip can drop to its own line under
     the $-input instead of overflowing; the chip itself wraps + spans full
     width, right-aligned. Mobile-only — desktop amount column unchanged. */
  .vxb-item-amount{flex-wrap:wrap;justify-content:flex-end;min-width:0}
  .vxb-mc-inline{margin-right:0;flex-basis:100%;justify-content:flex-end;white-space:normal}
  /* 2026-07-04 (per-line count chips, mobile) — drop the per-unit rate text on
     phones: "$32 each × [15] pieces" is ~150px wide and overflowed LEFT out of
     the 94px amount column, overprinting the item title (seen on the deploy-
     preview verification pass). "× [15] pieces" fits the column; the rate
     stays in the chip tooltip and reconciles as line $ ÷ count. */
  .vxb-mc-inline .vxb-mc-inline-rate{display:none}
  /* 2026-06-27 (mobile fix #5) — taller touch targets for the per-line band
     cycle + Skip pills (were ~26px tall); bump the band group gap so the two
     pills don't crowd at finger size. Mobile-only. */
}
/* 2026-06-09 (Stephen — price-band toggle replaces Must/Nice/Skip). One pill
   group of dollar-tier bands ($$ / $$$ / $$$$) + a Skip, in the row's first
   column. State: active band fills gold (in plan); a faint "on-ramp" $$ shows
   on a PARKED line (out, not skipped — "you'd start at Rising"); skipped dims
   the group and lights Skip. Range + talent meaning live in each button title. */
.vxb-band-segs{display:inline-flex;border:1px solid rgba(44,74,62,.14);border-radius:100px;background:rgba(250,247,242,.6);padding:2px;overflow:hidden}
.vxb-band-seg{border:0;background:transparent;color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.02em;padding:4px 9px;border-radius:100px;cursor:pointer;white-space:nowrap;transition:background .15s ease,color .15s ease,opacity .15s ease;font-weight:600}
.vxb-band-seg:hover{background:rgba(44,74,62,.06);color:var(--green,#2C4A3E)}
.vxb-band-seg.is-active{background:var(--gold,#C8A96E);color:#fff}
.vxb-band-seg.is-onramp{color:var(--gold-deep,#A07840);opacity:.65}
/* 2026-06-10 (Stephen — mobile overlap fix) — single cycle button replaces the
   segments, with Skip as a sibling pill to its right. 2026-06-26 — UNIFIED to the
   global $/$$/$$$/$$$$ tier scale: none = grey/dashed placeholder (at the inherited
   tier); then lightest → soft → mid → deep gold for $ / $$ / $$$ / $$$$. */
@media (max-width:560px){
  /* 2026-06-10 (Stephen) — on phones, STACK Skip beneath the tier pill so the
     band column is one pill wide; that reclaims ~50px of horizontal room for
     the item name + descriptor pills. Pills fill the narrow column. */
  .vxb-band-seg{padding:4px 7px;font-size:.58rem}
}
/* ═══════════ CALM BUDGET LOOK-PASS (2026-07-19) ═══════════
   Per-line detail demotes into an on-tap .vxb-item-detail panel (the chevron
   replaces the retired ⓘ popover); category subtotals quiet down; adds the
   Next-3 Vera card + the "optional for your day" line. All #section-budget-
   scoped so these win the cascade over the pre-calm .vxb-* rules above by
   specificity. The band pill + amount input stay inline (load-bearing). */
#section-budget .vx-next3{background:var(--white,#fff);border:1px solid var(--border,#eae5dd);border-radius:16px;padding:22px 24px;margin:22px 0 30px}
#section-budget .vx-next3[hidden]{display:none}
#section-budget .vx-next3-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);margin:0 0 8px}
#section-budget .vx-next3-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.4rem;font-weight:500;color:var(--charcoal,#33352f);margin:0 0 4px;display:block}
#section-budget .vx-next3-sub{font-size:.85rem;color:var(--text-muted,#88928d);margin:0 0 12px}
#section-budget .vx-next3-row{display:flex;align-items:center;gap:14px;padding:14px 0;border-top:1px solid var(--border,#eae5dd)}
#section-budget .vx-next3-ic{width:20px;color:var(--green-mid,#3a6b59);flex-shrink:0;text-align:center;font-family:var(--ff-m,'DM Mono',monospace)}
#section-budget .vx-next3-txt{flex:1;font-size:1rem;line-height:1.4;color:var(--charcoal,#33352f)}
#section-budget .vx-next3-act{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;color:var(--green,#2C4A3E);background:transparent;border:1px solid var(--green,#2C4A3E);border-radius:100px;padding:6px 16px;cursor:pointer;white-space:nowrap}
#section-budget .vx-next3-act:hover{background:var(--green-pale,#EAF0ED)}
#section-budget .vxb-section-head{padding:20px 2px;border-bottom:none;margin-bottom:0}   /* 2026-07-19: uniform padding on booked + in-process heads (locked titles are now the same large type, so the flush treatment no longer fits) */
/* ⚑ THE OWNED CATEGORY JOINS THE SELECTOR LIST RATHER THAN COPYING IT.
   Stephen: Transportation should "operate like every other expandable
   category". A parallel block would drift the first time one side is tuned —
   and this variant already had NO rules in this layer at all, which is why it
   stacked centred while its neighbours sat in a row. Sharing the selector is
   the only version of parity that cannot come apart. */
#section-budget .vxb-section.is-planned .vxb-section-head,
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-head{display:flex;flex-direction:row;align-items:center;flex-wrap:nowrap;gap:14px;min-height:0}
#section-budget .vxb-section.is-planned .vxb-section-title,
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-title{order:1;flex:1 1 auto;min-width:0}
#section-budget .vxb-section.is-planned .vxb-section-meta,
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-meta{order:2;margin-left:auto;display:flex;align-items:center;gap:14px}
#section-budget .vxb-section.is-planned .vxb-chevron{order:3;margin-left:0}
#section-budget .vxb-section-title{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-cat-title,.9rem);font-weight:600;color:var(--money-ink,#33352f);margin:0}
#section-budget .vxb-chevron{width:24px;height:24px;background:transparent;color:var(--green,#2C4A3E);font-size:1.5rem}
#section-budget .vxb-section.is-expanded .vxb-chevron{background:transparent;color:var(--gold,#C8A96E)}
#section-budget .vxb-amount{color:var(--money-ink,#33352f)}   /* family/size/weight from the canonical money block; color unified here (was DM Mono muted) */
#section-budget .vxb-section.is-planned:not(.is-expanded) .vxb-bulk-toggle,
#section-budget .vxb-section.is-planned:not(.is-expanded) .vxb-reset-medians,
#section-budget .vxb-section.is-planned:not(.is-expanded) .vxb-amount-tag{display:none}
#section-budget .vxb-item{display:grid;grid-template-columns:minmax(0,1fr) 132px;align-items:center;gap:16px;padding:14px 2px 14px 10px;border-bottom:none;border-top:1px solid rgba(44,74,62,.07)}
#section-budget .vxb-items-inner .vxb-item:first-child{border-top:none}
#section-budget .vxb-item-name{min-width:0}
#section-budget .vxb-item-name-row{font-size:.86rem;color:var(--charcoal,#33352f);display:flex;flex-wrap:nowrap;align-items:center;gap:7px;min-width:0}
/* 2026-07-25 — the name text truncates; the expand chevron (relocated here from
   the money column) stays a quiet affordance right after the name, so the money
   column can hold a single clean right-aligned ledger. */
#section-budget .vxb-item-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
#section-budget .vxb-item-name-row .vxb-item-expand{width:22px;height:22px;font-size:1.15rem;color:var(--text-muted,#b3b0a8);flex-shrink:0}
#section-budget .vxb-item-amount{display:inline-flex;align-items:center;gap:8px;justify-self:end;flex-wrap:nowrap}
#section-budget .vxb-amount-input{font-family:var(--ff-m,'DM Mono',monospace);font-size:1rem;font-weight:500;color:var(--charcoal,#33352f);width:92px;text-align:right;border:1px solid transparent;background:transparent;border-radius:8px;padding:6px 8px}
#section-budget .vxb-amount-input:hover{border-color:var(--border,#eae5dd)}
#section-budget .vxb-amount-input:focus{border-color:var(--green,#2C4A3E);outline:none;background:var(--white,#fff)}
#section-budget .vxb-amount-prefix{color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace)}
/* 2026-07-25 (first-view polish) — consolidated money treatment. Match the
   line-item text (DM Sans, .84rem, tabular figures) so amounts never out-weigh
   the names; hide number spinners; and let the input hug its digits (width set
   inline per amount in _renderItemRow) so the $ sits tight to the number
   cross-browser (iOS Safari has no field-sizing). Higher specificity than the
   scattered base/mobile rules, so it wins at every width. */
#section-budget .vxb-item .vxb-item-amount{gap:2px}
#section-budget .vxb-item .vxb-amount-input{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--money-ink,#33352f);width:var(--money-field-w,68px);min-width:var(--money-field-w,68px);max-width:var(--money-field-w,68px);text-align:right;padding:5px 0;appearance:none;-moz-appearance:textfield}
#section-budget .vxb-item .vxb-amount-input::-webkit-outer-spin-button,
#section-budget .vxb-item .vxb-amount-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
#section-budget .vxb-item .vxb-amount-prefix{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;color:var(--money-ink,#33352f);margin-right:0}
#section-budget .vxb-section-meta .vxb-amount[data-cat-amount]{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--money-ink,#33352f)}
/* 2026-07-25 — "Why this number" detail panel: same scale as the sheet. The
   unit-formula was 1rem (out-weighing the .86rem line names); bring it to .9rem
   and quiet the source/util lines so the panel reads as one consistent voice. */
#section-budget .vxb-mc-why{font-size:.9rem;font-weight:500;color:#33352f}
#section-budget .vxb-mc-src{font-size:.8rem;color:#5b625a}
#section-budget .vxb-item-util{font-size:.78rem}
#section-budget .vxb-mc-inline{font-size:.82rem}
@media (max-width:700px){
  #section-budget .vxb-section-title{font-size:var(--fs-cat-title,.9rem)}   /* 2026-07-28: was 1.18rem for the retired serif; DM Sans title is one size across breakpoints */
  #section-budget .vxb-item-name-row{font-size:.85rem}
}
#section-budget .vxb-item-expand{width:26px;height:26px;border-radius:50%;border:none;background:transparent;color:var(--text-muted,#88928d);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.35rem;line-height:1;flex-shrink:0;transition:transform .22s cubic-bezier(.22,.61,.36,1),color .15s}
#section-budget .vxb-item-expand:hover{color:var(--green,#2C4A3E)}
#section-budget .vxb-item.is-open .vxb-item-expand{transform:rotate(90deg);color:var(--gold,#C8A96E)}
#section-budget .vxb-item-detail{grid-column:1 / -1;max-height:0;overflow:hidden;opacity:0}
#section-budget .vxb-item.is-open .vxb-item-detail{max-height:none;opacity:1;overflow:visible;margin:6px 0 2px;padding:16px 18px;background:var(--cream-warm,#F0EBE1);border-radius:12px}
#section-budget .vxb-mc-why-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted,#88928d);margin:0 0 6px}
#section-budget .vxb-mc-why{font-size:1rem;line-height:1.55;color:var(--charcoal,#33352f);margin:0 0 3px}
#section-budget .vxb-mc-src{font-size:.82rem;color:var(--text-mid,#5b625a);margin:0 0 2px}
/* The way into the transportation worksheet. A door, not a lock — so it reads
   as an invitation and never as a disabled field. */
#section-budget .vxb-mc-tp-open{margin:10px 0 0;padding:8px 16px;min-height:38px;border-radius:100px;
  cursor:pointer;border:1px solid var(--green,#2C4A3E);background:var(--green,#2C4A3E);color:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;font-weight:500}
#section-budget .vxb-mc-tp-open:hover{background:#243D33;border-color:#243D33}
#section-budget .vxb-detail-controls{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:14px}
/* 2026-08-13 — the hotel line's lodging-tier extras: confirm the market modifier
   we inferred, and the on/off-route hotel list behind the door. Deliberately the
   SAME faces and weights as the "why this number" block above them (DM Sans
   .84rem body, mono only for the eyebrow) — the typography-consistency pass, and
   a new visual language on one line would read as a different product. */
#section-budget .vxb-hb-adj{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0 2px}
#section-budget .vxb-hb-adj-btn{appearance:none;-webkit-appearance:none;cursor:pointer;
  border:1px solid var(--border,#eae5dd);background:var(--white,#fff);color:var(--text-mid,#5b625a);
  border-radius:100px;padding:5px 13px;min-height:32px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;font-weight:500;line-height:1}
#section-budget .vxb-hb-adj-btn:hover{border-color:var(--green,#2C4A3E);color:var(--green,#2C4A3E)}
/* The applied choice reads as SETTLED, not as an alert — no red anywhere, since a
   market adjustment is a refinement and never a problem with their plan. */
#section-budget .vxb-hb-adj-btn.is-on{background:var(--green-pale,#EAF0ED);
  border-color:var(--green-mid,#3a6b59);color:var(--green-mid,#3a6b59)}
#section-budget .vxb-hb-route{margin-top:10px}
#section-budget .vxb-hb-route:empty{display:none}
#section-budget .vxb-hb-hotel{display:flex;align-items:baseline;gap:8px;padding:5px 0;
  border-bottom:1px solid rgba(44,74,62,.07);font-family:var(--ff-b,'DM Sans',sans-serif)}
#section-budget .vxb-hb-hotel:last-child{border-bottom:none}
#section-budget .vxb-hb-dot{flex:0 0 8px;width:8px;height:8px;border-radius:50%;
  background:var(--gold,#C8A96E);transform:translateY(-1px)}
#section-budget .vxb-hb-hotel.is-off .vxb-hb-dot{background:#aab2ac}
#section-budget .vxb-hb-nm{font-size:.84rem;font-weight:500;color:#33352f}
#section-budget .vxb-hb-hotel.is-off .vxb-hb-nm{color:var(--text-mid,#5b625a)}
#section-budget .vxb-hb-meta{font-size:.78rem;color:var(--text-muted,#88928d);margin-left:auto;
  white-space:nowrap}
@media (max-width:700px){
  #section-budget .vxb-hb-hotel{flex-wrap:wrap}
  #section-budget .vxb-hb-meta{margin-left:16px;width:100%}
}
/* 2026-07-26 — Quality-tier picker, first control in the line expand (was row col 1).
   Five segments — None · $ · $$ · $$$ · $$$$ — one tap to any tier. Active segment
   carries the tier's gold shade (deeper = pricier); None active = neutral grey. */
#section-budget .vxb-item-detail .vxb-detail-tier{display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;margin:0 0 4px}
#section-budget .vxb-item-detail .vxb-detail-tier-lbl{font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted,#88928d)}
#section-budget .vxb-tier-segs{display:inline-flex;align-items:stretch;border:1px solid rgba(44,74,62,.16);border-radius:100px;background:rgba(250,247,242,.6);padding:3px;gap:2px;white-space:nowrap}
#section-budget .vxb-tier-segs.is-skipped{opacity:.5}
#section-budget .vxb-tier-seg{appearance:none;-webkit-appearance:none;border:none;background:transparent;cursor:pointer;font-family:var(--ff-m,'DM Mono',monospace);font-size:.72rem;font-weight:600;letter-spacing:.02em;line-height:1;color:var(--text-muted,#8a938d);padding:6px 12px;border-radius:100px;transition:background .15s ease,color .15s ease}
#section-budget .vxb-tier-seg:hover{color:var(--gold-deep,#A07840)}
#section-budget .vxb-tier-seg.is-active{color:#fff;background:var(--gold,#C8A96E)}
#section-budget .vxb-tier-seg.is-active.is-r0{background:rgba(200,169,110,.9)}
#section-budget .vxb-tier-seg.is-active.is-r1{background:var(--gold,#C8A96E)}
#section-budget .vxb-tier-seg.is-active.is-r2{background:var(--gold-deep,#A07840)}
#section-budget .vxb-tier-seg.is-active.is-r3{background:#8a6d3a}
#section-budget .vxb-tier-seg.is-none.is-active{color:var(--text-mid,#5b625a);background:rgba(44,74,62,.1)}
@media (max-width:700px){#section-budget .vxb-tier-seg{padding:6px 9px;font-size:.7rem}}
#section-budget .vxb-detail-controls .vxb-mc-inline{display:inline-flex;align-items:center;gap:7px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.82rem;color:var(--text-mid,#5b625a);background:var(--white,#fff);border:1px solid var(--border,#eae5dd);border-radius:100px;padding:4px 12px;white-space:nowrap}
/* 2026-07-25 (Stephen) — "Why this number" box reads as ONE uniform voice: the
   formula, the explanation and the provenance are all DM Sans .84rem (the sheet's
   body face), no mono, no size jumps. Eyebrow is the same size, just bolder as the
   mini-heading. Higher specificity (+ later source) than the scattered rules above,
   so it's the authority. */
#section-budget .vxb-item-detail .vxb-mc-why-eyebrow{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:600;letter-spacing:.01em;text-transform:none;color:#33352f;margin:0 0 6px}
#section-budget .vxb-item-detail .vxb-mc-why,
#section-budget .vxb-item-detail .vxb-mc-src,
#section-budget .vxb-item-detail .vxb-item-util{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:400;line-height:1.5;letter-spacing:normal;text-transform:none;color:#4a4a4a}
#section-budget .vxb-detail-controls .vxb-mc-inline.is-overridden{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
#section-budget .vxb-detail-controls .vxb-unit-input{width:44px;text-align:center;border:none;border-bottom:1px solid var(--gold,#C8A96E);background:transparent;font-family:var(--ff-m,'DM Mono',monospace);font-size:.85rem;color:var(--charcoal,#33352f);padding:2px 0}
#section-budget .vxb-detail-controls .vxb-mc-inline-lbl{color:var(--text-muted,#88928d)}
#section-budget .vxb-detail-controls .vxb-item-reset{display:inline-flex;align-items:center;width:auto;height:auto;min-width:0;border:1px solid var(--border,#eae5dd);background:var(--white,#fff);border-radius:100px;padding:5px 12px;margin:0;cursor:pointer;color:var(--text-mid,#5b625a);font-family:var(--ff-m,'DM Mono',monospace);font-size:.82rem;text-transform:none;letter-spacing:normal}
#section-budget .vxb-detail-controls .vxb-item-reset:hover{border-color:var(--green,#2C4A3E);color:var(--green,#2C4A3E)}
#section-budget .vxb-detail-controls .vxb-pill,
#section-budget .vxb-detail-controls .vxb-ov-chip{font-size:.78rem;background:var(--green-pale,#EAF0ED);color:var(--green-mid,#3a6b59);padding:5px 12px;border-radius:100px;text-transform:none;letter-spacing:normal}
#section-budget .vxb-detail-controls .vxb-strat{font-size:.78rem;background:var(--gold-pale,#F4ECD8);color:var(--gold-deep,#A07840);padding:5px 12px;border-radius:100px}
#section-budget .vxb-detail-controls .vxb-item-util{font-size:.82rem;color:var(--text-muted,#88928d);display:inline;font-style:normal}
#section-budget .vxb-optional{border-top:1px solid rgba(44,74,62,.07)}
#section-budget .vxb-optional-head{display:flex;align-items:center;gap:12px;padding:14px 2px 14px 10px;cursor:pointer;user-select:none;background:transparent;border:none;width:100%;text-align:left;font:inherit}
#section-budget .vxb-optional-ic{color:var(--text-muted,#88928d);font-family:var(--ff-m,'DM Mono',monospace)}
#section-budget .vxb-optional-label{font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-mid,#5b625a);flex:1}
#section-budget .vxb-optional-note{font-size:.78rem;color:var(--text-muted,#88928d)}
#section-budget .vxb-optional-chevron{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.3rem;color:var(--text-muted,#88928d);transition:transform .22s;line-height:1}
#section-budget .vxb-optional.is-open .vxb-optional-chevron{transform:rotate(90deg);color:var(--green,#2C4A3E)}
#section-budget .vxb-optional-body{max-height:0;overflow:hidden;opacity:0}
#section-budget .vxb-optional.is-open .vxb-optional-body{max-height:none;opacity:1;overflow:visible;padding:0 2px 10px 32px}
#section-budget .vxb-opt-row{display:flex;align-items:center;gap:16px;padding:11px 0;border-top:1px solid rgba(44,74,62,.07)}
#section-budget .vxb-opt-name{flex:1;color:var(--text-mid,#5b625a);font-size:.98rem}
#section-budget .vxb-opt-price{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums;color:var(--text-muted,#88928d)}
#section-budget .vxb-opt-add{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;color:var(--green,#2C4A3E);background:transparent;border:1px solid var(--green,#2C4A3E);border-radius:100px;padding:5px 14px;cursor:pointer}
#section-budget .vxb-opt-add:hover{background:var(--green-pale,#EAF0ED)}
/* ── calm v2 (2026-07-19): compact tier pill in col 1 · shared money column
   (amounts right-align, 22px chevron + 12px gap on both category head + line) ·
   Skip as a gray status tag left of the amount · ↺ left of Skip. Appended so it
   overrides the v1 rules above by source order. ── */
#section-budget .vxb-section.is-planned .vxb-section-head,
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-head{gap:0}
#section-budget .vxb-section.is-planned .vxb-section-meta,
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-meta{gap:0}
/* ⚑ THE $ WAS MOVING LEFT, AND IT WAS THIS. Stephen 2026-08-28, from the iOS
   Simulator: "the $'s are moving left". MEASURED at 402pt with the real font
   stack: every planned row's amount ends at x=375 against a head right edge of
   379; Transportation's ended at 327 — forty-eight pixels of dead space, and
   the status pill pushed back against the title with no gap to separate them.

   Two causes, both an ABSENCE rather than an override:
     · planned heads right-align their content (justify-content:flex-end, set at
       <=600px). `.is-owned-elsewhere` never got it, so it packed to flex-start.
     · the rule directly above zeroes the head gap for BOTH, but planned wins a
       12px column-gap back from a later rule. Owned-elsewhere kept 0, which is
       why "FROM YOUR PLAN" sat against "Transportation".

   ⚑ AND IT WAS NEVER A WEBKIT BUG. An earlier probe cleared the component
   because it measured a container that was display:none with no webfonts — the
   title came back 38px wide. With the real cascade, the real fonts and the
   container shown, Chrome reproduces it exactly. Three earlier hypotheses were
   eliminated honestly; this is the fourth and it is measured, not guessed.

   Right-aligning the meta rather than dissolving it (planned uses
   display:contents plus eight explicit `order:` values and a ::after row-break)
   — the smaller change reaches the same place, and the orders it would have to
   duplicate are the kind of thing that drifts. */
/* ⚑ `margin-left:auto` ON THE META, NOT `justify-content:flex-end` ON THE HEAD.
   flex-end pushes the WHOLE row right, and measured that indented
   "Transportation" to x=55 where every neighbouring title starts at 25 — the
   amount was fixed and the title had moved instead. Letting the name column
   grow keeps the title hard left and the auto margin does the right-alignment,
   which is the pattern the rest of the head layout already uses. */
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-head{
  column-gap: 12px; row-gap: 8px; }
#section-budget .vxb-section.is-owned-elsewhere .vxb-head-name{
  flex: 1 1 auto; min-width: 0; }
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-meta{
  margin-left: auto; column-gap: 12px;
  /* ⚑ AND THE LAST 77px WERE INSIDE THE META. Right-aligning the box was not
     enough: a <=560px rule gives this meta `width:100%` and
     `justify-content:flex-start`, written so it would drop onto its own
     full-width row the way a planned card's does. It never can — the head is
     `flex-wrap:nowrap` — so instead it claimed the whole row and packed the
     pill and the amount against its left edge. Measured: meta box right 383
     (correct), amount right 306.
     Sized to content and packed right, which is what the box was always for. */
  width: auto; justify-content: flex-end;
  /* ⚑ THE LAST TWO PIXELS, MATCHED NOT CHOSEN. Planned metas carry
     `padding-right:2px`; this one carried 0, which left the amount at x=377
     against every neighbour's 375. Copied from the neighbour deliberately — if
     that 2px ever changes it should change for all of them together, and a
     different number invented here is how the column drifts apart again. */
  padding-right: 2px; }
#section-budget .vxb-section.is-planned .vxb-amount,
#section-budget .vxb-section.is-owned-elsewhere .vxb-amount{order:9;text-align:right}
#section-budget .vxb-section.is-planned .vxb-bulk-toggle{order:2;margin-right:12px}
#section-budget .vxb-section.is-planned .vxb-reset-medians{order:3;margin-right:12px}
#section-budget .vxb-chevron{width:22px;flex:0 0 22px;margin-left:12px}
#section-budget .vxb-item{grid-template-columns:minmax(0,1fr) auto;gap:14px;padding:14px 2px 14px 8px}
#section-budget .vxb-item-amount{gap:0}
#section-budget .vxb-item-amount .vxb-item-reset{width:auto;height:auto;min-width:0;border:none;background:transparent;color:var(--text-muted,#88928d);cursor:pointer;font-size:1rem;line-height:1;padding:0;margin:0 10px 0 0;border-radius:0}
#section-budget .vxb-item-amount .vxb-item-reset:hover{color:var(--green,#2C4A3E);background:transparent;border:none}
#section-budget .vxb-amount-prefix{margin-right:1px}
#section-budget .vxb-amount-input{width:var(--money-field-w,68px);min-width:var(--money-field-w,68px);max-width:var(--money-field-w,68px);text-align:right;padding:4px 0}   /* 2026-07-20: fixed slot so every amount is the SAME size (stable money column). 2026-08-07: this rule was never in effect — the renderer wrote an inline width:calc() from the value, and an inline style beats any stylesheet. Inline width removed; the number is now --money-field-w, measured to hold $9999999. */
#section-budget .vxb-item-expand{width:22px;flex:0 0 22px;height:auto;border-radius:0;background:transparent;font-size:1.35rem;margin-left:12px}
/* ── calm v3 (2026-07-19): status by verbiage, uniform type (booked matches in-process fonts) + Tips-line fixes ── */
#section-budget .vxb-status-tag{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:3px 9px;border-radius:100px;white-space:nowrap;border:none;line-height:1.5}
#section-budget .vxb-status-tag.is-booked{color:var(--green-mid,#3a6b59);background:var(--green-pale,#EAF0ED)}
#section-budget .vxb-status-tag.is-process{color:var(--text-muted,#88928d);background:rgba(44,74,62,.06)}
#section-budget .vxb-status-tag.is-soon{color:var(--gold-deep,#A07840);background:rgba(200,169,110,.18)}   /* 2026-07-20: booking window open — gentle gold, never red */
#section-budget .vxb-section-meta .vxb-status-tag{order:8;margin-right:12px}
/* 2026-07-25 (Zola-clean first view) — in the demo, hide the bare "In process"
   status so the collapsed category line stays calm (name + total). The
   category_timing client swaps this tag to "by <Mon Year>" (is-soon/is-booked)
   once a wedding date exists, and that DOES show; only the date-less state is
   hidden. Demo-scoped — subscribers' status behaviour is untouched. */
body.vx-demo-active #section-budget .vxb-status-tag.is-process{display:none}
#section-budget .vxb-section.is-planned:not(.is-expanded) .vxb-section-meta .vxb-status-tag{margin-right:12px}
/* uniform type: booked (locked) title + amount match in-process (planned) — status is carried by the tag, not the font */
#section-budget .vxb-section.is-locked .vxb-section-title{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-cat-title,.9rem);font-weight:600;color:var(--money-ink,#33352f);align-self:center}
/* 2026-07-28 (Stephen) — match the booked/locked category $ to the unlocked category $
   (.vxb-section-meta .vxb-amount ~L8979: DM Sans .84rem/600 tabular #33352f). Was DM Mono
   .9rem/400 muted — a visibly different font. The booked-dim opacity still makes it recede;
   font/size/weight/color now read identically to the planned rows. */
#section-budget .vxc-lock-amount{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:600;font-variant-numeric:tabular-nums;color:#33352f}
/* Tips + priority-control lines keep the wider col 1 (the Must/Nice/Skip pill doesn't fit 64px) */
#section-budget .vxb-tips-line,
/* 2026-07-26 — retired: the Must/Nice/Skip priority control (and the tier pill) moved
   into the .vxb-item-detail expand, so the row no longer needs a first control column.
   `:has(.vxb-item-priority)` would now match the descendant in the panel and wrongly
   re-add a 128px track — kept 2-col instead. */
/* Tips amount into the shared money column (tips lines have no expand chevron) */
#section-budget .vxb-tips-line .vxb-tips-amount-display{margin-right:34px}
/* (planned Lock-chrome flex position now lives in calm v4 below — order:6, margin-left:8px) */
/* 2026-07-20 — standardize the small budget controls to the status-pill scale
   (mobile-first). Skip all / Lock / Unlock / Edit were 0.9rem sans — ~50% bigger
   than the 0.6rem status pills, so the buttons read louder than the status. Bring
   them to the pill size; ↺ icons a touch above text. #id-scoped so it also beats
   the ≤560 mobile rules. Padding is kept, so tap targets don't shrink. */
#section-budget .vxb-bulk-toggle,
#section-budget .vxc-lock-edit,
#section-budget .vxc-lock-unlock,
#section-budget .vxc-lock-cta-mini{font-size:.6rem;letter-spacing:.04em}
#section-budget .vxb-reset-medians,
#section-budget .vxb-item-reset{font-size:.86rem}
/* ── calm v4 (2026-07-20) — denser + harmonized + one aligned money column:
   (1) headings + ALL amounts step down to sit in proportion with the .6rem status
       pills; (2) category gap → 2px — the real control was .vxb-root's flex `gap`
       (18px), NOT the section margin, so earlier margin tweaks just stacked on it;
   (3) the expand chevron moves to hug the category NAME on planned rows so it
       matches the locked rows — every category reads as expandable in the SAME
       spot (the whole head is the click target; the chevron is the cue);
   (4) the trailing cluster is uniform — amount · Edit · Lock/Unlock — on every
       row (planned Edit added in the lock decorator), and the two action buttons
       are width-matched so the money column aligns locked-vs-unlocked at any
       width (the cluster is right-anchored to a fixed inset);
   (5) on phones the head wraps to two deliberate lines (title on 1, values
       right-aligned on 2) via a zero-height flex break, never a mid-row split.
   Appended last so it wins the cascade by source order. ── */
/* (1) type scale — the DATA + controls flatten to the .6rem status-pill size for a
   calm uniform cluster, but the category TITLE stays larger (1.05rem). At equal px the
   Cormorant serif title reads MUCH smaller/thinner than the DM Mono data, so a fully
   flat size makes the title vanish under the numbers (worst on mobile, per Stephen
   2026-07-20). The title is the row's scan anchor and must hold its weight. */
/* 2026-07-28 (Stephen) — CANONICAL TITLE supersedes the 2026-07-20 DM-Sans .82rem title
   experiment: category titles are now Cormorant var(--fs-cat-title) in ONE rule for every
   state (base/planned/locked), governed above. The stale DM-Sans title override that lived
   here is deleted so it no longer collides with / crushes the canonical serif title. */
#section-budget .vxb-item-name-row{font-size:.9rem}
/* 2026-07-28 (Stephen) — .vxc-lock-amount REMOVED from this .6rem "data" group. It's the BOOKED
   category header $, which must match the UNLOCKED header $ (.vxb-amount escapes this .6rem via a
   more-specific .vxb-section-meta rule at ~.84rem; the booked one had no such escape, so it read
   tiny). It now follows its own #section-budget .vxc-lock-amount rule (.84rem). Broader platform
   type consistency is handled by the dedicated type-system pass, not here. */
/* 2026-07-28 (Stephen) — CANONICAL MONEY. This group used to CRUSH budget dollars to .6rem; it is
   now the single soft money face for every functional dollar: DM Sans, --fs-amount, weight 500 (was
   a hard 600), tabular-nums. DM Mono is retired from money. The hero 'wow' figure (.vx-bt-value totals
   strip + #vxDemoEstBig estimate) is deliberately EXCLUDED and stays Cormorant serif (Stephen's call).
   Semantic COLORS stay on each element's own rule (secured=green on .vxc-lock-comp-amt, estimate=muted
   on .vxc-lock-line-est, money-ink elsewhere) — this block governs family/size/weight/figures only. */
#section-budget .vxb-amount,
#section-budget .vxb-amount-input,
#section-budget .vxb-amount-prefix,
#section-budget .vxc-lock-amount,
.vxc-lock-comp-amt,
.vxc-lock-line-est{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);font-weight:500;font-variant-numeric:tabular-nums}
#section-budget .vxb-reset-medians,
#section-budget .vxb-item-reset,
#section-budget .vxb-item-count{font-size:.6rem}
/* (2) density — gap on the flex container; cards + heads tighten */
#section-budget .vxb-root{gap:2px}
#section-budget .vxb-section{padding-top:6px;padding-bottom:6px}
#section-budget .vxb-section-head{padding:4px 2px;min-height:0}
/* (3) title + chevron grouped in .vxb-head-name — the row's left column. On desktop it
   hugs the left; margin-right:auto pushes the meta/chrome cluster right (chevron-by-name).
   The chevron sits ONE consistent space after the title (no bounce), same on every row. */
/* order:0 (not 1): on BOOKED desktop heads the appended lock badge (.vxc-lock-chrome) has
   default order:0; with head-name at order:1 the badge sorted BEFORE the title (reversed row).
   order:0 ties the badge so DOM order wins (head-name is first) → title left, badge right. */
#section-budget .vxb-head-name{display:flex;align-items:center;min-width:0;flex:0 1 auto;order:0;margin-right:auto}
#section-budget .vxb-head-name .vxb-section-title{flex:0 1 auto;min-width:0}
#section-budget .vxb-head-name .vxb-chevron{width:auto;min-width:0;height:auto;flex:0 0 auto;margin:0 0 0 .3em;padding:0;justify-content:flex-start;background:transparent}
/* PLANNED rows carry pre-calm rules that out-specify the two above (1,3,0 > 1,2,0):
   .is-planned .vxb-section-title{flex:1 1 auto;order:1} (L~8709) GROWS the title so its box
   fills the column and the chevron is shoved far from the visible text, and
   .is-planned .vxb-chevron{margin-left:0} (L~8846) removes the one-space gap. Only shows on
   PLANNED cards (locked titles don't grow) — which is why a mostly-booked account looks fine
   but an in-process account doesn't. Override at (1,4,0) so planned hugs like locked: one .3em
   space, every row. */
/* ⚑ AND THE FINAL LAYER TOO. Joining the 9270 block was not enough: a LATER
   block re-orders the same elements (`meta{order:5;margin-left:0}`), so the
   owned variant kept the earlier `margin-left:auto` and still diverged. The
   gate caught it by comparing RESOLVED values rather than counting rules —
   which is the only way to see a cascade. Three layers govern this head; all
   three now name both variants. */
#section-budget .vxb-section.is-planned .vxb-head-name .vxb-section-title,
#section-budget .vxb-section.is-owned-elsewhere .vxb-head-name .vxb-section-title{flex:0 1 auto;order:0}
#section-budget .vxb-section.is-planned .vxb-head-name .vxb-chevron{margin:0 0 0 .3em}
#section-budget .vxb-section.is-planned .vxb-section-meta,
#section-budget .vxb-section.is-owned-elsewhere .vxb-section-meta{order:5;margin-left:0}
#section-budget .vxb-section.is-planned .vxc-lock-chrome{order:6;margin-left:8px;margin-right:10px}
/* (4) fixed money column + width-matched action buttons so the amounts, the pills to
   their left, and Edit all line up across every row (booked + planned) at any width.
   The head DISPLAY amounts were auto-width ($272 vs $47,134 = different widths), which
   shoved the pill left/right row-to-row ("wavy pills"); a fixed 52px right-aligned slot
   (fits $XXX,XXX at .6rem) stabilizes the whole cluster. */
#section-budget .vxb-amount,
#section-budget .vxc-lock-amount{display:inline-block;width:52px;flex:0 0 52px;text-align:right}
#section-budget .vxc-lock-unlock,
#section-budget .vxc-lock-cta-mini{min-width:56px;justify-content:center;text-align:center}
#section-budget .vxc-lock-edit-expand{margin-right:8px;cursor:pointer}
/* neutralize the pre-calm ≤600 head ::after breaker (L~7357): in the grid head below it
   would become a stray auto-placed grid item and eat a cell. (1,3,1) beats its (0,3,1). */
#section-budget .vxb-section.is-planned .vxb-section-head::after{content:none}
#section-budget .vxb-head-br{display:none}
/* (5) phones (≤600): the head becomes a 2-column grid — the title (+chevron) fills the
   left ~2/3 vertically centered, and the data forms a 2×2 quadrant on the right ~1/3:
   Q1 status · Q2 amount (top row) / Q3 Edit · Q4 Lock-Unlock (bottom row). Both render
   paths share FIXED columns (172px data area, 60px right sub-col) so a long date pill can
   never shove the amount, and every cell right-justifies with a 2px pad. Desktop = one line.
   2026-07-31 (Stephen) — breakpoint raised 560→600 to match the app's mobile boundary (the
   step-bar hides + the demo footer shows at ≤600). At 561–600px the head fell back to the
   older flex layout whose right-justify rode on the ↺ reset control, which is hidden when a
   category is collapsed → the amounts went ragged. The grid right-justifies them regardless. */
@media (max-width:600px){
  /* SCOPED to .is-planned / .is-locked so it ties the pre-existing (1,3,0) is-planned flex
     rule (L~8708) and wins on source order — an unscoped (1,1,0) rule loses and the grid
     never engages for planned cards (the common case). */
  #section-budget .vxb-section.is-planned .vxb-section-head,
  #section-budget .vxb-section.is-locked .vxb-section-head{display:grid;grid-template-columns:1fr 172px;grid-template-rows:auto auto;align-items:center;column-gap:12px;row-gap:7px}
  #section-budget .vxb-head-br{display:none}
  #section-budget .vxb-head-name{grid-column:1;grid-row:1 / span 2;align-self:center;display:flex;align-items:center;gap:0;min-width:0;margin:0}
  #section-budget .vxb-head-name .vxb-chevron{margin:0 0 0 .3em}
  /* 4 data cells: status→Q1(col1) · amount→Q2(col2) · Edit→Q3(col1) · Lock/Unlock→Q4(col2) */
  #section-budget .vxb-status-tag{grid-column:1;min-width:0;margin:0}
  /* the planned "In process" tag keeps a leftover 12px right-margin (L~8786/8787) that beats
     a plain reset; override at matching (1,5,0) specificity so Q1 aligns tight over Q3 */
  #section-budget .vxb-section.is-planned .vxb-section-meta .vxb-status-tag.is-process{margin:0}
  /* on EXPAND, Skip-all / reset-↺ / skipped-tag become visible in the meta and would auto-flow
     into the quadrant; keep them OUT of the mobile head (per-line skip/reset live in the body). */
  #section-budget .vxb-section.is-planned .vxb-section-meta .vxb-bulk-toggle,
  #section-budget .vxb-section.is-planned .vxb-section-meta .vxb-reset-medians,
  #section-budget .vxb-section.is-planned .vxb-section-meta .vxb-amount-tag{display:none}
  #section-budget .vxb-amount,#section-budget .vxc-lock-amount{grid-column:2;width:auto;min-width:0;max-width:none;flex:none;justify-self:end}
  #section-budget .vxc-lock-edit:not(.vxc-lock-cta-mini):not(.vxc-lock-unlock),#section-budget .vxc-lock-edit-expand{grid-column:1;justify-self:end;width:auto;min-width:0;margin:0;white-space:nowrap;line-height:1.5}
  #section-budget .vxc-lock-unlock,#section-budget .vxc-lock-cta-mini{grid-column:2;justify-self:end;width:58px;min-width:58px;white-space:nowrap;text-align:center;line-height:1.5}
  /* planned: meta = top row (Q1|Q2), chrome = bottom row (Q3|Q4) — same fixed sub-columns */
  #section-budget .vxb-section.is-planned .vxb-section-meta{grid-column:2;grid-row:1;display:grid;grid-template-columns:minmax(0,1fr) 60px;align-items:center;justify-items:end;column-gap:6px;width:auto;margin:0;padding-right:2px}
  #section-budget .vxb-section.is-planned .vxc-lock-chrome{grid-column:2;grid-row:2;display:grid;grid-template-columns:minmax(0,1fr) 60px;align-items:center;justify-items:end;column-gap:6px;width:auto;margin:0;padding-right:2px}
  /* booked: dissolve the chrome wrapper so the badge IS the grid cell; badge = the full 2×2 */
  #section-budget .vxb-section.is-locked .vxc-lock-chrome{display:contents}
  #section-budget .vxc-lock-badge{grid-column:2;grid-row:1 / span 2;display:grid;grid-template-columns:minmax(0,1fr) 60px;align-items:center;justify-items:end;column-gap:6px;row-gap:7px;width:auto;margin:0;padding-right:2px}
}
/* (6) tier pill (band cycle) — the col-1 $$/$ chip had min-height:36px (L~8651) + width:100%
   (L~8688 mobile), making it a tall gold-filled box LARGER than the .9rem line-item name
   (Stephen 2026-07-20 "the tier pills are larger than the line items"). Make it a compact,
   centered chip (~34×22) that sits within the line-item row, not a full-column block. */
@media (max-width:560px){
}
/* ═══════════ end calm budget look-pass ═══════════ */
.vxb-item-check input{position:absolute;opacity:0;pointer-events:none}
.vxb-cb-track{width:22px;height:22px;border:1.5px solid var(--border-g,#cdc5b6);border-radius:6px;background:var(--white,#fff);display:flex;align-items:center;justify-content:center;transition:all .18s ease;position:relative}
.vxb-cb-track::after{content:"";width:11px;height:6px;border-left:2px solid var(--white,#fff);border-bottom:2px solid var(--white,#fff);transform:rotate(-45deg) translateY(-2px);opacity:0;transition:opacity .15s ease}
.vxb-item-check input:checked + .vxb-cb-track{background:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E)}
.vxb-item-check input:checked + .vxb-cb-track::after{opacity:1}

/* 2026-06-19 (gen6) — budget-style picker (3-way radio cards). Calm/editorial:
   reuses the profile palette + green/gold accents, no heavy new chrome. */
.vx-bstyle-options{display:flex;flex-direction:column;gap:10px;margin-top:4px}
.vx-bstyle-card{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border:1px solid var(--border-g,#cdc5b6);border-radius:12px;background:var(--white,#fff);cursor:pointer;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}
.vx-bstyle-card:hover{border-color:var(--gold,#C8A96E)}
.vx-bstyle-card input{margin:3px 0 0 0;accent-color:var(--green,#2C4A3E);flex:0 0 auto;width:16px;height:16px;cursor:pointer}
.vx-bstyle-card:has(input:checked){border-color:var(--green,#2C4A3E);background:rgba(44,74,62,.035);box-shadow:0 2px 10px rgba(44,74,62,.06)}
.vx-bstyle-body{display:flex;flex-direction:column;gap:3px;min-width:0}
.vx-bstyle-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.vx-bstyle-name{font-family:var(--ff-d);font-size:1.05rem;color:var(--green,#2C4A3E);font-weight:500}
.vx-bstyle-tag{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.06em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
.vx-bstyle-desc{font-size:.86rem;line-height:1.45;color:var(--text-mid,#5a6460)}
.vx-bstyle-micro{margin-top:10px;font-size:.78rem;font-style:italic;color:var(--text-muted,#88928d)}
.vxb-item-name{display:flex;flex-direction:column;gap:3px;min-width:0}
.vxb-item-name-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-width:0;overflow-wrap:break-word;font-family:var(--ff-b,sans-serif);font-size:.9rem;color:var(--charcoal,#1C1C1C);font-weight:400}
.vxb-item-util{font-family:var(--ff-m,monospace);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted,#88928d);font-style:italic}
.vxb-pill{display:inline-flex;align-items:center;padding:1px 8px;border-radius:100px;font-family:var(--ff-m,monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;font-weight:500}
.vxb-pill-extra{background:var(--rose-pale,#FCE9E9);color:var(--rose,#C97B6A)}
.vxb-pill-bundled{background:var(--green-pale,#EAF0ED);color:var(--green,#2C4A3E)}
.vxb-pill-varies{background:var(--gold-pale,#F4ECD8);color:var(--gold-deep,#A07840)}
.vxb-pill-core{background:rgba(200,169,110,.14);color:var(--gold-deep,#A07840);border:1px solid rgba(200,169,110,.4)}
/* 2026-05-28 — Verdeaux Memorability Lens chip (Phase 1). One color
   family per tag class so couples internalize the framework on scan:
     • PROTECT (green/gold-deep): memory_maker, memory_guest, required,
       lasting_value, low_cost_high_value, personal_priority
     • DEFAULT (warm neutral): moderate, mid_priority, situational,
       guest_experience, keep_practical, keep_simple, can_reduce
     • RELEASE (terracotta/muted): low_priority, easy_save, trendy,
       fun, only_if_needed, optional
   Tooltip on hover = Stephen's one-line note. */
.vxb-strat{display:inline-flex;align-items:center;padding:1px 8px;border-radius:100px;font-family:var(--ff-m,monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;font-weight:500;cursor:help}
/* PROTECT family — high editorial weight, won't-cut signal */
.vxb-strat-memory_maker,.vxb-strat-memory_guest{background:rgba(44,74,62,.10);color:var(--green,#2C4A3E);border:1px solid rgba(44,74,62,.30)}
.vxb-strat-required{background:rgba(160,120,64,.12);color:var(--gold-deep,#A07840);border:1px solid rgba(160,120,64,.40);font-weight:600}
.vxb-strat-lasting_value{background:rgba(44,74,62,.07);color:var(--green-mid,#3a6b59);border:1px solid rgba(44,74,62,.25)}
.vxb-strat-personal_priority{background:rgba(200,169,110,.10);color:var(--gold-deep,#A07840);border:1px solid rgba(200,169,110,.35)}
.vxb-strat-low_cost_high_value{background:rgba(58,107,89,.10);color:var(--green-mid,#3a6b59);border:1px solid rgba(58,107,89,.25)}
.vxb-strat-guest_experience{background:rgba(58,107,89,.08);color:var(--green-mid,#3a6b59);border:1px solid rgba(58,107,89,.22)}
/* DEFAULT family — middle of the road */
.vxb-strat-moderate,.vxb-strat-mid_priority,.vxb-strat-situational,.vxb-strat-keep_practical,.vxb-strat-keep_simple,.vxb-strat-can_reduce{background:rgba(122,116,104,.10);color:var(--charcoal-soft,#7a7468);border:1px solid rgba(122,116,104,.25)}
/* RELEASE family — easy-to-cut signal */
.vxb-strat-low_priority,.vxb-strat-easy_save,.vxb-strat-optional,.vxb-strat-only_if_needed{background:rgba(176,123,63,.07);color:#925e2a;border:1px solid rgba(176,123,63,.22)}
.vxb-strat-trendy{background:rgba(220,80,80,.06);color:#a23030;border:1px solid rgba(220,80,80,.20);font-style:italic}
.vxb-strat-fun{background:rgba(200,169,110,.08);color:var(--gold-deep,#A07840);border:1px solid rgba(200,169,110,.25)}
.vxb-ov-chip{display:inline-flex;align-items:center;padding:1px 8px;border-radius:100px;font-family:var(--ff-m,monospace);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;font-weight:500}
.vxb-ov-lock{background:rgba(58,107,89,.14);color:var(--green-mid,#3a6b59);border:1px solid rgba(58,107,89,.3)}
.vxb-ov-interview{background:rgba(107,92,165,.12);color:#6B5CA5;border:1px solid rgba(107,92,165,.3)}
.vxb-item-amount{display:flex;align-items:center;justify-content:flex-end;gap:2px;font-family:var(--ff-b,'DM Sans',sans-serif)}
.vxb-amount-prefix{color:var(--text-muted,#88928d);font-size:.85rem}
/* 2026-05-28 (Stephen "updatable multiplier factor"): visible × N chip on
   line items that scale by people-count. Editable input writes back to
   the wedding row's count field. Read-only variant shows the value with
   no input border. */
.vxb-unit-chip{display:inline-flex;align-items:center;gap:2px;margin-right:6px;font-family:var(--ff-m,monospace);font-size:.78rem;color:var(--green-mid,#3a6b59)}
.vxb-unit-input{width:42px;border:1px solid var(--border,#eae5dd);background:var(--cream,#FAF7F2);border-radius:5px;padding:3px 6px;font-family:var(--ff-m,monospace);font-size:.78rem;color:var(--green-mid,#3a6b59);text-align:right;outline:none;transition:all .15s ease;-moz-appearance:textfield}
.vxb-unit-input::-webkit-outer-spin-button,.vxb-unit-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.vxb-unit-input:hover{border-color:var(--green-mid,#3a6b59)}
.vxb-unit-input:focus{border-color:var(--green,#2C4A3E);background:var(--white,#fff);box-shadow:0 0 0 3px rgba(44,74,62,.08)}
.vxb-unit-times{color:var(--text-muted,#88928d);font-size:.78rem;font-weight:400;margin:0 2px}
.vxb-unit-readonly .vxb-unit-val{padding:3px 6px;color:var(--text-muted,#88928d);font-size:.78rem}
/* 2026-05-29 EARNED CREDIBILITY PASS — ⓘ pill + popover.
   Per Stephen's preview feedback: the inline chip carried too much visual
   weight against the Lens tags and per-row controls. Converted to a small
   ⓘ pill adjacent to the ↺ reset button. Click opens a floating popover
   in the Compare-card "why" style (.vx-cmp-inquiry-pop @ line ~4598),
   surfacing the formula + count + source citation + baseline note in
   one card.
   2026-05-29 UI v3 (Stephen): match ↺ reset dimensions exactly (24×24)
   for visual parity. Gold border at same opacity as ↺'s terracotta. */
.vxb-mc-info{appearance:none;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:1px solid rgba(200,169,110,.42);border-radius:50%;font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:.95rem;font-style:italic;font-weight:500;line-height:1;color:var(--gold-deep,#A07840);cursor:pointer;padding:0;margin-right:8px;flex-shrink:0;transition:all .15s ease;-webkit-tap-highlight-color:transparent}
.vxb-mc-info:hover{background:#FBF7EE;border-color:#C8A96E;color:#8B6420}
.vxb-mc-info:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
.vxb-mc-info[aria-expanded="true"]{background:#FBF7EE;border-color:#C8A96E}
/* Floating popover — matches .vx-cmp-inquiry-pop visual treatment. */
.vxb-mc-pop{position:fixed;z-index:9999;min-width:240px;max-width:300px;background:#fff;border:1px solid rgba(44,74,62,.18);border-radius:12px;box-shadow:0 16px 36px rgba(0,0,0,.18);padding:14px 16px 12px;font-family:var(--ff-b,'DM Sans',sans-serif);animation:vxbMcPopIn .14s ease}
@keyframes vxbMcPopIn{from{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}
.vxb-mc-pop-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--green,#2C4A3E);font-weight:600;margin-bottom:6px}
.vxb-mc-pop-formula{font-family:var(--ff-m,'DM Mono',monospace);font-size:13px;color:var(--ink,#1a1f1c);line-height:1.4;margin-bottom:8px;font-weight:500}
.vxb-mc-pop-formula strong{color:var(--green,#2C4A3E);font-weight:600}
.vxb-mc-pop-baseline{font-size:11.5px;color:var(--text-mid,#5b6a64);line-height:1.45;margin-bottom:10px;font-style:italic}
.vxb-mc-pop-source{font-family:var(--ff-m,'DM Mono',monospace);font-size:9.5px;letter-spacing:.04em;color:var(--text-muted,#88928d);line-height:1.4;padding-top:8px;border-top:1px solid rgba(44,74,62,.08)}
.vxb-mc-pop-edit{display:flex;align-items:center;gap:8px;margin:8px 0 4px;padding:8px 10px;background:rgba(200,169,110,.08);border:1px dashed rgba(200,169,110,.42);border-radius:8px;font-size:11.5px;color:var(--ink,#1a1f1c)}
.vxb-mc-pop-edit label{flex:1;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:11.5px;color:var(--text-mid,#5b6a64)}
.vxb-mc-pop-edit input{width:60px;border:1px solid rgba(44,74,62,.18);border-radius:6px;padding:4px 8px;font-family:var(--ff-m,'DM Mono',monospace);font-size:12px;text-align:right;-moz-appearance:textfield}
.vxb-mc-pop-edit input::-webkit-outer-spin-button,.vxb-mc-pop-edit input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.vxb-mc-pop-edit input:focus{outline:2px solid var(--gold,#C8A96E);outline-offset:0}
.vxb-mc-pop-close{position:absolute;top:8px;right:8px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;color:var(--text-muted,#88928d);font-size:16px;line-height:1;cursor:pointer;padding:0;border-radius:50%;transition:background .12s,color .12s}
.vxb-mc-pop-close:hover{background:rgba(44,74,62,.06);color:var(--ink,#1a1f1c)}
/* Mobile — keep readable */
@media (max-width:480px){
  .vxb-mc-pop{max-width:90vw;min-width:240px}
  .vxb-mc-info{font-size:1rem}
}
/* 2026-05-29 UI v3 hybrid — editable counts stay inline as chips
   (the count IS the user's lever). Static counts (per_guest, per_table,
   per_oot, per_invite, per_vendor, flat) live only inside the ⓘ pop.
   Per Stephen: "multipliers should still be visible if they are editable
   but on the pop-up only if decision is in the total price."
   Lightweight chip — just × N + label, optional input, no background pill. */
.vxb-mc-inline{display:inline-flex;align-items:center;gap:3px;margin-right:8px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;color:var(--green-mid,#3a6b59);white-space:nowrap;flex-shrink:0}
.vxb-mc-inline .vxb-mc-inline-x{color:var(--text-muted,#88928d);font-weight:400;opacity:.65;font-size:.74rem}
.vxb-mc-inline .vxb-mc-inline-val{color:var(--green,#2C4A3E);font-weight:500;font-variant-numeric:tabular-nums;min-width:14px;text-align:right}
.vxb-mc-inline .vxb-mc-inline-lbl{color:var(--text-muted,#88928d);font-weight:400;font-size:.72rem;margin-left:2px}
.vxb-mc-inline .vxb-mc-inline-rate{color:var(--green-mid,#3a6b59);font-weight:500;font-variant-numeric:tabular-nums;margin-right:1px}
.vxb-mc-inline input.vxb-unit-input{width:38px;padding:2px 5px;border:1px solid var(--border,#eae5dd);background:var(--cream,#FAF7F2);border-radius:5px;font-family:var(--ff-m,monospace);font-size:.76rem;color:var(--green,#2C4A3E);text-align:right;outline:none;transition:all .15s ease;-moz-appearance:textfield}
.vxb-mc-inline input.vxb-unit-input::-webkit-outer-spin-button,
.vxb-mc-inline input.vxb-unit-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.vxb-mc-inline input.vxb-unit-input:hover{border-color:var(--green-mid,#3a6b59)}
.vxb-mc-inline input.vxb-unit-input:focus{border-color:var(--green,#2C4A3E);background:#fff;box-shadow:0 0 0 3px rgba(44,74,62,.08)}
/* 2026-07-04 (per-line count overrides, units__<id>) — a chip whose count is a
   manual per-line override (not the Wedding-Details-derived auto count) wears a
   quiet gold treatment so pinned counts are visible at a glance; the row's ↺
   reset clears the override back to the auto count. */
.vxb-mc-inline.is-overridden input.vxb-unit-input{border-color:rgba(200,169,110,.8);background:rgba(200,169,110,.13);color:var(--gold-deep,#A07840);font-weight:600}
.vxb-mc-inline.is-overridden input.vxb-unit-input:focus{border-color:var(--gold-deep,#A07840);box-shadow:0 0 0 3px rgba(200,169,110,.18)}
/* 2026-05-29 Phase 4.1 — first-visit empty-state polish. When body has
   data-vx-empty-budget="true", suppress the Plan-vs-Funding green banner
   (would read as "$0 under" — nonsense) and dim Optimize/Resize buttons
   (nothing to optimize). The category structure + $0 line items stay
   visible; the inline #vxb-empty-nudge guides next action. */
body[data-vx-empty-budget="true"] #vxbFundingBanner,
body[data-vx-empty-budget="true"] .vxb-funding-banner,
body[data-vx-empty-budget="true"] #vxFundingStatus,
body[data-vx-empty-budget="true"] .vxb-advisor-note{display:none !important}
body[data-vx-empty-budget="true"] #vxbOptimize,
body[data-vx-empty-budget="true"] #vxbResize{opacity:.45;pointer-events:none;filter:saturate(.5)}
body[data-vx-empty-budget="true"] .vxb-mc{opacity:.75}
/* 2026-05-28 (Stephen "make Tips look like the other sections"):
   read-only amount span matches the editable .vxb-amount-input visual
   footprint so the right-edge column aligns across Tips and regular
   item rows. Priority-segment spacer keeps left-side alignment too. */
.vxb-tips-amount-display{display:inline-block;min-width:88px;padding:5px 8px;border:1px solid transparent;background:transparent;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;font-weight:400;color:var(--charcoal,#1C1C1C);text-align:right;line-height:1.2}
/* Same rule as the skipped item rows above: grey, never struck. The class name
   stays `is-struck` because the markup that sets it is shared and renaming it
   would touch the render for no behaviour; what it MEANS is "not included". */
.vxb-tips-amount-display.is-struck{color:var(--charcoal-soft,#7a7468)}
/* 2026-05-28: spacer retired — Tips lines now render the real
   .vxb-item-priority segments so users Must/Nice/Skip each tip.
   No-op selector kept so any cached markup degrades quietly. */
.vxb-tips-priority-spacer{display:none}
.vxb-tips-line .vxb-item-util{font-family:'Cormorant Garamond','Cormorant Fallback',Georgia,serif;font-style:italic;color:rgba(44,74,62,.55);font-size:.74rem;margin-top:2px}
/* Line-item amount inputs sized to match item-name (.vxb-item-name-row
   font-size:.9rem) so the dollar figures and labels read at the same
   visual weight. */
.vxb-amount-input{width:88px;border:1px solid var(--border,#eae5dd);background:var(--cream,#FAF7F2);border-radius:6px;padding:5px 8px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:0.9rem;font-weight:400;color:var(--charcoal,#1C1C1C);text-align:right;outline:none;transition:all .15s ease}
.vxb-amount-input:focus{border-color:var(--green,#2C4A3E);background:var(--white,#fff);box-shadow:0 0 0 3px rgba(44,74,62,.08)}
/* 2026-06-10 (Stephen — mobile pill overlap, ROOT CAUSE) — this block used to
   be @media (max-width:720px) with a stale `28px 1fr 100px` grid (sized for the
   pre-band CHECKBOX). At ≤560px BOTH this rule and the band-aware 560px rule
   matched; this one came later in source order so it WON, cramming the ~96px
   band control (cycle + skip) into a 28px column → the tier/skip pills
   overflowed right on top of the descriptor pills. Engine-independent, which
   is why tweaking only the 560px rule never took. Fix: scope this to the
   561–720 TABLET range (so ≤560 keeps its tuned 112px band column) and give
   the tablet a band-aware first column. Small-screen padding/input tweaks that
   used to live here are duplicated into the ≤560 block below. */
@media (min-width:561px) and (max-width: 720px){
  .vxb-section{padding:18px 16px}
  .vxb-item{grid-template-columns:126px minmax(0,1fr) 100px;gap:10px}
  .vxb-amount-input{width:74px}
  .vxb-section-totals{font-size:.62rem}
}
/* 2026-07-04 (Stephen — mobile "$ / 6777" wrap) — the PHONE amount-input width.
   Must live AFTER the .vxb-amount-input base rule above: the old width in the
   main ≤560 block (~L8000) was dead because the 88px base came later in source
   order at equal specificity and won even inside the matching media query. At
   88px the input + 2px gap + ~9px "$" prefix overflowed the 94px amount column
   and flex-wrap dropped the number onto its own line under the "$". 74px keeps
   $ + number on one line inside the 94px column (type=number shows no commas,
   so 6 digits fit at .9rem). */
@media (max-width:560px){
  .vxb-amount-input{width:74px;padding:5px 6px}
  /* Tips & Gratuity rows put a read-only span in the same 94px amount column
     (min-width:88px base above) — same overflow math, same fix. */
  .vxb-tips-amount-display{min-width:74px;padding:5px 6px}
}

/* Co-presence dot (in header next to identity pill) */
.vx-presence-row{display:inline-flex;align-items:center;gap:8px;margin-right:6px}
.vx-presence-dot{width:8px;height:8px;border-radius:50%;background:var(--green-lt);flex-shrink:0;box-shadow:0 0 0 0 rgba(90,140,122,.4);animation:vx-presence-pulse 2s ease-in-out infinite}
@keyframes vx-presence-pulse{0%,100%{box-shadow:0 0 0 0 rgba(90,140,122,.4)}50%{box-shadow:0 0 0 6px rgba(90,140,122,0)}}
.vx-presence-label{font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--green-mid)}

/* Per-question focus presence (Phase C) — appears next to the question text
   in the Interview when a partner has the same answer field focused. */
.vx-q-focus-badge{display:inline-flex;align-items:center;gap:5px;margin-left:.5rem;padding:2px 8px;border-radius:10px;background:var(--green-pale,#eaf0ed);color:var(--green-mid,#3a6b59);font-family:var(--ff-m,monospace);font-size:.62rem;letter-spacing:.04em;border:1px solid rgba(58,107,89,.18);vertical-align:middle;animation:vx-q-focus-fade .18s ease-out}
.vx-q-focus-badge::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--green-mid,#3a6b59);box-shadow:0 0 0 0 rgba(58,107,89,.45);animation:vx-presence-pulse 2s ease-in-out infinite}
@keyframes vx-q-focus-fade{from{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:none}}

/* Last-saved indicator above the Interview question forms (Phase D) */
.vdx-saved-indicator{display:inline-block;margin:6px 0 14px;padding:3px 10px;border-radius:10px;font-family:var(--ff-m,monospace);font-size:.62rem;letter-spacing:.06em;color:var(--text-muted,#88928d);background:transparent;border:1px solid transparent;transition:background .25s ease,color .25s ease,border-color .25s ease}
.vdx-saved-indicator[data-state="saved"]{color:var(--green-mid,#3a6b59);background:var(--green-pale,#eaf0ed);border-color:rgba(58,107,89,.18)}
.vdx-saved-indicator[data-state="flashing"]{color:#fff;background:var(--green-mid,#3a6b59);border-color:var(--green-mid,#3a6b59)}
.vdx-saved-indicator[data-state="idle"]{color:var(--text-muted,#88928d);background:transparent}

/* Concurrent-edit toast (Phase D) — appears bottom-center when a remote
   write lands while the local user has a field in the same category focused. */
.vdx-conflict-toast{position:fixed;bottom:36px;left:50%;transform:translateX(-50%);background:var(--green,#2C4A3E);color:#FAF7F2;font-family:var(--ff-b,sans-serif);font-size:.82rem;padding:11px 18px;border-radius:24px;box-shadow:0 8px 24px rgba(28,28,28,.18);z-index:9000;animation:vdx-conflict-pop .2s ease-out}
.vdx-conflict-toast.is-fading{opacity:0;transition:opacity .85s ease-out}
@keyframes vdx-conflict-pop{from{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translateX(-50%)}}

/* "While you were away" panel */
.vx-while-away{position:fixed;top:80px;right:24px;max-width:340px;background:var(--white);border:1px solid var(--border-g);border-radius:var(--radius-lg);box-shadow:0 8px 28px rgba(28,28,28,.12);padding:18px 22px;z-index:850;font-family:var(--ff-b)}
.vx-while-away[hidden]{display:none}
.vx-while-away h4{font-family:var(--ff-d);font-size:1.05rem;color:var(--green);margin:0 0 .35rem;font-weight:500}
.vx-while-away p{font-size:.8rem;color:var(--text-mid);margin:0 0 .85rem}
.vx-while-away ul{list-style:none;padding:0;margin:0 0 .85rem;max-height:240px;overflow-y:auto}
.vx-while-away ul li{font-size:.78rem;color:var(--charcoal);padding:5px 0;border-bottom:1px dashed var(--border);line-height:1.45}
.vx-while-away ul li:last-child{border-bottom:none}
.vx-while-away ul li time{display:block;font-family:var(--ff-m);font-size:.62rem;color:var(--text-muted);letter-spacing:.04em;margin-top:2px}
.vx-while-away-close{appearance:none;background:none;border:1px solid var(--border-g);border-radius:8px;padding:6px 12px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;color:var(--text-mid);cursor:pointer}
.vx-while-away-close:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}

/* Conflict-resolution modal (stale-check) */
#vx-conflict-modal{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(28,28,28,.5);backdrop-filter:blur(3px);z-index:9999;padding:20px}
#vx-conflict-modal .vx-cf-card{background:var(--white);border-radius:var(--radius-lg);max-width:480px;width:100%;padding:28px 30px;box-shadow:0 12px 40px rgba(28,28,28,.2)}
#vx-conflict-modal h3{font-family:var(--ff-d);font-size:1.4rem;color:var(--green);margin:0 0 .5rem;font-weight:500}
#vx-conflict-modal h3 em{color:var(--gold);font-style:italic}
#vx-conflict-modal .vx-cf-detail{font-size:.85rem;color:var(--text-mid);line-height:1.5;margin-bottom:1.25rem}
#vx-conflict-modal .vx-cf-values{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:1.25rem}
#vx-conflict-modal .vx-cf-value{padding:14px;border:1.5px solid var(--border-g);border-radius:10px;background:var(--cream)}
#vx-conflict-modal .vx-cf-value strong{display:block;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px}
#vx-conflict-modal .vx-cf-value-content{font-family:var(--ff-b);font-size:.95rem;color:var(--charcoal);word-wrap:break-word}
#vx-conflict-modal .vx-cf-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
#vx-conflict-modal button{padding:10px 18px;border-radius:8px;font-family:var(--ff-b);font-size:.85rem;cursor:pointer;border:1px solid var(--border-g);background:var(--white);color:var(--text-mid)}
#vx-conflict-modal button.primary{background:var(--green);color:var(--white);border-color:var(--green)}
#vx-conflict-modal button.primary:hover{background:var(--green-deep)}
#vx-conflict-modal button:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
#vx-conflict-modal .vx-cf-note{margin-top:1rem;padding-top:1rem;border-top:1px dashed var(--border)}
#vx-conflict-modal .vx-cf-note textarea{width:100%;min-height:60px;padding:8px 12px;border:1.5px solid var(--border-g);border-radius:8px;font-family:var(--ff-b);font-size:.85rem;background:var(--cream);resize:vertical}

/* Decision-log timeline view */
.vx-decision-log{max-width:920px;margin:0 auto;padding:24px clamp(20px,5vw,48px)}
.vx-dl-entry{display:grid;grid-template-columns:80px 1fr;gap:16px;padding:14px 0;border-bottom:1px dashed var(--border)}
.vx-dl-entry:last-child{border-bottom:none}
.vx-dl-time{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted);padding-top:3px}
.vx-dl-summary{font-size:.9rem;color:var(--charcoal);line-height:1.5}
.vx-dl-summary strong{color:var(--green-mid);font-weight:500}

/* ═══ Decisions tab (2026-05-09) — editorial timeline of wedding_decisions
   inside the Account panel. Distinct from .vx-decision-log above (legacy,
   only used by an embedded view). The .vx-dec-* classes are scoped to the
   Account-Decisions panel. */
.vx-dec-loading{font-family:var(--ff-b);font-size:.9rem;color:var(--text-muted);padding:24px 0;text-align:center;font-style:italic}
.vx-dec-empty{padding:32px 24px;text-align:center;background:var(--cream);border:1px dashed var(--border-g);border-radius:var(--radius-lg)}
.vx-dec-empty p{font-family:var(--ff-d);font-size:1.1rem;color:var(--text-mid);font-style:italic;margin:0;line-height:1.55}
.vx-dec-timeline{display:flex;flex-direction:column;gap:18px;margin-top:8px}

/* 2026-05-22 — Tasks sub-tab. Sibling of Decisions/Videos. Read-only
   library view; system writes via the 6 writer paths. */
.vx-tasks-loading{font-family:var(--ff-b);font-size:.9rem;color:var(--text-muted);padding:24px 0;text-align:center;font-style:italic}
.vx-tasks-empty{padding:32px 24px;text-align:center;background:var(--cream);border:1px dashed var(--border-g);border-radius:var(--radius-lg)}
.vx-tasks-empty-lede{font-family:var(--ff-d);font-size:1.25rem;color:var(--green);margin:0 0 12px;font-style:italic}
.vx-tasks-empty p{font-family:var(--ff-b);font-size:.9rem;color:var(--text-mid);line-height:1.6;margin:0 0 12px;max-width:560px;margin-left:auto;margin-right:auto}
.vx-tasks-empty-cta a{color:var(--gold-deep);text-decoration:none;border-bottom:1px solid var(--gold);font-family:var(--ff-b);font-size:.92rem}
.vx-tasks-empty-cta a:hover{color:var(--green);border-bottom-color:var(--green)}
.vx-tasks-bar{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:12px 16px;background:var(--cream-warm,#F0EBE1);border:1px solid var(--border-g);border-radius:var(--radius-lg);margin:8px 0 16px;flex-wrap:wrap}
.vx-tasks-bar-meta{display:flex;align-items:center;gap:10px;font-family:var(--ff-b);font-size:.85rem;color:var(--text-mid)}
.vx-tasks-bar-count{font-weight:500;color:var(--green)}
.vx-tasks-bar-sep{color:var(--text-muted)}
.vx-tasks-bar-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.vx-tasks-bar-cta{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:7px 12px;border-radius:14px;border:1px solid var(--gold);background:white;color:var(--gold-deep);text-decoration:none;cursor:pointer;transition:all .15s}
.vx-tasks-bar-cta:hover{background:var(--gold);color:white}
.vx-tasks-filters{display:flex;align-items:center;gap:8px;margin:0 0 14px;flex-wrap:wrap}
.vx-tasks-filter{appearance:none;background:transparent;border:1px solid var(--border-g);border-radius:14px;padding:5px 12px;font-family:var(--ff-m);font-size:.68rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-mid);cursor:pointer;transition:all .15s}
.vx-tasks-filter:hover{border-color:var(--gold);color:var(--gold-deep)}
.vx-tasks-filter.is-active{background:var(--green);color:white;border-color:var(--green)}
.vx-tasks-filter-sep{color:var(--border-g);margin:0 2px}
.vx-tasks-list{display:flex;flex-direction:column;gap:10px;margin-top:8px}
.vx-task-card{display:flex;align-items:flex-start;gap:14px;padding:14px 18px;background:white;border:1px solid var(--border-g);border-left:3px solid var(--gold);border-radius:var(--radius-lg);transition:border-color .15s,box-shadow .15s}
.vx-task-card:hover{border-left-color:var(--gold-deep);box-shadow:0 2px 12px rgba(44,74,62,.06)}
.vx-task-card.is-done{opacity:.55;border-left-color:var(--green)}
.vx-task-card.is-overdue{border-left-color:var(--amber-risk,#C97B3A)}
.vx-task-card.is-critical{border-left-color:var(--red-risk,#B94040)}
.vx-task-checkbox{appearance:none;flex-shrink:0;width:20px;height:20px;border:1.5px solid var(--border-g);border-radius:5px;background:white;cursor:pointer;margin-top:1px;transition:all .15s;position:relative}
.vx-task-checkbox:hover{border-color:var(--green)}
.vx-task-checkbox:checked{background:var(--green);border-color:var(--green)}
.vx-task-checkbox:checked::after{content:'✓';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:white;font-size:13px;font-weight:600;line-height:1}
.vx-task-body{flex:1;min-width:0}
/* 2026-07-29 — per-task trashcan (soft-dismiss). Quiet until card hover/focus;
   always faintly visible on touch (no hover). */
.vx-task-trash{flex-shrink:0;align-self:center;width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;padding:0;border:none;background:transparent;color:var(--ink-faint,#9a948a);border-radius:8px;cursor:pointer;opacity:0;transition:opacity .15s,color .15s,background .15s}
.vx-task-card:hover .vx-task-trash{opacity:1}
.vx-task-trash:hover{color:var(--red-risk,#B94040);background:rgba(185,64,64,.08)}
.vx-task-trash:focus-visible{opacity:1;outline:2px solid var(--gold);outline-offset:2px}
.vx-task-trash:disabled{cursor:default;opacity:.4}
@media (hover:none){.vx-task-trash{opacity:.55}}
.vx-task-title{font-family:var(--ff-b);font-size:.95rem;font-weight:500;color:var(--ink);line-height:1.35;margin:0 0 4px}
.vx-task-card.is-done .vx-task-title{text-decoration:line-through;color:var(--text-muted)}
.vx-task-meta{display:flex;align-items:center;gap:10px;margin:4px 0;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);flex-wrap:wrap}
.vx-task-source{color:var(--gold-deep);font-weight:500}
.vx-task-due{color:var(--text-mid)}
.vx-task-due.is-overdue{color:var(--amber-risk,#C97B3A);font-weight:600}
.vx-task-amount{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-amount,.9rem);color:var(--money-ink,#33352f);font-weight:500;font-variant-numeric:tabular-nums;letter-spacing:0;text-transform:none}
.vx-task-desc{font-family:var(--ff-b);font-size:.85rem;color:var(--text-mid);line-height:1.55;margin:4px 0 0;max-width:680px}
.vx-task-assignee{font-family:var(--ff-m);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);padding:3px 8px;border:1px solid var(--border-g);border-radius:10px;background:var(--cream);flex-shrink:0}

/* 2026-05-22 — Chat Remember button. Appears under non-streaming
   assistant replies. One-tap → writes a chat_remember task via the
   task_create_chat_remember RPC. */
.vx-chat-remember{display:inline-flex;align-items:center;gap:6px;margin-top:8px;padding:5px 10px;border:1px solid rgba(200,169,110,.4);border-radius:14px;background:rgba(200,169,110,.06);color:var(--gold-deep);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;cursor:pointer;transition:all .15s}
.vx-chat-remember:hover{background:var(--gold);color:white;border-color:var(--gold)}
.vx-chat-remember:disabled{opacity:.55;cursor:not-allowed}
.vx-chat-remember.is-saved{background:rgba(58,107,89,.1);color:var(--green);border-color:var(--green)}

/* 2026-05-22 — 10-Min Prep phase content. Editorial register: large
   Cormorant title, paragraphic sections, must-ask list with "why this
   matters" subtext. Video slot sits at top when present. */
.vx-prep-wrap{max-width:780px;margin:0 auto;padding:8px 0 32px}
.vx-prep-hero{margin-bottom:24px}
.vx-prep-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);font-weight:500;margin-bottom:8px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.vx-prep-listen{margin-left:auto;background:var(--green,#2C4A3E);border:1px solid var(--green,#2C4A3E);color:white;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:4px 12px;border-radius:10px;cursor:pointer;font-weight:500;transition:background .15s,border-color .15s,transform .12s}
.vx-prep-listen:hover{background:#243d34;transform:translateY(-1px)}
.vx-prep-listen.is-loading{background:#a18650;border-color:#a18650;cursor:wait}
.vx-prep-listen.is-playing{background:#b94040;border-color:#b94040;animation:vx-pulse 1.4s infinite}
.vx-prep-refresh{background:transparent;border:1px solid rgba(161,134,80,.35);color:var(--gold-deep,#A07840);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:4px 10px;border-radius:10px;cursor:pointer;font-weight:500;transition:background .15s,border-color .15s}
.vx-prep-refresh:hover{background:rgba(161,134,80,.08);border-color:rgba(161,134,80,.6)}
.vx-prep-listen + .vx-prep-refresh{margin-left:0}
@keyframes vx-pulse{0%,100%{box-shadow:0 0 0 0 rgba(185,64,64,.4)}50%{box-shadow:0 0 0 6px rgba(185,64,64,0)}}
.vx-prep-title{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:clamp(1.6rem,3vw,2.1rem);font-weight:500;color:var(--green,#2C4A3E);line-height:1.15;margin:0 0 12px;letter-spacing:-.005em}
.vx-prep-intro{font-family:var(--ff-b);font-size:1rem;line-height:1.65;color:var(--text-mid);margin:0;max-width:680px}
.vx-prep-video{margin:0 0 28px;background:#000;border-radius:14px;overflow:hidden;box-shadow:0 4px 24px rgba(44,74,62,.12)}
.vx-prep-video video{display:block;width:100%}
.vx-prep-video-meta{padding:10px 16px;background:#1a2825;color:rgba(255,255,255,.7);font-family:var(--ff-m);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase}
.vx-prep-sections{margin:0 0 28px;display:flex;flex-direction:column;gap:22px}
.vx-prep-section{padding:18px 22px;background:white;border:1px solid rgba(44,74,62,.08);border-radius:12px}
.vx-prep-section-heading{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.2rem;font-style:italic;color:var(--green,#2C4A3E);margin:0 0 10px;font-weight:500;line-height:1.3}
.vx-prep-section-body{font-family:var(--ff-b);font-size:.95rem;line-height:1.65;color:var(--text-mid)}
.vx-prep-section-body p{margin:0 0 10px}
.vx-prep-section-body p:last-child{margin-bottom:0}
.vx-prep-mustask{margin:0 0 28px;padding:24px 26px;background:rgba(200,169,110,.06);border:1px solid rgba(200,169,110,.25);border-left:3px solid var(--gold-deep,#A07840);border-radius:0 12px 12px 0}
.vx-prep-mustask-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);font-weight:500;margin-bottom:14px}
.vx-prep-mustask-list{margin:0;padding-left:22px;counter-reset:mustask}
.vx-prep-mustask-item{margin-bottom:16px;padding-left:6px;list-style-position:outside}
.vx-prep-mustask-item:last-child{margin-bottom:0}
.vx-prep-mustask-q{font-family:var(--ff-b);font-size:.95rem;line-height:1.45;color:var(--ink);font-weight:500;margin-bottom:5px}
.vx-prep-mustask-why{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:.92rem;font-style:italic;line-height:1.55;color:var(--text-mid)}
.vx-prep-cta{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding-top:12px;border-top:1px solid var(--border-g)}
@media (max-width:768px){
  .vx-prep-section{padding:14px 16px}
  .vx-prep-mustask{padding:18px 18px 18px 22px}
  .vx-prep-cta{justify-content:stretch;flex-direction:column}
  .vx-prep-cta button{width:100%}
}

/* 2026-05-22 v3 — Prep card styles (gap-driven rehearsal). The
   verdeaux-interview.js renderer outputs .vdx-r-* elements; canonical
   styles live here in the SPA shell so they don't depend on the
   interview module's injectStyles path. */
.vdx-rehearsal-host{margin:8px 0 22px;display:flex;flex-direction:column;gap:14px}
/* 2026-05-25 — Pre-Call Readiness Check styles. Planner-grade pre-call
   checklist that renders above the 3 question cards. Sage-toned card so
   it reads as the editorial "preamble" before the tactical question
   scripts. Cormorant italic title + DM Mono eyebrow + balanced 2-column
   list (collapses to 1 column on narrow viewports). */
.vx-readiness-check{background:rgba(90,140,122,.06);border:1px solid rgba(90,140,122,.22);border-left:3px solid var(--green-lt,#5A8C7A);border-radius:12px;padding:22px 24px;margin-bottom:6px}
.vx-readiness-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.18em;text-transform:uppercase;color:var(--green-mid,#3D6355);margin-bottom:8px}
.vx-readiness-title{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-size:1.25rem;font-weight:400;color:var(--green,#2C4A3E);margin:0 0 16px;line-height:1.35;font-style:italic}
.vx-readiness-title em{color:var(--gold,#C8A96E);font-style:italic}
.vx-readiness-list{list-style:none;padding:0;margin:0;display:grid;grid-template-columns:1fr;gap:10px}
@media (min-width:560px){.vx-readiness-list{grid-template-columns:repeat(2,1fr);gap:12px 18px}}
.vx-readiness-item{padding:10px 0 10px 14px;border-left:2px solid rgba(200,169,110,.36)}
.vx-readiness-label{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;color:var(--charcoal,#1C1C1C);letter-spacing:.01em;margin-bottom:3px}
.vx-readiness-guidance{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;line-height:1.55;color:var(--text-mid,#4A4A4A)}
/* 2026-08-05 (Gen8) — an item the engine could answer for the couple. The
   answer leads in the green the rest of the product uses for settled facts,
   and the detail underneath carries the basis or the caveat. A number without
   its working is what this product exists not to do, so the detail is never
   dropped — only made quieter. The gold left-rule becomes green: gold is the
   colour of "decide this", green of "decided". */
.vx-readiness-item.is-answered{border-left-color:var(--green-lt,#5A8C7A)}
.vx-readiness-answer{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.95rem;font-weight:500;line-height:1.4;color:var(--green,#2C4A3E)}
.vx-readiness-detail{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;line-height:1.5;color:var(--text-muted,#88928d);margin-top:3px}
.vx-readiness-check.is-prefilled{background:rgba(90,140,122,.09)}

/* 2026-08-05 (Gen8) — the transportation worksheet: a timeline a couple reads
   down the phone, and prints as a one-page handout.

   NOT A TABLE, deliberately. A table forces horizontal scroll at 390px, and a
   vendor handout that scrolls sideways is one a couple will not use. Each leg
   is a small block: time + route + riders + estimate on one line, vehicles and
   addresses beneath. Reads top-to-bottom on a phone, prints as rows on paper. */
.vx-tw{margin:0 0 6px}
.vx-tw-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:14px}
.vx-tw-total{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-size:1.5rem;color:var(--green,#2C4A3E)}
.vx-tw-day{margin:0 0 18px}
.vx-tw-daylabel{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 8px;
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--green-mid,#3D6355);font-weight:500;padding-bottom:5px;border-bottom:1px solid rgba(44,74,62,.12)}
.vx-tw-daysub{color:var(--text-muted,#88928d);letter-spacing:.04em}
.vx-tw-rows{list-style:none;margin:0;padding:0}
.vx-tw-row{padding:10px 0 11px;border-bottom:1px solid rgba(44,74,62,.06)}
.vx-tw-row:last-child{border-bottom:none}
/* A GRID, not a wrapping flex row. As flex, where the estimate landed depended
   on how long the leg's question happened to be: most rows put the riders chip
   and the price together on line two, but a short one ("Westin Edina → MSP
   Airport") pulled the chip up beside the title and pushed the price onto a
   line by itself. Same component, two different shapes, decided by text length.
   The grid pins the price to the top-right of every row and the chip below it,
   which is also Stephen's spec: question and estimate on row one. */
.vx-tw-top{display:grid;grid-template-columns:1fr auto;column-gap:12px;align-items:baseline}
.vx-tw-lead{grid-column:1;grid-row:1;display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px}
.vx-tw-time{font-family:var(--ff-m,'DM Mono',monospace);font-size:.66rem;color:var(--gold-deep,#A07840);
  letter-spacing:.04em;flex:0 0 auto}
.vx-tw-q{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;font-weight:500;
  color:var(--ink,#2C2C2C);flex:1 1 auto;min-width:0}
/* Riders is the control, not a label — it is the number that swings the bill,
   so it reads as editable. Gold once she has typed one: her number, not ours. */
.vx-tw-qty{font-family:var(--ff-m,'DM Mono',monospace);font-size:.66rem;color:var(--text-mid,#4A4A4A);
  background:rgba(44,74,62,.05);border:1px solid rgba(44,74,62,.12);border-radius:20px;padding:2px 8px;
  grid-column:1;grid-row:2;justify-self:start;margin-top:5px}
.vx-tw-qty.is-user{background:rgba(200,169,110,.12);border-color:rgba(200,169,110,.38);color:var(--gold-deep,#A07840)}
.vx-tw-was{display:block;font-size:.58rem;opacity:.72;letter-spacing:.02em}
.vx-tw-est{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;font-weight:500;
  color:var(--green,#2C4A3E);grid-column:2;grid-row:1;justify-self:end}
.vx-tw-veh{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted,#88928d);margin-top:2px}
.vx-tw-addr{display:flex;flex-wrap:wrap;align-items:baseline;gap:3px 6px;margin-top:4px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted,#88928d);line-height:1.45}
.vx-tw-arrow{color:var(--gold,#C8A96E)}
/* A missing address is SAID, never left blank — a handout with a silent hole is
   worse than one that admits it. Dashed, not red: this is a gap to fill, not a
   failure. */
.vx-tw-a.is-missing{color:var(--gold-deep,#A07840);border-bottom:1px dashed rgba(200,169,110,.55)}
/* What cutting a run would really save, shown only when it differs from the
   row's own figure. Quiet — it is a useful fact, not a warning. */
.vx-tw-drop{margin:4px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;
  line-height:1.5;color:var(--gold-deep,#A07840)}
.vx-tw-warn{margin:8px 0 2px;padding:9px 11px;background:rgba(200,169,110,.09);
  border-left:2px solid var(--gold,#C8A96E);border-radius:0 8px 8px 0}
.vx-tw-warn strong{display:block;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;
  font-weight:500;color:var(--ink,#2C2C2C);line-height:1.45}
.vx-tw-warn ul{margin:5px 0 0;padding-left:16px}
.vx-tw-warn li{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-mid,#4A4A4A);
  line-height:1.45;margin-bottom:2px}
.vx-tw-note{margin:12px 0 0;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-style:italic;
  font-size:.9rem;color:var(--text-mid,#4A4A4A)}
.vx-tw-gaps{margin:6px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;color:var(--gold-deep,#A07840)}
@media (min-width:620px){
  .vx-tw-addr{font-size:.75rem}
  .vx-tw-q{font-size:.9rem}
}
/* ── The transportation workspace (Gen8) ─────────────────────────────────
   "Plan the day" — the couple's own plan of the weekend, which has to exist
   before any operator can quote it. Mobile-first and deliberately quiet: the
   couple reading this is already overwhelmed, so a saved edit dims the card
   rather than throwing up a spinner, and nothing here is ever styled as a
   warning. */
.vx-tp{position:relative;transition:opacity .18s ease}
.vx-tp.is-saving{opacity:.55;pointer-events:none}
/* WHY THIS SHAPE — plain body text, not italic serif. Stephen 2026-08-08: "the
   italic is hard to read on a small table so that style is not preferred."
   It was also the largest text on the tab at 1rem, sitting directly above a
   sheet whose biggest element is 13.8px, so it read as a headline rather than
   as the explanation it is. Sized to land just under a row title. */
.vx-tp-why{margin:0 0 16px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.85rem;line-height:1.6;color:var(--text-mid,#4A4A4A)}
.vx-tp-empty{margin:20px 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;
  line-height:1.6;color:var(--text-muted,#88928d)}
.vx-tp-err{margin:0 0 12px;padding:9px 13px;background:rgba(200,169,110,.10);
  border-left:2px solid var(--gold-deep,#A07840);border-radius:0 6px 6px 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;color:var(--text-mid,#4A4A4A)}
/* A tap target, not a hint. Editable values read as editable on a phone —
   44px min height is the difference between a couple correcting an address in
   a parking lot and a couple giving up. */
.vx-tw-qty,.vx-tw-a{cursor:pointer}
.vx-tw-qty:hover,.vx-tw-a:hover{color:var(--gold-deep,#A07840)}
.vx-tp-input{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:16px;/* 16px: iOS zooms below it */
  padding:7px 9px;min-height:38px;width:100%;max-width:340px;
  border:1px solid var(--gold,#C8A96E);border-radius:6px;background:#fff;color:var(--text,#1C1C1C)}
/* ── ⚑ AN INLINE EDITOR THAT LOOKS LIKE WHAT IT REPLACES ─────────────────
   Stephen 2026-08-20: "the title box font is different & bigger in edit mode."
   It is — `.vx-tp-input` is 16px, and the comment above says exactly why: below
   16px iOS zooms the whole page when a field takes focus. That is a real bug on
   a phone and I am not trading it away to tidy a desktop.

   ⚑ SO IT IS SPLIT ON THE POINTER, NOT ON THE SCREEN. A fine pointer is a mouse
   or a trackpad, and no such browser zooms on focus — there the editor inherits
   the row's own type and the title stops changing size the moment you click it.
   Touch keeps 16px and keeps the protection. Do not "simplify" this to one rule;
   the two cases genuinely differ. */
@media (hover: hover) and (pointer: fine) {
  .vx-tp-input--inherit{font:inherit;font-size:inherit;line-height:inherit;
    min-height:0;padding:2px 6px;max-width:none;
    border-color:var(--gold-deep,#A07840)}
}
/* The day sits beside the name, sized to a date and no wider. */
.vx-tp-input--day{width:auto;max-width:9.5rem;margin-left:6px}
@media (hover: hover) and (pointer: fine) {
  .vx-tp-input--day{font:inherit;font-size:inherit;min-height:0;padding:2px 6px}
}
.vx-tp-btn{min-height:44px;padding:11px 20px;border-radius:100px;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:500;
  background:#fff;color:var(--green,#2C4A3E);border:1px solid rgba(44,74,62,.28)}
.vx-tp-btn.is-primary{background:var(--green,#2C4A3E);color:#fff;border-color:var(--green,#2C4A3E)}
.vx-tp-btn:hover{border-color:var(--gold,#C8A96E)}
/* Says the quiet part out loud. The couple should know WHY the operator sheet
   looks thinner than her worksheet — it is a deliberate withholding, not an
   omission. */
/* 2026-08-09 — "Before you call an operator". Three facts the engine always
   computed and never showed. Deliberately quiet: this is a briefing, not an
   alarm, and it sits BELOW the sheet because the sheet stays money-free. */
.vx-tp-precall{margin:14px 0 4px;padding:14px 16px;border-radius:10px;
  background:rgba(58,107,89,.045);border:1px solid rgba(58,107,89,.16)}
.vx-tp-precall-h{margin:0 0 8px;font-family:'Cormorant Garamond',serif;
  font-size:1.02rem;font-weight:500;color:var(--green,#2C4A3E)}
.vx-tp-precall-list{margin:0;padding-left:18px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;line-height:1.6;
  color:var(--text-mid,#4A4A4A)}
.vx-tp-precall-list li{margin-bottom:7px}
.vx-tp-precall-list li:last-child{margin-bottom:0}
.vx-tp-precall-list strong{color:var(--green,#2C4A3E);font-weight:600}
.vx-tp-precall-list em{font-style:normal;color:var(--gold-deep,#A07840)}
.vx-tp-precall-note{margin:9px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.74rem;line-height:1.5;color:var(--text-muted,#88928d)}
.vx-tp-privacy{margin:9px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.75rem;
  line-height:1.55;color:var(--text-muted,#88928d)}

/* ── The three day maps, and the layer ───────────────────────────────────
   "The input is a list to prep but the output is the map." Tabs first because
   the day is the thing a couple thinks in; the layer second because who is
   riding is the question they have not thought of yet. */
.vx-tp-map{margin:0 0 18px}
/* THE CORRIDOR LOOK. Stephen 2026-08-06: "I really want the corridor look for
   the transportation day menus — big and clean on mobile." These are the hotel
   corridor demo's tier cards, matched rule for rule: the money takes the gold
   mono slot $/$$/$$$ occupies there, the day is the bold label, the ride count
   is the hint. flex:1 1 0 with a 96px floor puts three across a phone without
   any horizontal scroll — a day you have to swipe to find is a day nobody
   plans. */
.vx-tp-daytabs{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 12px}
.vx-tp-daytab{flex:1 1 0;min-width:96px;cursor:pointer;text-align:left;transition:.16s;
  border:1px solid rgba(44,74,62,.16);background:#fff;border-radius:12px;padding:12px 14px;
  font-family:var(--ff-b,'DM Sans',sans-serif);display:block}
.vx-tp-daytab:hover{border-color:var(--gold,#C8A96E)}
.vx-tp-daytab-sym{display:block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.9rem;
  color:var(--gold-deep,#A07840);font-weight:500;letter-spacing:.04em}
.vx-tp-daytab-l{display:block;font-size:13px;font-weight:600;color:var(--text-dark,#2B2B2B);margin-top:2px}
.vx-tp-daytab-m{display:block;font-size:11px;color:var(--text-mid,#4A4A4A);margin-top:1px}
.vx-tp-daytab.is-on{background:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E)}
.vx-tp-daytab.is-on .vx-tp-daytab-sym{color:var(--gold,#C8A96E)}
.vx-tp-daytab.is-on .vx-tp-daytab-l,
.vx-tp-daytab.is-on .vx-tp-daytab-m{color:var(--cream,#FAF7F2)}
/* An empty day is quieter than a full one, but it is never absent and never
   greyed to the point of looking disabled — it is an invitation, not a gap. */
.vx-tp-daytab.is-empty .vx-tp-daytab-sym{color:rgba(160,120,64,.45)}
.vx-tp-daytab.is-empty .vx-tp-daytab-l{color:var(--text-mid,#4A4A4A)}
.vx-tp-daytab.is-on.is-empty .vx-tp-daytab-sym{color:rgba(200,169,110,.7)}

/* One control: which day. The Agenda/Map toggle that briefly lived here was
   duplicating the guide's own Map tab, so it is gone along with its pane
   classes — the plan and the picture now live one tab apart. */
.vx-tp-nav{margin:0 0 12px}
.vx-tw-day.is-off{display:none}

/* The empty day. No red, no warning glyph — the next action, not a problem. */
.vx-tp-emptyday{margin:0 0 18px;padding:18px 18px 20px;border-radius:12px;
  background:rgba(44,74,62,.03);border:1px dashed rgba(44,74,62,.18)}
.vx-tp-emptyday-l{margin:0 0 6px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.92rem;color:var(--text-dark,#2B2B2B)}
.vx-tp-emptyday-h{margin:0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;
  line-height:1.55;color:var(--text-muted,#88928d)}

/* 2026-08-07 — PLAN THE WEEKEND: COLLAPSIBLE ACTIVITY BLOCKS.

   Stephen, with the draft manifest in hand: "a four row block that is
   collapsable to the title row but expands to show a to, from and group and
   the expected hours of the activity ... If the Planning tab is too
   complicated, no user will try this feature."

   So the default state is CLOSED. A couple sees a short list of the things
   happening that day and opens only what they want to argue with. Four rows
   when open, and only four — no price (that is the Budget tab's) and no
   vehicle (that is the operator's to propose on the manifest). */
.vx-th{margin:0 0 6px}
.vx-th-title{margin:0;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-size:1.5rem;color:var(--green,#2C4A3E)}
.vx-th-lede{margin:6px 0 20px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;
  line-height:1.55;color:var(--text-muted,#88928d)}
.vx-th-day{margin:0 0 22px}
/* 14px, the top of his three-step scale — the day is the biggest thing on the
   page because it is what a couple orients by. */
.vx-th-dayhead{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 9px;
  font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-day,.875rem);letter-spacing:.1em;text-transform:uppercase;
  color:var(--green,#2C4A3E);font-weight:600;padding-bottom:5px;
  border-bottom:1px solid rgba(44,74,62,.14)}
.vx-th-daydate{color:var(--text-muted,#88928d);letter-spacing:.03em;text-transform:none;font-size:var(--fs-trip,.75rem)}

/* THE BLOCK. Closed it is one tappable row; open it is that row plus four. */
/* THE GROUP LAYER. Who rides decides which vehicle, so this is the level an
   operator quotes at — and at twelve-plus activities it is also the only thing
   standing between a wedding day and a wall. A thin bar, not a card: three
   levels of nesting only works if the middle one is nearly free. */
/* THE GROUP IS THE CARD, and the activities are rows inside it. Stephen,
   looking at the first cut: "the group titles would look better if they were
   like the blocks are and the blocks should look like the headers."

   He is describing an inverted hierarchy, and it was. The child carried more
   visual weight than its parent — three bordered white cards stacked under a
   thin grey rule read as three separate things rather than as one group with
   three members. Putting the container treatment on the container is what
   makes the nesting legible, and it removes a border per activity while it is
   at it. */
.vx-th-group{margin:0 0 10px;border:1px solid rgba(44,74,62,.13);border-radius:11px;
  background:#fff;overflow:hidden}
.vx-th-grouphead{display:flex;align-items:center;gap:6px;padding:6px 8px 6px 6px;
  min-height:48px;background:rgba(44,74,62,.035);
  border-bottom:1px solid rgba(44,74,62,.09)}
.vx-th-grouptoggle{display:flex;align-items:center;gap:9px;flex:1 1 auto;min-width:0;
  padding:8px;background:none;border:0;cursor:pointer;text-align:left;font:inherit;border-radius:8px}
.vx-th-grouptoggle:hover{background:rgba(44,74,62,.05)}
.vx-th-groupmove{display:flex;gap:2px;flex:0 0 auto}
.vx-th-gmove{background:none;border:1px solid rgba(44,74,62,.14);border-radius:6px;cursor:pointer;
  width:26px;height:26px;line-height:1;font-size:.72rem;color:var(--text-muted,#88928d);padding:0}
.vx-th-gmove:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
.vx-th-groupname{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;font-weight:600;
  color:var(--green,#2C4A3E)}
.vx-th-groupcount{font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;
  color:var(--gold-deep,#A07840)}
.vx-th-groupn{margin-left:auto;font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;
  letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-th-groupbody{padding:0}
.vx-th-group.is-shut .vx-th-grouphead{border-bottom-color:transparent;background:none}
.vx-th-group:not(.is-shut) .vx-th-caret{transform:rotate(90deg);color:var(--gold,#C8A96E);background:rgba(200,169,110,.12)}

/* An activity is now a ROW in its group's card — no border of its own, no
   second background, just a rule between it and the next. */
.vx-th-block{margin:0;border:0;border-top:1px solid rgba(44,74,62,.07);border-radius:0;
  background:transparent;overflow:hidden}
.vx-th-block:first-child{border-top:0}
.vx-th-blockhead{display:flex;align-items:center;gap:8px;padding:4px 8px 4px 4px;min-height:46px}
.vx-th-blockhead.is-static{padding:10px 12px}
/* The name is the tap target; hours and the trashcan sit outside it so they
   are independently reachable without opening the block. */
.vx-th-blocktoggle .vx-th-caret{width:20px;height:20px;font-size:1rem;background:none}
.vx-th-blocktoggle{display:flex;align-items:center;gap:9px;flex:1 1 auto;min-width:0;
  padding:8px;background:none;border:0;cursor:pointer;text-align:left;font:inherit;border-radius:8px}
.vx-th-blocktoggle:hover .vx-th-blockname{color:var(--gold-deep,#A07840)}
/* HOURS, NOT A START TIME. Duration is a real requirement an operator quotes
   against; a clock time on an activity we proposed is invented. Editable in
   place, so correcting it never costs a tap to open the block. */
.vx-th-blockhours{flex:0 0 auto;cursor:pointer;font-family:var(--ff-m,'DM Mono',monospace);
  font-size:.68rem;letter-spacing:.03em;color:var(--green,#2C4A3E);
  border-bottom:1px dotted rgba(44,74,62,.32);white-space:nowrap}
.vx-th-blockhours:hover{color:var(--gold-deep,#A07840)}
.vx-th-blockhours.is-missing{color:var(--gold-deep,#A07840);border-bottom-style:dashed}
.vx-th-skip{flex:0 0 auto;background:none;border:none;cursor:pointer;color:var(--text-muted,#88928d);
  font-size:.95rem;line-height:1;padding:6px;border-radius:6px}
.vx-th-skip:hover{color:var(--rose,#C97B6A);background:rgba(185,64,64,.06)}
/* Skipped stays on the sheet, greyed, with its way back — never deleted. It is
   also the "do not fund this" instruction, so it has to be visible. */
.vx-th-block.is-skipped{background:rgba(44,74,62,.02)}
.vx-th-block.is-skipped .vx-th-blockname{color:var(--text-muted,#88928d);
  text-decoration:line-through;text-decoration-color:rgba(44,74,62,.3)}
.vx-th-skipnote{flex:1 1 auto;font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-th-undo{flex:0 0 auto;background:none;border:none;padding:4px 6px;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;color:var(--green,#2C4A3E);
  text-decoration:underline;border-radius:6px}
.vx-th-undo:hover{color:var(--gold-deep,#A07840)}
/* The zero-saving case, said out loud. A couple who skips something and sees
   the total hold still needs the reason, or they stop believing the number. */
.vx-th-savednote{margin:0;padding:0 12px 11px 12px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.74rem;line-height:1.5;color:var(--text-muted,#88928d)}
/* Rename in place. The catalogue label is ours; the name is theirs. */
.vx-th-rename{width:100%;padding:5px 8px;min-height:34px;border-radius:7px;
  border:1px solid rgba(44,74,62,.18);background:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:600;
  color:var(--ink,#2C2C2C)}
.vx-th-rename:focus{outline:none;border-color:var(--gold,#C8A96E)}
/* Reorder and remove live INSIDE the open block — off the title line, where a
   thumb reaching for the header was going to hit them. */
.vx-th-blockactions{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:10px;
  padding-top:9px;border-top:1px solid rgba(44,74,62,.07)}
.vx-th-move,.vx-th-remove{background:none;cursor:pointer;padding:6px 11px;min-height:34px;
  border-radius:100px;border:1px solid rgba(44,74,62,.16);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-mid,#4A4A4A)}
.vx-th-move:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
.vx-th-remove{margin-left:auto;color:var(--text-muted,#88928d)}
.vx-th-remove:hover{border-color:rgba(185,64,64,.4);color:var(--rose,#C97B6A)}
.vx-th-delete{flex:0 0 auto;background:none;border:none;padding:4px 6px;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;color:var(--text-muted,#88928d);
  text-decoration:underline;border-radius:6px}
.vx-th-delete:hover{color:var(--rose,#C97B6A)}
/* Borrowed wholesale from the budget page, whose own comment records why: the
   thin character it replaced "read as decoration". Mine was that character. */
.vx-th-caret{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;
  flex:0 0 auto;font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.25rem;font-style:italic;
  line-height:1;color:var(--green,#2C4A3E);background:rgba(44,74,62,.06);border-radius:50%;
  transition:transform .22s cubic-bezier(.22,.61,.36,1),background .15s}
.vx-th-grouptoggle:hover .vx-th-caret{background:rgba(44,74,62,.12)}

/* THE POWER LINE. Stephen's own budget pattern — "behind a simple line but
   real power if needed". A quiet row at the foot of an open group; the couple
   who never opens it pays nothing for its existence. */
.vx-th-grouptune{border-top:1px solid rgba(44,74,62,.07)}
/* Save to budget — the one control on this sheet that moves money, so it reads
   as a deliberate act rather than another inline edit. No amount on its face:
   "no $ on the plan" holds, and the figure lands in the confirmation. */
.vx-th-tobudget{margin:18px 0 4px;padding:14px 16px;border:1px solid rgba(200,169,110,.35);
  border-radius:12px;background:rgba(200,169,110,.06);display:flex;flex-wrap:wrap;
  align-items:center;gap:12px;justify-content:space-between}
.vx-th-tobudget.is-done{border-color:rgba(44,74,62,.3);background:rgba(44,74,62,.04)}
.vx-th-tobudget-line{margin:0;flex:1 1 220px;min-width:0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;line-height:1.5;color:var(--text-mid,#5b5b52)}
.vx-th-tobudget-btn{flex:0 0 auto;background:var(--green,#2C4A3E);color:#FAF7F2;border:none;
  border-radius:40px;padding:10px 20px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.85rem;font-weight:600;cursor:pointer;min-height:44px}
.vx-th-tobudget-btn:hover{background:var(--green-2,#3d6a58)}
.vx-th-tobudget-btn:disabled{opacity:.55;cursor:default}
@media (max-width:520px){.vx-th-tobudget-btn{width:100%}}
.vx-th-gtune{display:block;width:100%;padding:9px 14px;min-height:38px;text-align:left;
  background:none;border:0;cursor:pointer;font-family:var(--ff-m,'DM Mono',monospace);
  font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-th-gtune:hover{background:rgba(44,74,62,.03);color:var(--gold-deep,#A07840)}
/* Open, the same line is the way out — so it stops being a muted hint and
   reads as a control. It stays exactly where the finger already is. */
.vx-th-gtune.is-open{color:var(--green,#2C4A3E);font-weight:600;
  background:rgba(44,74,62,.04)}
.vx-th-tuneform{padding:4px 14px 12px;border-top:1px solid rgba(44,74,62,.07);
  background:rgba(44,74,62,.02)}
.vx-th-tunenote{margin:8px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;
  line-height:1.5;color:var(--text-muted,#88928d)}
.vx-th-blockname{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;font-weight:600;
  color:var(--ink,#2C2C2C);flex:1 1 auto;min-width:0}
.vx-th-blocktime{font-family:var(--ff-m,'DM Mono',monospace);font-size:.66rem;letter-spacing:.04em;
  color:var(--gold-deep,#A07840);flex:0 0 auto}
.vx-th-block.is-open{background:rgba(44,74,62,.02)}
.vx-th-blockbody{padding:2px 13px 12px}

/* FOUR ROWS. Label left, value right — the same shape four times, so the eye
   learns it once and stops reading the labels. */
.vx-th-row{display:flex;align-items:baseline;gap:12px;padding:7px 0;
  border-top:1px solid rgba(44,74,62,.07)}
.vx-th-rowlabel{flex:0 0 58px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-th-rowvalue{flex:1 1 auto;min-width:0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.84rem;color:var(--ink,#2C2C2C)}
/* Locations are PICKED, never typed — the options come from the server, so a
   couple can only choose a place this wedding actually has. */
.vx-th-pick{width:100%;padding:5px 8px;min-height:34px;border-radius:7px;cursor:pointer;
  border:1px solid rgba(44,74,62,.18);background:#fff;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.84rem;color:var(--ink,#2C2C2C)}
.vx-th-pick:hover{border-color:var(--gold,#C8A96E)}
.vx-th-group{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem}
/* The two editable numbers. Riders re-solves the fleet; hours decides whether
   the vehicle waits through the activity or is released and comes back. */
.vx-th-qty{cursor:pointer;border-bottom:1px dotted rgba(44,74,62,.35);
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.8rem;color:var(--green,#2C4A3E)}
.vx-th-qty:hover{color:var(--gold-deep,#A07840)}

/* Adding is a first-class action sitting with the day it belongs to, not a
   menu item a couple has to go hunting for. */
/* THE ADD FORM. Same facts as a block, in the same order, so adding one is
   filling in a block rather than learning a new screen. */
.vx-th-addform{margin:8px 0 0;padding:12px 13px;border-radius:10px;background:#fff;
  border:1px solid rgba(44,74,62,.2)}
.vx-th-addname{width:100%;padding:8px 10px;margin-bottom:4px;border-radius:8px;
  border:1px solid rgba(44,74,62,.18);font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.88rem;font-weight:600;color:var(--ink,#2C2C2C)}
.vx-th-addhrs{width:88px;padding:5px 8px;min-height:34px;border-radius:7px;
  border:1px solid rgba(44,74,62,.18);font-family:var(--ff-m,'DM Mono',monospace);
  font-size:.8rem;color:var(--ink,#2C2C2C)}
.vx-th-addactions{display:flex;align-items:center;gap:10px;margin-top:10px}
.vx-th-addsave{padding:8px 18px;min-height:38px;border-radius:100px;cursor:pointer;
  background:var(--green,#2C4A3E);color:#FAF7F2;border:none;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;font-weight:600}
.vx-th-addcancel{background:none;border:none;cursor:pointer;padding:6px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;color:var(--text-muted,#88928d)}

/* THE RUNNING TOTAL. Not a reversal of "no money on the plan" — that rule is
   about per-movement prices, which mislead on a shared booking. One total is
   the consequence of the couple's own choices, and hours sits beside it
   because it explains it: the engine bills to the operator's minimum, so
   dropping a movement sometimes does not lower the number. */
.vx-th-summary{display:flex;gap:10px;margin:0 0 18px}
.vx-th-stat{flex:1 1 0;min-width:0;padding:11px 13px;border-radius:10px;
  background:rgba(44,74,62,.04);border:1px solid rgba(44,74,62,.09)}
.vx-th-statlabel{display:block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;
  letter-spacing:.11em;text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-th-statvalue{display:block;margin-top:3px;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-size:1.35rem;line-height:1.1;color:var(--green,#2C4A3E)}
.vx-th-stathint{display:block;margin-top:3px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.66rem;line-height:1.35;color:var(--text-muted,#88928d)}

/* Adding belongs to the DAY, so it sits outside the group cards rather than
   reading as a member of whichever group happens to be last. */
.vx-th-add{display:block;width:100%;margin:8px 0 0;padding:10px;min-height:40px;
  border-radius:9px;cursor:pointer;background:none;border:1px dashed rgba(44,74,62,.24);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;color:var(--text-muted,#88928d)}
.vx-th-add:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
/* The in-group adder is quieter than the day's — it is a row at the end of a
   list, not a second call to action competing with it. */
.vx-th-groupadd{border-top:1px solid rgba(44,74,62,.07)}
.vx-th-add.is-ingroup{margin:0;border:0;border-radius:0;padding:11px 14px;text-align:left;
  min-height:42px;font-size:.75rem}
.vx-th-add.is-ingroup:hover{background:rgba(44,74,62,.03);color:var(--gold-deep,#A07840)}
.vx-th-groupbody .vx-th-addform{margin:0;border:0;border-radius:0;
  border-top:1px solid rgba(44,74,62,.07)}

/* The prompt's question, kept as the answer to "why is this on my sheet". */
/* The prompt's own question, on the By-group view. Same change and the same
   reason — italic serif at body size is the hardest thing on the page to read
   on a phone. It stays quiet through colour instead. */
.vx-th-why{margin:0;padding:9px 13px 11px;border-top:1px solid rgba(44,74,62,.07);
  font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.78rem;line-height:1.55;color:var(--text-muted,#88928d)}
.vx-th-keep{margin-left:4px;padding:2px 10px;min-height:26px;border-radius:100px;cursor:pointer;
  background:#fff;border:1px solid rgba(44,74,62,.28);font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.7rem;font-weight:500;font-style:normal;color:var(--green,#2C4A3E);white-space:nowrap}
.vx-th-keep:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
/* A gap is the NEXT ACTION, never a warning. No red, no glyph, no count. */
.vx-th-gap{margin:8px 0 0;padding:9px 11px;border-radius:8px;background:rgba(200,169,110,.10);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.75rem;line-height:1.5;
  color:var(--text-mid,#4A4A4A)}

/* ── THE RUN SHEET ────────────────────────────────────────────────────────
   The Plan tab's primary view. One line per row, the include control first on
   every one of them, nothing behind a disclosure — the three-tap path to a
   single decision is what this replaces.

   Its own type is the SITE's, not the mockup's. Stephen's prototype loads
   Barlow and IBM Plex from Google; this uses DM Mono for the clock and DM Sans
   for the line, because the fallback metrics for those are measured and pinned
   and a new webfont would reflow fourteen pages to buy nothing. */
.vx-rs{margin:0 0 6px}
.vx-rs-head{margin:0 0 16px}
.vx-rs-assumed{margin:0 0 14px;padding:9px 11px;border-radius:8px;
  background:rgba(200,169,110,.10);font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.75rem;line-height:1.5;color:var(--text-mid,#4A4A4A)}

/* ── VERA ON HOW DEEP THE MARKET IS ─────────────────────────────────────
   Stephen asked for this "at the top of the page like we do on the Budget", so
   it reads as a quiet summary card rather than a widget: one tint, no border
   chrome, and the numbers carried by weight instead of by boxes.

   ⚑ IT SHIPPED WITH NO CSS AT ALL and every gate passed — the structure was
   right, the wiring was right, and it rendered as raw body text and a default
   browser button. Only looking at it caught that. Worth remembering that a
   green suite says nothing about whether a thing is presentable.

   ⚑ EVERY var() CARRIES A FALLBACK. An unresolved custom property does not
   fall back to the previous value, it makes the whole declaration `unset` —
   which is how a hover rule once emptied the active tab. */
.vx-rs-depth{margin:0 0 20px;padding:14px 16px;border-radius:10px;
  background:rgba(44,74,62,.045);
  font-family:var(--ff-b,'DM Sans',sans-serif)}
.vx-rs-depth.is-loading{background:rgba(44,74,62,.03)}
.vx-rs-depthlede{margin:0;font-size:.8rem;line-height:1.55;
  color:var(--text-mid,#4A4A4A)}
.vx-rs-depth.is-loading .vx-rs-depthlede{color:var(--text-muted,#88928d)}
.vx-rs-depthlede strong{font-weight:600;color:var(--green,#2C4A3E)}

/* The options, as a small table that stays legible when it wraps. Grid rather
   than flex so the money column lines up down the list — a stable money column
   is a decision made elsewhere in this file and it applies here too. */
.vx-rs-depthlist{list-style:none;margin:12px 0 0;padding:0;
  display:grid;gap:6px}
.vx-rs-depthrow{display:grid;grid-template-columns:minmax(96px,auto) 1fr auto;
  gap:4px 12px;align-items:baseline;
  font-size:.78rem;line-height:1.5;color:var(--text-mid,#4A4A4A)}
.vx-rs-depthveh{font-weight:600;color:var(--green,#2C4A3E)}
.vx-rs-depthn{min-width:0}
.vx-rs-depthn strong{font-weight:600;color:var(--green,#2C4A3E)}
.vx-rs-depthcost{font-family:var(--ff-m,'DM Mono',monospace);
  font-size:.76rem;color:var(--text-mid,#4A4A4A);text-align:right;
  font-variant-numeric:tabular-nums}
@media (max-width:560px){
  /* Two lines beat three squeezed columns on a phone: the vehicle and its
     price on ONE row, the count beneath.
     ⚑ PLACED EXPLICITLY, NOT LEFT TO AUTO-FLOW. Setting only the column count
     and spanning the middle cell gave THREE rows, not two — auto-placement put
     the vehicle in row 1, the full-width count in row 2, and pushed the price
     down to row 3 on its own. It looked deliberate and cost an extra line per
     option, which on a phone is the clutter this card is supposed to avoid. */
  .vx-rs-depthrow{grid-template-columns:1fr auto;row-gap:2px}
  .vx-rs-depthveh{grid-row:1;grid-column:1}
  .vx-rs-depthcost{grid-row:1;grid-column:2}
  .vx-rs-depthn{grid-row:2;grid-column:1 / -1;color:var(--text-muted,#88928d)}
}

/* The sentence that makes this a recommendation rather than statistics. */
.vx-rs-depthwhy{margin:12px 0 0;font-size:.8rem;line-height:1.55;
  color:var(--text-mid,#4A4A4A)}
.vx-rs-depthwhy strong{font-weight:600;color:var(--green,#2C4A3E)}
/* ⚑ THE CAVEAT IS THE CREDIBILITY, so it is quiet but never hidden — muted,
   not smaller than the eye can hold, and never behind a disclosure. */
.vx-rs-depthnote,.vx-rs-depthcaveat{margin:8px 0 0;font-size:.72rem;line-height:1.5;
  color:var(--text-muted,#88928d)}
.vx-rs-depthbtn{margin:10px 0 0;padding:7px 14px;min-height:32px;
  border:1px solid rgba(44,74,62,.22);border-radius:100px;cursor:pointer;
  background:#fff;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.74rem;font-weight:500;color:var(--green,#2C4A3E)}
.vx-rs-depthbtn:hover{background:rgba(44,74,62,.05)}
/* ⛑ The plans built with Vera, listed in the transportation journal above the rides (2026-09-15). */
.vx-tp-plans{margin:0 0 20px;padding:14px 16px;border-radius:10px;background:rgba(44,74,62,.045);
  font-family:var(--ff-b,'DM Sans',sans-serif)}
.vx-tp-plans .vx-tp-h{margin:0 0 4px}
.vx-tp-planlede{margin:0 0 10px;font-size:.8rem;line-height:1.55;color:var(--text-mid,#4A4A4A)}
.vx-tp-planlist{list-style:none;margin:0 0 6px;padding:0;display:grid;gap:6px}
.vx-tp-planrow{display:flex;flex-direction:column;justify-content:center;gap:2px;min-height:44px;padding:8px 12px;
  border:1px solid rgba(44,74,62,.16);border-radius:10px;background:#fff;text-decoration:none}
.vx-tp-planrow:hover{border-color:rgba(44,74,62,.35)}
.vx-tp-planrow:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
.vx-tp-planname{font-size:.9rem;font-weight:600;color:var(--green,#2C4A3E)}
.vx-tp-planmeta{font-size:.74rem;color:var(--text-muted,#88928d)}
.vx-tp-plannew{display:inline-flex;align-items:center;min-height:44px;font-size:.8rem;font-weight:600;
  color:var(--green,#2C4A3E);text-decoration:none}
/* The door to the evidence. A link-weight control, not a second primary
   button — the sentence above it is the point, and this is the "show me". */
.vx-rs-depthqr{display:inline-flex;align-items:center;min-height:44px;
  margin:6px 0 0;padding:0;border:0;background:none;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;font-weight:500;
  color:var(--green,#2C4A3E);text-decoration:underline;
  text-underline-offset:3px;text-decoration-color:rgba(44,74,62,.3)}
.vx-rs-depthqr:hover{text-decoration-color:var(--green,#2C4A3E)}

/* ── 10-MIN PREP, TRANSPORT: READINESS RATHER THAN A SCRIPT ─────────────
   Stephen 2026-08-17: the read-this/push-back pairs assume the call happens in
   a fixed order. These sections prepare a couple for a conversation they cannot
   choreograph instead. Quiet by construction — this page runs BEFORE the plan,
   so it must never look like a verdict on one. */
.vx-tp-sec{margin:18px 0 0;padding:16px 0 0;border-top:1px solid rgba(44,74,62,.10)}
.vx-tp-h{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.15rem;
  font-style:italic;color:var(--green,#2C4A3E);margin:0 0 8px;line-height:1.25}
.vx-tp-lede,.vx-tp-wait{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;
/* ⚑ WHERE THE WAIT TRADE STOPS PAYING. Quiet, under the lever it bounds — a
   limit on the trade, not a recommendation to take it. Lives here beside the
   panel's own type rather than in the .vx-plan-cards block: it renders in the
   fleet section, and plan-cards-validate rightly insists every rule in that
   block is scoped to a card. */
.vx-tp-waitcap{margin:2px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.72rem;line-height:1.35;color:var(--text-muted,#88928d)}
  line-height:1.55;color:var(--text-mid,#4A4A4A);margin:0 0 10px}
.vx-tp-wait{color:var(--text-muted,#88928d)}
/* ⚑ NEXT ACTIONS, NEVER A TALLY OF FAILURES. No red, no counts framed as
   problems — each line is a thing to go and do. */
.vx-tp-todo{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.vx-tp-todo li{position:relative;padding-left:18px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;line-height:1.5;color:var(--text-mid,#4A4A4A)}
.vx-tp-todo li::before{content:'';position:absolute;left:2px;top:7px;width:6px;height:6px;
  border-radius:50%;background:var(--gold,#C8A96E)}
.vx-tp-ok{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;line-height:1.55;
  color:var(--text-mid,#4A4A4A);margin:0}
.vx-tp-go{margin:12px 0 0;min-height:44px;padding:9px 16px;border-radius:100px;cursor:pointer;
  border:1px solid rgba(44,74,62,.22);background:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;
  color:var(--green,#2C4A3E)}
.vx-tp-go:hover{background:rgba(44,74,62,.05)}
/* What they will ask you. Each row is a question and the reason it is asked —
   the reason is what makes it prep rather than a form. */
.vx-tp-asks{list-style:none;margin:0;padding:0;display:grid;gap:12px}
.vx-tp-ask{display:grid;gap:2px}
.vx-tp-askq{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;font-weight:600;
  color:var(--green,#2C4A3E);line-height:1.4}
.vx-tp-askwhy{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;line-height:1.5;
  color:var(--text-mid,#4A4A4A)}

/* ── THE STOPS, AS A CONNECTED STACK ────────────────────────────────────
   Stephen's Apple Maps reference: stops joined by a line and read top to
   bottom, so a journey looks like a journey rather than two unrelated fields.

   ⚑ THE LINE IS DRAWN BETWEEN THE DOTS, NOT BEHIND THEM. A single border on
   the container would run past the last dot and read as "and then something
   else" — the opposite of what the last stop means. Each stop except the last
   draws the segment BELOW itself, so the line stops where the journey stops.

   The dots and the line are decoration: they carry no information the labels do
   not, so they are aria-hidden and the stack reads as its two selects. */
.vx-rs-stack{margin:0 0 10px}
/* ── ⚑ THREE LEVELS: EVENT, MOVEMENT, DETAIL ────────────────────────────
   Stephen 2026-08-19: "an event (like a Budget category), then a movement
   (line item), then the editable details are in line item expansion, so the
   Plan is really clean."

   ⚑ THE FACE CARRIES NO CONTROLS. Every earlier version put the place picker,
   the who and the time on the row itself, and at 390px that is four things
   competing for one line — which is what "our process is complicated" was
   about. A line item is a thing to READ; the tap is what makes it editable.

   Type scale is the page's own tokens, not new sizes. An unresolved var()
   DELETES the property rather than falling back, so every one carries a
   literal — the trick that once emptied the active tab on hover. */
/* The name is a control now, so it says so on hover — quietly, because it is
   also the thing you read most and a permanently underlined title is noise. */
/* Doors is a secondary time, and it must never be mistaken for the departure —
   the whole point of the theatre model is that one is sharp and one is not. */
.vx-qp-doors{font-size:var(--fs-eyebrow,.62rem);letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted,#8b8378)}
/* The measure-drives offer. Deliberately the same quiet card as the fleet-depth
   read and NOT a warning colour: it reports what we have not done yet, which is
   our business, not a fault in their weekend. */
.vx-rs-assumed{margin:12px 0 0;padding:12px 14px;border:1px solid var(--border,#eae5dd);
  border-radius:10px;background:var(--card,#fdfcfa)}
.vx-rs-assumedlede{margin:0;font-size:var(--fs-caption,.78rem);line-height:1.5;
  color:var(--muted,#8b8378)}
.vx-rs-assumedbtn{margin-top:9px;padding:6px 13px;border:1px solid var(--border,#eae5dd);
  border-radius:8px;background:none;cursor:pointer;font-size:var(--fs-eyebrow,.62rem);
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink,#2c2a26)}
.vx-rs-assumed.is-loading .vx-rs-assumedlede{opacity:.75}
.vx-rs-titleedit{cursor:text;border-radius:3px}
.vx-rs-titleedit:hover{background:var(--sage-tint,#eef1ea)}
.vx-rs-titleedit:focus-visible{outline:2px solid var(--sage,#7d8c6f);outline-offset:2px}
/* A later departure of the same loop: the same line, quieter, and with no
   caret — there is nothing under it, because the hire is edited once. */
.vx-rs-movewave{color:var(--muted,#8b8378);font-size:var(--fs-caption,.78rem)}
.vx-rs-move.is-wave .vx-rs-movename{color:var(--muted,#8b8378)}
/* ⚑ NO `display` HERE — the grid above governs every movehead, static or not.
   This said `display:flex`, and `.vx-rs-movehead.is-static` outranks
   `.vx-rs-movehead`, so the wave and derived rows NEVER used the clock track.
   Stephen's card showed it: 'Departure #1' with no clock at all and
   'Departure #2' with its time clipped at the card edge, because in a flex
   row `.vx-rs-cpair{width:100%}` becomes an enormous basis. Measured at 402pt
   with Playwright: the clock box was 216px wide against a 112px track. */
.vx-rs-movehead.is-static{align-items:center;gap:10px;width:100%;
  padding:9px 0;cursor:default}
/* ══ THE MOVEMENT LIST — the Budget line item, in the Plan ══════════════
   Stephen 2026-08-19: "I thought we were mirroring the Budget details expand
   for the detail entry under a line item?"

   So the pattern is taken from #section-budget .vxb-item-detail rather than
   invented beside it: the face is a quiet row, the expansion is a tinted card
   with the same 16/18 padding and 12px radius, its labels are the same bold
   NOT-uppercase mini-headings, and its controls are the same pill row. One
   pattern a couple learns once, on both cards.

   ⚑ AND ONE TYPE THROUGHOUT. Stephen: "I would like all of the trip fonts to
   be the same as the [lede] paragraph" — DM Sans .8rem/1.55, which is
   .vx-th-lede exactly. Every size in this block resolved to a different token
   before (.9rem name, .78rem select, .62rem uppercase label), and a panel with
   four type sizes in it reads as four different things. Literals on every
   token: an unresolved var() deletes the property outright rather than falling
   back. */
.vx-rs-moves{margin:2px 0 0}
.vx-rs-move + .vx-rs-move{border-top:1px dashed var(--border,#eae5dd)}
/* ⚑ NAME LEFT, CLOCKS RIGHT, GRIP LAST — the vendor-index row's shape.
   Stephen 2026-08-26: "move the time fields to the right side of the row and
   start with the index screenshot... the time and positioning grip would replace
   the 'booked' pill location."
   A grid rather than a flex row, because the clock has to occupy the SAME track
   on every line: with the times split either side of a flexible name, a long
   stop name pushed them apart and neither column read down the card.
   ⚑ THE TRACK IS THE LOCK, AND IT IS FIXED FOR THAT REASON. Stephen: "the |
   still being in the same location for all rows for that is a visual lock
   point." A fixed track plus the 1fr/7px/1fr grid inside it is what holds the
   pipe on one x — nothing about the times themselves does. 124px, up from 116
   when the clock went a rung larger: "10:00a | 10:20a" needs about 97px at
   .9rem DM Sans, and the rest is deliberate slack so the next size change is a
   decision rather than an overflow.
   ⚑ 124px -> 112px when the clock came back down a rung: "10:00a | 10:20a"
   needs about 84px at .78rem, and a track sized for type it no longer carries
   is just name column left on the floor. The pipe's lock is that every row
   shares ONE track, not that the track sits at any particular x. */
.vx-rs-movehead{display:grid;align-items:center;gap:10px;width:100%;
  grid-template-columns:minmax(0,1fr) var(--vx-clockw,112px) auto;
  padding:11px 0;background:none;border:0;text-align:left;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);color:inherit}

/* ⚑ THE PIPE HOLDS ONE COLUMN. Its own 3-track grid inside the fixed one, so
   the separator lands on the same x whether a time is four characters or six —
   and tabular figures keep 1 and 9 the same width, so 1:15p and 12:00a cannot
   drift against each other. */
.vx-rs-cpair{display:grid;grid-template-columns:1fr 7px 1fr;align-items:baseline;
  /* ⚑ FILLS ITS TRACK — `justify-self:end` shrank the clock to its CONTENT, so
     `1fr` resolved to the width of the text and the pipe moved 7.8px between a
     5-character time and a 6-character one. MEASURED across four rows before
     and after: spread 7.8px, then 0. */
  column-gap:2px;white-space:nowrap;width:100%;
  /* ⚑ THE CLOCK IS A VALUE, SO IT TRACKS THE NAME, NOT THE LABELS. It sized off
     --fs-stopdet, which is the eyebrow the detail box uses for "Leave by" and
     "From" — a label size for the second most important thing on the row. On
     the Budget card the vendor reads at the same size as the line item it sits
     against; this is that, and it holds at every breakpoint because both now
     move on one token.

     ⚑ AND IT IS THE ROW'S OWN FACE, NOT DM MONO. Stephen, looking at the row:
     "check the font of the time (it is different)" — it was, and I had made it
     so. The clock this replaced set NO font-family at all: it inherited DM Sans
     like everything else on the line. Mono was mine, it is the only thing on
     the row not in the body face, and it contradicts the rule he wrote over
     this very block on 2026-08-18 — "--ff-b DM Sans everything". Inherited
     again, so there is nothing here to disagree with the name beside it.

     `tabular-nums` stays and is doing the work it always did: it is what keeps
     a column of times from drifting, and the 1fr/7px/1fr grid holds the pipe
     regardless. */
  font-size:var(--fs-stop,.6875rem);
  font-variant-numeric:tabular-nums;line-height:1.4}
.vx-rs-cp-lv{text-align:right}
.vx-rs-cp-ar{text-align:left}
.vx-rs-cp-pipe{text-align:center;color:var(--text-muted,#88928d);opacity:.5}
/* ⚑ INK IS THEIRS, GREY IS OURS — his ruling: "user entered values are black
   font and calculated are gray." Both fields always carry a value, so the tint
   is the only thing saying which of the two is a commitment. */
.vx-rs-cp-lv,.vx-rs-cp-ar{color:var(--text-muted,#88928d);font-weight:400}
.vx-rs-cp-lv.is-typed,.vx-rs-cp-ar.is-typed{color:var(--charcoal,#33352f);font-weight:500}
.vx-rs-movename{flex:1 1 auto;min-width:0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stop,.6875rem);line-height:1.5;
  color:var(--charcoal,#33352f);
  /* ⚑ THE TWO-LINE CLAMP IS GONE, AND IT WAS WORSE THAN DEAD. Every one of its
     partners was already overridden by the one-line rule further down — his
     2026-08-19 "the titles are wrapping" — but `display` was not, because that
     rule never set one. So a `-webkit-box` inherited a `white-space:nowrap`
     from its replacement and the pair clipped the name mid-word with NO
     ellipsis: neither design, and the reason a truncated stop gave the couple
     no sign there was more to read. One rule owns this now. */
  overflow:hidden}
/* ⚑ THE GRIP, AND `touch-action:none` IS LOAD-BEARING. This list sits inside a
   scrolling panel inside a scrolling page; without it the browser claims the
   gesture for a scroll before the first pointermove arrives and the row never
   moves at all — on a phone, which is 80% of the traffic. It is scoped to the
   grip alone, so the page still scrolls everywhere else in the list. */
/* The staging glyph — see _vxStagingGlyph. Sits with the place names rather
   than at the end of the row, because it qualifies the leg, not the line. */
/* ⚑ THE ONE SIGNAL OUTSIDE THE DETAILS BOX. Gold, not red: a decision waiting
   to be made is not a fault, and "reduce stress, never alarm" is a charter. */
.vx-rs-flag{margin-left:7px;color:var(--gold-deep,#A07840);font-size:var(--fs-trip,.75rem)}
.vx-rs-gapnote{margin:0 0 8px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:var(--fs-stopdet,.625rem);line-height:1.5;color:var(--charcoal,#33352f)}
.vx-rs-gapadd,.vx-rs-gapno{display:inline-flex;align-items:center;border-radius:100px;
  padding:5px 12px;cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:var(--fs-stopdet,.625rem);letter-spacing:normal;text-transform:none}
.vx-rs-gapadd{border:1px solid var(--gold,#C8A96E);background:var(--white,#fff);
  color:var(--gold-deep,#A07840)}
.vx-rs-gapno{border:1px solid var(--border,#eae5dd);background:none;
  color:var(--text-mid,#5b625a)}
.vx-rs-stage{margin-left:6px;font-size:var(--fs-stop,.6875rem);opacity:.6}
/* The expand affordance, between the name and the grip: one says "there is
   more inside", the other says "this can move". Rotates when open, which is the
   Budget card's own behaviour. */
/* The trip's own expand mark. Same glyph and same rotation as a stop's, one
   step larger, because the two levels are the same gesture. */
.vx-rs-tripcaret{flex:0 0 auto;margin-left:6px;font-size:var(--fs-caret,.9rem);line-height:1;
  color:var(--text-muted,#88928d);transition:transform .18s ease;display:inline-block;
  border:0;background:none;padding:2px 4px;cursor:pointer;font-family:inherit}
.vx-rs-tripcaret[aria-expanded="true"]{transform:rotate(90deg)}
.vx-rs-row.is-open .vx-rs-tripcaret,
.vx-rs-row[aria-expanded="true"] .vx-rs-tripcaret{transform:rotate(90deg)}
/* ⚑ THE SAME CONTROL, WEARING THE ALERT. Stephen 2026-08-25: "can the 'alert'
   triangle replace the expand arrow when there is an action required… that
   would be a consistent place on the screen."

   Gold, not red — a decision to make, not a fault. And it must NOT inherit the
   caret's rotation: a chevron turning 90 degrees reads as opening, a triangle
   turning 90 degrees reads as broken. */
/* ⚑ THE WARNING STATE IS THE SAME CONTROL, SO IT IS THE SAME SIZE. It carried
   .72rem — a third size on one button, so the arrow SHRANK when a trip went
   tight. Only the colour and the glyph say "tight"; the geometry must not. */
.vx-rs-tripcaret.is-tight{color:var(--amber-risk,#C97B3A);font-size:var(--fs-caret,.9rem)}
/* ⚑ ALL THREE ROTATION RULES, because the caret has three. Two select the
   element, one selects an open row — miss any and an open trip spins its
   triangle onto its side. */
.vx-rs-tripcaret.is-tight[aria-expanded="true"],
.vx-rs-row.is-open .vx-rs-tripcaret.is-tight,
.vx-rs-row[aria-expanded="true"] .vx-rs-tripcaret.is-tight{transform:none}
/* The hour on a stop's row: tabular so a column of them lines up, quiet enough
   that the two place names stay the thing you read. "by 10:00a" is a deadline
   the couple stated; a bare time is a departure the plan worked out. */
/* ⚑ THE TWO EDGES. Fixed columns so a whole trip reads as a timeline down the
   page rather than as ragged text — that alignment is the point of putting them
   at the edges rather than beside the names. Tabular figures for the same
   reason. A stated deadline is weighted; a computed arrival is quiet. */
.vx-rs-leaveat,.vx-rs-arriveby{flex:0 0 auto;width:3.6em;
  font-size:var(--fs-stopdet,.5625rem);font-variant-numeric:tabular-nums;
  color:var(--text-muted,#88928d);white-space:nowrap}
.vx-rs-leaveat{text-align:left}
.vx-rs-arriveby{text-align:right}
.vx-rs-arriveby.is-by{color:var(--text-mid,#5b625a);font-weight:600}
/* ⚑ THE ARROW IS A PATH NOW — see _vxChevron. It stays sized by --fs-caret
   because the svg is 1em square, so every assertion about that token still
   applies; what changed is how much ink an em of it actually draws. */
.vx-rs-chev{width:1em;height:1em;display:block;overflow:visible}
.vx-rs-movecaret{flex:0 0 auto;font-size:var(--fs-caret,.9rem);line-height:1;
  color:var(--text-muted,#88928d);transition:transform .18s ease}
.vx-rs-move.is-open .vx-rs-movecaret{transform:rotate(90deg)}
.vx-rs-movegrip{flex:0 0 auto;padding:8px 2px 8px 10px;margin-right:-2px;
  font-size:1rem;line-height:1;color:var(--text-muted,#88928d);
  cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.vx-rs-movegrip:active{cursor:grabbing}
/* The row under the finger. Lifted rather than tinted: a colour change reads as
   a state the row is now IN, and this one ends the moment it is let go. */
.vx-rs-move.is-dragging{background:var(--white,#fff);border-radius:10px;
  box-shadow:0 6px 18px rgba(44,74,62,.16);position:relative;z-index:2}
.vx-rs-move.is-dragging .vx-rs-movegrip{cursor:grabbing}
/* The face and its grip sit on one line, the grip on the outside. */
.vx-rs-move{display:flex;align-items:center;flex-wrap:wrap}
/* ⚑ `flex:1 1 0` AND `min-width:0`, NOT `1 1 auto`. With `auto` the head's
   basis is its CONTENT, so a long place name pushed the grip past 100% and it
   wrapped onto a line of its own under the stop — a bare ≡ floating in the
   list, which is what he photographed. Zero basis lets the head shrink and the
   grip stay on the row. */
.vx-rs-movehead{flex:1 1 0;min-width:0}
.vx-rs-movebody,.vx-rs-move > .vx-rs-movehead.is-static{flex:1 0 100%}
/* The tinted card, matching the Budget line item's own expansion. */
/* ══ THE TRIP CARD — THE BUDGET CARD'S OWN LANGUAGE ═══════════════════════
   Stephen 2026-08-19: "this looks horrible — the spreadsheet was an example NOT
   the final product — this is not a premium look at all."

   ⚑ AND THE MISTAKE IS A SPECIFIC ONE. I read his spreadsheet as a VISUAL spec
   when it was a STRUCTURAL one. Excel draws borders and yellow fills because
   that is all Excel has; the hierarchy was the message, not the grid lines. He
   had already given the visual answer a message earlier — "the design should
   function like the Budget card" — and function meant look, too.

   So every value below is lifted from #section-budget rather than invented
   beside it: cream-warm panel, 12px radius, 16/18 padding, hairline rules
   between rows, .86rem names, DM Sans throughout. No borders. No fills. A trip
   is a category, a stop is a line item, and they are already styled — the job
   was to use that, not to draw a table. */

/* ── THE STOP LIST ──────────────────────────────────────────────────────── */
.vx-rs-moves{margin:0}
.vx-rs-move{display:flex;align-items:center;flex-wrap:wrap;gap:10px;
  border-top:1px solid rgba(44,74,62,.07)}
.vx-rs-moves > .vx-rs-move:first-child{border-top:none}
/* ⚑ THIS RULE NO LONGER LAYS THE ROW OUT — the grid above does.
   It declared `display:flex;align-items:center;gap:8px;padding:7px 0` at the
   same specificity as the grid and LATER in the document, so it won: the fixed
   clock track never applied, `.vx-rs-cpair{width:100%}` became a huge flex
   basis, and the stop name was squeezed to a fraction of the row. Shipped green
   because the only assertion on the new row counted `vx-rs-cpair` in the
   MARKUP — the name appearing, never the layout working.
   What is left is what a movehead needs as a flex ITEM of `.vx-rs-move`, plus
   its button reset. Layout lives in exactly one place now. */
.vx-rs-movehead{flex:1 1 0;min-width:0;
  background:none;border:0;text-align:left;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);color:inherit}
/* ⚑ ONE LINE, THEN ELLIPSIS. Stephen 2026-08-19: "the titles are wrapping."
   Two place names is a long string and a wedding venue is longer than most; a
   list where half the rows are two lines tall stops reading as a list. */
/* ⚑ A FLEX LINE, SO THE NAME SHRINKS AND THE MARKER DOES NOT. The row used to
   truncate as one string, which was fine while the ⚠ LED it and nothing
   followed the name. With the marker moved after the title — his ask, so the
   titles align — a shared ellipsis would eat the warning on exactly the longest
   rows. The name is the only flexible thing on the line; the ellipsis moves to
   it, and `.vx-rs-alert` / `.vx-rs-movewave` are `flex:0 0 auto`. */
.vx-rs-movename{flex:1 1 auto;min-width:0;font-size:var(--fs-stop,.6875rem);
  line-height:1.35;color:var(--charcoal,#33352f);
  display:flex;align-items:baseline;
  white-space:nowrap;overflow:hidden}
.vx-rs-movewave{color:var(--text-muted,#88928d);font-size:var(--fs-stopdet,.5625rem)}

/* A stop's own name. Ordinary text until the row is open, then it invites the
   edit — a dotted rule rather than a box, because the clean design he asked for
   has no room for a second control on the line. */
/* The name owns the truncation now that it is one item on a flex line. */
.vx-rs-stopname{cursor:inherit;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* ⚑ AND THE ELLIPSIS STANDS DOWN WHILE YOU TYPE. Stephen 2026-08-20: "the same
   editable textbox font style and sizing issue on Stops like it was on Trips."
   The rule above this one clips the name to one line, which is right for a list
   and wrong for a field — the editor was cut mid-word at the row's edge. The
   name reads clipped and edits whole. */
.vx-rs-movename.is-editing{overflow:visible;white-space:normal;text-overflow:clip}
/* ⚑ AND THE ELLIPSIS STANDS DOWN ON THE SPAN THAT NOW CARRIES IT. The rule
   above was written when `.vx-rs-movename` clipped the text itself; the clip
   moved down one level with the flex line, so the editor would still have been
   cut mid-word at the row's edge without this. */
.vx-rs-stopname.is-editing{overflow:visible;white-space:normal;text-overflow:clip}
.vx-rs-stopname.is-editing{border-bottom:none;display:block}
.vx-rs-stopname.is-editable{cursor:text;
  border-bottom:1px dashed var(--line,rgba(51,53,47,.28))}
.vx-rs-stopname.is-editable:hover{border-bottom-color:var(--gold-deep,#A07840)}

/* ⚑ THE STOP THAT CANNOT HAPPEN AS ENTERED.
   Stephen 2026-08-20: a warning for a group the trip's vehicle cannot carry, or
   a pick-up/drop-off route feedback says cannot be met.

   It LEADS the name rather than trailing the row, for the same reason the leave
   time does: an eye running down a list of stops finds a column, never a ragged
   right edge. Sized to the type around it and coloured, not boxed — one stop in
   a plan of twenty should draw the eye once, not turn the card into an alarm.

   ⚑ EVERY var() CARRIES A FALLBACK. An unresolved custom property does not fall
   back to the previous value, it deletes the declaration outright — which is
   how a hover state once emptied the active tab in this same file. */
.vx-tp-slackline{margin:0 0 8px;font-size:var(--fs-stop,.6875rem);
  line-height:1.55;color:var(--text-muted,#88928d)}
.vx-tp-slackline b{font-weight:600;color:var(--charcoal,#33352f)}

/* ── THE MANIFEST AN OPERATOR PRICES AGAINST ──────────────────────────────
   Reads as a document, not as another card: a quiet rule around it, sections
   with their own headings, and the rides in a fixed-width time column so an
   eye running down finds the clock. Every var() carries a fallback — an
   unresolved token deletes the property outright. */
.vx-pk{border:1px solid var(--line,rgba(51,53,47,.14));border-radius:8px;
  padding:14px 16px;margin:10px 0 12px;
  background:var(--card,#fff)}
.vx-pk-states{display:flex;gap:6px;align-items:flex-start;margin:0 0 12px;
  padding:7px 9px;border-radius:6px;
  background:var(--gold-pale,rgba(200,169,110,.08));
  border-left:2px solid var(--amber-risk,#C97B3A);
  font-size:var(--fs-stop,.6875rem);line-height:1.45;
  color:var(--charcoal,#33352f)}
.vx-pk-states span{color:var(--amber-risk,#C97B3A)}
.vx-pk-sec{margin:0 0 14px}
.vx-pk-sec:last-child{margin-bottom:0}
.vx-pk-sec h4{margin:0 0 6px;font-size:var(--fs-stopdet,.5625rem);
  letter-spacing:.08em;text-transform:uppercase;font-weight:600;
  color:var(--text-muted,#88928d)}
.vx-pk-ride{display:flex;gap:10px;align-items:baseline;padding:3px 0;
  font-size:var(--fs-stop,.6875rem);line-height:1.45}
.vx-pk-when{flex:0 0 58px;font-variant-numeric:tabular-nums;
  color:var(--text-muted,#88928d)}
.vx-pk-where{flex:1 1 auto;min-width:0;color:var(--charcoal,#33352f)}
.vx-pk-where b{font-weight:600}
.vx-pk-where span{display:block;color:var(--text-muted,#88928d);
  font-size:var(--fs-stopdet,.5625rem)}
.vx-pk-line{margin:0 0 4px;font-size:var(--fs-stop,.6875rem);line-height:1.5;
  color:var(--charcoal,#33352f)}
.vx-tp-copy{appearance:none;border:1px solid var(--line,rgba(51,53,47,.2));
  background:var(--card,#fff);color:var(--charcoal,#33352f);
  border-radius:6px;padding:8px 14px;cursor:pointer;
  font-size:var(--fs-stop,.6875rem);font-weight:600}
.vx-tp-copy:hover{background:var(--gold-pale,rgba(200,169,110,.08))}

/* The plan crosses a state line — a property of the plan, sat with its title.
   Quieter than a stop's mark: this is a thing to carry into a conversation
   with an operator, not something to go and fix on the sheet. */
.vx-rs-multistate{display:flex;gap:6px;align-items:flex-start;
  margin:8px 0 0;padding:7px 9px;border-radius:6px;
  background:var(--gold-pale,rgba(200,169,110,.08));
  border-left:2px solid var(--amber-risk,#C97B3A);
  font-size:var(--fs-stop,.6875rem);line-height:1.45;
  color:var(--text-muted,#88928d)}
.vx-rs-multistate b{font-weight:600;color:var(--charcoal,#33352f)}
.vx-rs-multistatemark{flex:0 0 auto;color:var(--amber-risk,#C97B3A);line-height:1.45}

.vx-rs-alert{flex:0 0 auto;margin-left:5px;
  color:var(--amber-risk,#C97B3A);
  font-size:var(--fs-stop,.6875rem);line-height:1}
.vx-rs-move.is-derived .vx-rs-movename,
.vx-rs-move.is-wave .vx-rs-movename{color:var(--text-muted,#88928d)}
/* `flex:1 1 0` is a flex ITEM property — this element is a child of
   `.vx-rs-move`, which IS a flex row. Its own display comes from the grid. */
.vx-rs-movehead.is-static{flex:1 1 0;align-items:center;gap:8px;
  padding:7px 0;cursor:default}

/* The reason, at the top of the box the couple opened to fix it. States what
   the schedule does and names the edits; never "you are late" — that is the
   alarm reduce-stress-never-alarm bars, and it is not what this is. */
.vx-rs-mbreak{margin:0 0 8px;display:flex;flex-direction:column;gap:6px}
.vx-rs-mbreakrow{display:flex;gap:6px;align-items:flex-start;
  padding:6px 8px;border-radius:6px;
  background:var(--gold-pale,rgba(200,169,110,.08));
  border-left:2px solid var(--amber-risk,#C97B3A)}
/* ⚑ VERA REPORTS; SHE DOES NOT WARN. Stephen 2026-08-25: "make the alert more
   Vera and 'We have adjusted your leave by times based on estimated traffic.'"

   The amber rule and the triangle are for something the couple must act on. A
   note saying we already handled it is the opposite of that, and dressing it as
   an alert is how a plan starts to feel like a list of problems — the thing
   "reduce stress, never alarm" exists to prevent. Green, a sparkle, and the
   same shape so the two read as one family. */
.vx-rs-mbreakrow.is-vera{
  background:var(--green-pale,rgba(44,74,62,.06));
  border-left-color:var(--green,#2C4A3E)}
.vx-rs-mbreakrow.is-vera .vx-rs-mbreakmark{color:var(--green,#2C4A3E)}
.vx-rs-mbreakrow.is-vera .vx-rs-mbreaktext b{color:var(--green,#2C4A3E)}
.vx-rs-mbreakmark{flex:0 0 auto;color:var(--amber-risk,#C97B3A);
  font-size:var(--fs-stopdet,.5625rem);line-height:1.5}
.vx-rs-mbreaktext{display:flex;flex-direction:column;gap:1px;min-width:0}
/* ⚑ THE ALERT'S OWN ANSWER, AS A CONTROL. Stephen 2026-08-27: "there is no way
   of accepting the earlier time." Quiet — it is an offer, not a call to action,
   and it sits inside an amber note that is already doing the attention-getting.
   16px, because it is a tap target on a phone and the row it lives in is dense. */
.vx-rs-mbreakdo{display:inline-block;margin-top:6px;appearance:none;cursor:pointer;
  background:var(--white,#fff);border:1px solid var(--gold-deep,#A07840);
  border-radius:999px;padding:6px 14px;min-height:32px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;
  color:var(--gold-deep,#A07840);line-height:1}
.vx-rs-mbreakdo:active{background:rgba(200,169,110,.12)}
.vx-rs-mbreakdo:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
.vx-rs-mbreaktext b{font-weight:600;font-size:var(--fs-stopdet,.5625rem);
  line-height:1.5;color:var(--charcoal,#33352f)}
.vx-rs-mbreaktext span{font-size:var(--fs-stopdet,.5625rem);line-height:1.5;
  color:var(--text-muted,#88928d)}
/* The grip: quiet until touched, and the only thing on the right of the row. */
.vx-rs-movegrip{flex:0 0 auto;padding:7px 2px 7px 10px;font-size:.8rem;
  line-height:1;color:var(--text-muted,#88928d);opacity:.55;
  cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.vx-rs-move:hover .vx-rs-movegrip{opacity:1}
.vx-rs-movegrip:active{cursor:grabbing}
.vx-rs-move.is-dragging{background:var(--white,#fff);border-radius:10px;
  box-shadow:0 6px 18px rgba(44,74,62,.14);position:relative;z-index:2}

/* ── THE STOP'S DETAIL ────────────────────────────────────────────────────
   Stephen 2026-08-19, on the rendered card: "the Stop details are too big and
   should be within the Stop title and no wider than the × so show
   differentiation on mobile, and the look is not using the screen space well at
   all. As a user, the fonts are different sizes, the box looks poorly designed,
   not on brand with the rest of the guides."

   Four faults, and they are all one fault: the panel was drawn as a thing in
   its own right instead of as part of the row above it.

   ⚑ IT LINES UP WITH THE STOP TITLE, AND STOPS AT THE ×. Left edge at the
   title's text, not at the marker; right edge where the × and the grip sit.
   That indent IS the hierarchy on a phone — a box running the full width reads
   as a sibling of the trip rather than as the inside of a stop.

   ⚑ ONE SIZE THROUGHOUT. Labels and values were both meant to be 9px and were
   not: `Leave by` sat in a grid cell that never took the rule. Everything here
   is --fs-stopdet, the label bolder rather than bigger.

   ⚑ AND THE WIDTH GOES TO THE ANSWERS. A label column sized to "Group" leaves
   the rest for the place names, which are the longest strings on the page and
   the only ones a couple needs to read in full. */
/* ⚑ THE BASIS HAS TO PAY FOR THE MARGINS. `flex:1 0 100%` sets the basis to the
   full row and the margins ADD to it, so the panel overflowed its own row and
   sat wider than the grip — which is what "the right edge should be even with
   the expand arrow" was looking at. `calc(100% - 64px)` is the same 20 + 44 the
   margins take, so the box ends where the caret does. */
.vx-rs-movebody{flex:1 0 calc(100% - 64px);position:relative;
  /* 20px clears the marker and its gap, so the panel starts under the title
     text; 44px clears the grip, so it ends level with the expand arrow. */
  margin:0 44px 8px 20px;padding:7px 9px;
  /* ⚑ NO SHADING. Stephen 2026-08-25: "I want to remove the background shading
     on the 'stop' details." The panel was a filled block inside a card that is
     already a filled block on a page that is another one — three tones deep,
     and the fill was the only thing separating a stop's detail from the stop
     above it. A hairline does that job without adding a third surface, which is
     how the stop rows themselves are already divided. */
  background:none;border-radius:8px;
  border-top:1px solid var(--line,rgba(35,38,31,.10));
  display:grid;grid-template-columns:max-content minmax(0,1fr);
  gap:4px 8px;align-items:center;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.5625rem)}
/* The two times share the top row and split it evenly. */
/* ⚑ FIVE IDENTICAL ROWS, THE EXPEDIA SHAPE. Stephen 2026-08-19, with a trip
   confirmation open: "I like the Date layout in the detail from this site. This
   would use the full width of the detail box, but I still only want the time on
   the Stop title row."

   Theirs is `Check-in   Aug 22, 2026 at 3:00pm` — a bold label and the whole
   value on one full-width line. That is already the shape of From, To and
   Group; the two times were the odd pair, squeezed into half-width cells side
   by side, which is why "Sat 9:30a" clipped to "Sat 9:3…" in a box a couple
   types into.

   ⚑ AND THE FULL WIDTH BUYS THE DAY. A wedding weekend runs Friday to Sunday,
   so "9:30a" alone is ambiguous in the one place it must not be — the field
   that sets it. The row on the stop title keeps the bare time, because there
   the day is the heading above it. */
/* ── ⚑ THE FOUR CLOCKS, TWO BY TWO ──────────────────────────────────────
   Stephen's mock, 2026-08-27: Leave by | Boarding on one row, Arrive by |
   Drop-off on the next. The left column is what a couple thinks in, the right
   is what the vehicle does — his own descriptor: an arrive-by is walking
   through the door, a drop-off is a logistics window.

   ⚑ WAS `display:contents`, WHICH FLATTENED BOTH CELLS INTO THE PANEL'S OWN
   `min-content 1fr` GRID — a label column and a field column, which is why the
   two times could only ever stack. A grid of its own, spanning both tracks, is
   what lets four values occupy the two rows the old two used. Measured at
   402pt: 122px either way, so the extra pair costs no height.

   ⚑ AND GREEN MEANS "YOU CAN SET THIS". His rule: the outline, not a fill, and
   it extends to every input on the stop — From, To, Group and the two times.
   The two derived cells keep the quiet line, because a couple must be able to
   see at a glance which two follow from the other two. */
.vx-rs-mtimes{display:grid;grid-column:1 / -1;grid-template-columns:1fr 1fr;
  gap:8px 10px;margin:2px 0 4px}
.vx-rs-mtcell{display:flex;flex-direction:column;gap:3px;min-width:0}
.vx-rs-mtcell > span:first-child{
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.5625rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d);white-space:nowrap}
/* A value, not a field — see _vxDerivedCell. Same box so the block reads as one
   object; no focus, no keyboard, and the muted ink says it followed. */
/* ⚑ ONE HEIGHT FOR EVERY FIELD IN THE PANEL. Stephen 2026-08-29: "the 'Leave
   by' and 'Boarding' field sizes are also different… I would like one height
   for all fields."

   They were set in two places and only one of them was unconditional. The
   DERIVED clocks (Boarding, Drop-off) carry `min-height:38px` always; the
   EDITABLE ones (Leave by, Arrive by) and the selects only got 38px inside the
   <=430px block that raises the font to 1rem to stop iOS zooming. So on a phone
   they matched by accident and on a desktop they never did — 38px beside ~26px,
   in the same row, which is what he photographed.

   Declared once as a token so the two can no longer drift: change this and both
   the typed fields and the derived cells move together. */
:root{--vx-stopfieldh:38px}
.vx-rs-movebody input,.vx-rs-movebody select,
.vx-rs-movebody .vx-th-input,.vx-rs-movebody .vx-th-pick,
.vx-rs-stopgrid input,.vx-rs-stopgrid select{
  min-height:var(--vx-stopfieldh);box-sizing:border-box}
/* ⚑ AND A SHAPE WE WORKED OUT READS THE SAME WAY. The picker opens on what the
   trip is already doing rather than on "— Not set —"; muted until the couple
   chooses, solid once they have. Same rule as the four clocks below. */
.vx-rs-movebody select.vx-rs-msel.is-derived{color:var(--text-muted,#88928d)}

/* ⚑ CALCULATED IS GREY; WHAT THEY TYPED IS BLACK. Stephen 2026-08-31: "the
   newest data that is changed is in black font while the other values show gray
   because they are calculated".
   ⚑ THE RULE WAS ALREADY HERE AND THE COLOUR WAS NOT DOING IT. `--text-mid`
   (#5b625a) against the inputs' `--charcoal` (#33352f) is a difference of a few
   percent of luminance — on his phone Boarding and Drop-off read as black
   beside a typed Arrive by, so all four clocks looked equally authoritative and
   none of them looked calculated. `--text-muted` is the tone this file already
   uses everywhere else for "we worked this out", and it separates at a glance. */
.vx-rs-mtval{display:flex;align-items:center;min-height:var(--vx-stopfieldh);padding:0 8px;
  box-sizing:border-box;border:1px solid var(--line,rgba(35,38,31,.16));
  border-radius:6px;background:transparent;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stop,.6875rem);
  color:var(--text-muted,#88928d)}
/* ⚑ THE GREEN LIVES ON THE RULE THAT GOVERNS, not in a second one beside it.
   Written here first it lost to the base rule's `border:` SHORTHAND, which
   resets border-color — the same later-wins trap that kept the clock track from
   applying this morning. Changed at source instead; see that rule below. */
/* ⚑ THE OLD `display:contents` IS GONE, NOT OVERRIDDEN. It sat one line below
   the grid above and would have won on order — the exact shape that kept the
   stop row's clock track from ever applying this morning. */
.vx-rs-mtcell input{width:100%;min-width:0;box-sizing:border-box}
/* ⚑ ONE RULE FOR EVERY LABEL IN THE PANEL, times and pickers alike. They were
   two rules and only one of them landed. */
/* ⚑ THE LABEL AND ITS ANSWER ARE THE SAME SIZE. Stephen 2026-08-19: "what is
   the font size of the field labels vs the field data, they should be the same
   size." They already shared --fs-stopdet — but UPPERCASE at 9px with letter
   spacing reads a size smaller than the sentence-case value beside it, which is
   the whole complaint. Sentence case, same size, bolder to separate them. */
.vx-rs-movebody label > span:first-child{
  font-size:var(--fs-stopdet,.5625rem);font-weight:600;letter-spacing:0;
  text-transform:none;color:var(--text-mid,#5b625a);white-space:nowrap}
/* ⚑ ONE HEIGHT FOR ALL FIVE, AND TWO WIDTHS. "The fields should all be the
   same height and two at one size and three at another." A time is four
   characters and a place name is forty; giving both the full column wasted the
   row the times sit on and cramped nothing. The two times take a fixed box
   sized for a clock, the three pickers take the rest.

   `height` rather than padding, because an <input> and a <select> compute
   their box differently and padding alone leaves them a pixel or two apart —
   which is what "the fields should all be the same height" was seeing. */
/* ⚑ THE SELECT'S OWN CHROME WAS THE EXTRA HEIGHT. Stephen 2026-08-19: "are the
   pick-list arrows causing us to have the extra padding on the bottom three
   fields?" — yes. A native <select> renders the platform's arrow plus a
   reserved gutter for it, and on WebKit its internal padding is not reachable
   from CSS at all, so the three pickers sat taller than the two inputs however
   the height was set.

   `appearance:none` takes the platform chrome off and we draw the chevron
   ourselves, which makes all five fields one box with one height — and lets the
   arrow match the carets elsewhere on the sheet instead of being whatever the
   OS draws.

   ⚑ THE SVG IS A LITERAL, not a token. An unresolved var() DELETES the property
   rather than falling back, and a background that vanishes takes the only sign
   that this is a picker with it. */
/* ⚑ THE LABEL IS SMALL; THE VALUE IS CONTENT. Stephen 2026-08-19: "the names
   are so small to the size of the arrows."

   His scale — Trip 13, Stops 11, details 9 — put the LABEL and the VALUE at one
   size, and 9px is right for "From" and wrong for "Equestria West at Bavaria
   Downs": a place name at that size inside a 24px box with an arrow beside it
   reads as furniture around nothing. The label holds 9; the value takes 11, the
   same size as the stop row it belongs to, which also makes the panel read as
   that row opened rather than as a separate form. */
/* A derived value reads as an answer, not as an empty control — it is a fact
   about the chain, and there is nothing to choose. */
.vx-rs-movebody input,.vx-rs-movebody select{width:100%;min-width:0;height:24px;
  box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stop,.6875rem);
  font-weight:400;color:var(--charcoal,#33352f);background:var(--white,#fff);
  /* ⚑ GREEN MEANS YOU CAN SET THIS. Stephen 2026-08-27: "the green would extend
     to all input fields on a stop" — From, To, Group and the two times. The two
     clocks we derive keep the quiet grey line (see .vx-rs-mtval), so a couple
     can see at a glance which two follow from the other two. An outline, not a
     fill: his call, and it keeps the panel calm on a cream card. */
  border:1px solid rgba(44,110,74,.5);border-radius:5px;padding:0 7px;
  text-overflow:ellipsis}
.vx-rs-movebody select{padding-right:18px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2388928d' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 6px center;
  background-size:7px 4px}
.vx-rs-movebody input:focus,.vx-rs-movebody select:focus{outline:none;
  border-color:var(--gold,#C8A96E)}
/* ⚑ A COMPUTED HOUR IS PALER, NOT SLANTED.
   Stephen 2026-08-25, testing: "I saw the Leave by time change when I entered
   an arrive by but I did not know that the field was calculated — that is
   perfect… maybe removing the background and shading, making the font a lighter
   color and not italic only would be more identifiable."

   ⚑ THE BEHAVIOUR IS THE EXPLANATION, so the styling only has to label it. He
   worked out what the field was by watching it MOVE when he typed the other
   one; nothing needed to announce it. That is also why the Leave by | Arrive by
   | Flexible control that briefly stood above these fields is gone — "no need
   for the buttons" — a control explaining something the behaviour already says.

   ⚑ AND ITALIC ALONE WAS NOT IDENTIFIABLE. Measured before touching it: label,
   input and select are all DM Sans at 9px, so the family was never the problem —
   the slant was doing the whole job, and at 9px it reads as a different face
   rather than as "this one is different". Weight down, colour up: paler than
   the muted text around it, upright like everything else. */
/* ⚑ A LITERAL, BECAUSE `--text-faint` DOES NOT EXIST. I reached for it and
   checked: the palette defines --text-muted (#7A7A7A) and --text-mid (#4A4A4A)
   and nothing fainter. A `var(--text-faint, …)` would have WORKED — on the
   fallback — and then silently changed meaning the day somebody defines that
   token for another purpose. #9E9E9E is one step lighter than --text-muted,
   which is the whole requirement: paler than the label beside it. */
.vx-rs-movebody input::placeholder{color:#9E9E9E;font-style:normal}


/* The trashcan sits on the panel's own top-right, inside its padding. */
/* ⚑ AN INLINE SVG, NOT A GLYPH. The bin was an emoji (heavier than ≡ at every
   size), then an emoji forced to text presentation — which on this machine
   falls back to an empty box, because the font has no text-presentation form
   for U+1F5D1. A drawn icon is the only version that renders the same
   everywhere, and it can be sized to the grip exactly. */
/* ⚑ UNDER THE EXPAND ARROW, NOT BESIDE THE FIELDS. Stephen 2026-08-25: "move
   the trashcan icon under the 'expand' arrow." The panel is inset 44px from the
   right so the caret column stays clear above it; the trashcan sat inside that
   padding at right:5px, which put it over the FIELDS rather than in the column
   the caret owns. Pulling it out into the gutter lines the two controls up, so
   everything you can do to a row lives in one vertical strip.

   -34px = the 44px inset minus about half the icon, which centres it under a
   caret that is itself centred in that gutter. */



.vx-rs-stopwarn{grid-column:1 / -1;margin:0;font-size:var(--fs-stopdet,.5625rem);
  line-height:1.45;color:var(--text-mid,#5b625a)}
.vx-rs-mrow{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:8px}
/* ⚑ THE ALERT SPANS BOTH COLUMNS, LIKE EVERY OTHER STACKED BLOCK HERE.
   `.vx-rs-movebody` is a two-column grid and `/* (duplicate .vx-rs-mlab display rule removed — see the definition above) */`
   feeds each label's word and field in as separate cells. A block that does not
   claim the full row takes ONE cell — which rendered the capacity warning one
   word wide down a 300px column and shunted every label to the wrong side of
   its input. Stephen's screenshot, 2026-08-20.
   Listed beside the others rather than fixed in isolation: anything stacked
   inside this panel needs this, and the next one added will need it too. */
.vx-rs-mbreak{grid-column:1 / -1}

/* ── ADD A STOP, AND ADD A TRIP ──────────────────────────────────────────── */
.vx-rs-addmove{border-top:1px solid rgba(44,74,62,.07)}
.vx-rs-addmove .vx-rs-addstopbtn{padding:8px 0;font-size:var(--fs-stop,.6875rem)}
/* "+ Add a trip" gets the stop panel's own treatment, indented the same way —
   it is the same kind of box and must not read as a second design. */
/* ── ⚑ ADD A TRIP: DAY AND TITLE ON TOP, THE FIRST LEG UNDER ─────────────
   Stephen 2026-08-20: "'Add a trip' needs to look like 'Add a stop' but the Day
   and Title on the top row. This should all be on a '+ Add a trip' link and
   only expose the box when requested."

   ⚑ NOT `display:contents`. The stop panel uses it because its labels and
   fields alternate down two columns — but this form gained four more rows and
   the same trick spread six captions and six fields across a three-wide flow:
   "DAY | TITLE | LEAVE BY" on one line with their inputs on the next, each
   caption over somebody else's field. His screenshot.

   Each label is one cell now, caption stacked over its own field, so a pair can
   never come apart. Two columns puts Day beside Title on the first row, which
   is what he asked for, and the rest follow in pairs. */
/* The panel is a stack now: the trip's identity, then its first stop, then the
   button. Each block owns its own layout instead of one grid trying to serve
   three different shapes. */
.vx-rs-newtrip{margin:0 34px 8px 20px;padding:9px 11px;
  background:var(--cream-warm,#F0EBE1);border-radius:8px;
  display:flex;flex-direction:column;gap:8px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.5625rem)}
/* Day beside Title — the trip's own two facts, on the top row he asked for. */
/* ⚑ `.vx-rs-ntop` IS GONE — Stephen 2026-08-26: "the 'Add a stop' format should
   be the standard with just the date and trip title being the additional data
   points." It was a second form idiom (two equal columns, label ABOVE field)
   stacked on the stop panel's label-left rows. Day and Title are now rows of
   the same grid, so the block, its stacked-label rule and its one-column
   mobile override all come out with it rather than lingering as dead selectors
   that the next reader has to prove unused. */
/* ⚑ THE FIRST STOP BORROWS THE STOP PANEL OUTRIGHT — `.vx-rs-movebody` — so
   Leave by / From / To / Group are the same rows, the same widths and the same
   type as the ones a couple has already used on every other stop. Only the
   chrome differs: no margin of its own, because it is already inside a panel. */
/* ⚑ THE OLD ADDER'S GRID AREAS DO NOT LEAK INTO THE STANDARD PANEL.
   Merging Day and Title into `.vx-rs-movebody` put `.vx-rs-addname` — which
   carries `grid-area:name` for the single-line adder's own area template —
   inside a grid that has no named areas. One item asking for a line called
   "name" invents implicit tracks, and the whole panel silently became FOUR
   columns by three rows instead of two by six.

   MEASURED in a probe against the live stylesheet at 375px:
     before   16.3px 21.7px 55.6px 66.4px   date input  22px  (wrapping "Ju 11, 20")
     after    37.3px 138.7px                date input 139px

   ⚑ AND IT WAS INVISIBLE TO THE GATE that shipped it, which asserted the panel
   was one element and that Day and Title preceded the first stop's time. Both
   were true. A structural assertion cannot see a collapsed grid. */
.vx-rs-movebody .vx-rs-addname,
.vx-rs-movebody .vx-rs-addat,
.vx-rs-movebody .vx-rs-adddate,
.vx-rs-movebody .vx-rs-addwho,
.vx-rs-movebody .vx-rs-addsel,
.vx-rs-movebody .vx-rs-addbtn{grid-area:auto}
.vx-rs-ntstop{margin:0;flex:none}
/* ⚑ AND THE TITLE FIELD STOPS BEING THE ONE BIG THING ON THE FORM.
   `.vx-rs-addname` carries .85rem from the old single-line adder, and at equal
   weight the later rule won — so one input rendered half again the size of
   every field beside it. Pinned here to the same type the stop rows use. */
.vx-rs-newtrip .vx-rs-addname{font-size:var(--fs-stopdet,.5625rem);font-weight:500;
  border:1px solid rgba(44,74,62,.1);background:var(--white,#fff);min-height:0;
  padding:4px 7px}
/* The Add button sits on its own line rather than sharing one with a field. */
.vx-rs-newtrip .vx-rs-mrow{margin:0}
/* ⚑ AND THE BOX STAYS SHUT UNTIL ASKED FOR. The collapse rule hid
   `.vx-rs-adddet`, a class this form does not use — so the whole thing sat open
   under every trip list whether anyone wanted it or not. */
.vx-rs-add:not(.is-open) .vx-rs-newtrip{display:none}
/* And the link is the whole control until then; once the box is open it has
   done its job and would only be a second way to do what is already done. */
.vx-rs-add.is-open .vx-rs-addtriplink{display:none}
.vx-rs-addtriplink{margin:0 34px 8px 20px}
.vx-rs-newtrip input,.vx-rs-newtrip select{width:100%;min-width:0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.5625rem);
  color:var(--charcoal,#33352f);background:var(--white,#fff);
  border:1px solid rgba(44,74,62,.1);border-radius:6px;padding:4px 7px}

/* The mini-heading: bold, NOT uppercase — the Budget panel's own decision,
   made on 2026-07-25 so a detail box reads as one uniform voice. */
/* ⚑ LABEL AND CONTROL ON ONE ROW. Stephen 2026-08-19: "the pick-list fields
   and the field titles should be on one row each to conserve screen space."
   Stacked, three fields cost six lines of a phone screen to carry three
   answers. The label column is sized to the longest word it holds rather than
   to a guess, so From / To / Who line up down the panel without a fixed width
   that a longer label would break out of. */
/* ⚑ SUPERSEDED 2026-08-27. This put the label and its control on ONE ROW —
   Stephen 2026-08-19: "the pick-list fields and the field titles should be on
   one row each to conserve screen space." Today he asked for the opposite, and
   for a reason that did not exist then: "put the titles (From, To, Group) above
   their fields and expand the field so everything is aligned left edge to right
   edge with the time boxes." The four clocks stack their labels, so a beside-
   label makes From/To/Group the only controls in the panel shaped differently.
   The space argument still stands and is answered instead by the 2x2 — four
   values in the two rows the old two occupied. Its non-layout properties stay;
   the layout moved to the single definition further down. */
.vx-rs-mlab{grid-template-columns:none;align-items:center;
  gap:5px 12px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.625rem);font-weight:600;
  letter-spacing:.01em;text-transform:none;color:var(--charcoal,#33352f)}
/* ⚑ ONE COLUMN WIDTH FOR ALL THREE, set on the panel rather than the label —
   a per-label `auto` would give each row its own width and the controls would
   stagger down the card. `min-content` on the panel makes every label share
   the widest one. */
.vx-rs-movebody{grid-template-columns:min-content 1fr}
/* ⚑ AND IT STOPS DODGING CONTROLS THAT ARE NOT BESIDE IT. Stephen 2026-08-26:
   "the mobile screen is small, can we reduce the padding on the 'stop' details
   to use more of the white space since the data is already grouped within the
   'stop' header."

   The desktop margins are `0 44px 8px 20px`, and both have honest reasons up at
   the base rule — 20px "clears the marker", 44px "clears the grip, so it ends
   level with the expand arrow". On a phone the grip and the arrow sit on the
   stop ROW ABOVE this panel, not to its side, so the panel is leaving 64px of a
   371px card clear of nothing.

   MEASURED at 500px before this: card 371px, panel 257px, the field itself
   193px with 132px of dead space to its right. The header already says which
   stop these fields belong to — that is his point, and it is why the inset can
   be small rather than structural. */
@media (max-width:767px){
  /* ⚑ THE BASIS, NOT JUST THE MARGINS. Cutting the margins alone bought FOUR
     pixels — MEASURED live before shipping it — because the base rule sets
     `flex:1 0 calc(100% - 64px)` and that hardcodes the very 64px the margins
     were being trimmed from. The flex basis was the width; the margins were
     only where it sat. With both: panel 257px -> 299px, field 193px -> 237px on
     a 371px card. */
  /* ⚑ AND THEN ALL THE WAY. Stephen 2026-08-27: "love the titles to align under
     the stop title." 10px of margin plus 8px of padding still sat the labels
     18px right of the name they belong to, which is the same mistake the leg
     list's 34px was — an inset clearing controls that are not beside it on a
     phone. The list already carries the card's 14px on both sides, so the panel
     needs none of its own: "Leave by" now starts exactly under "Westin Edina
     Galleria", and the hairline above it spans the same width as the row. */
  /* ⚑ FLUSH ON BOTH SIDES AGAIN. This briefly reserved 24px on the right to
     hold a trashcan that hung on `right:-34px` — it lived in the margin this
     rule zeroed out, so it fell outside a card with `overflow:hidden` and
     vanished. The control moved to the foot of the panel as a worded "Remove
     stop" (his call, 2026-08-27), so the gutter went with it and the fields
     have the full width back. Nothing in this panel hangs outside it now, and
     stop-row-layout-validate holds that: any absolutely-positioned child with a
     negative offset must have padding on that side to land in. */
  .vx-rs-movebody{flex-basis:100%;
    margin-left:0;margin-right:0;padding-left:0;padding-right:0}
  /* ⚑ AND THE CREATE FORM'S WRAPPER STOPS DODGING TOO. `.vx-rs-newtrip` carries
     `margin:0 34px 8px 20px` from the desktop sheet, and it sits INSIDE
     `.vx-rs-newpane`'s own 15px padding — so the create panel was inset 130px of
     a 330px card before its grid even started. Same reasoning as the stop panel
     above: the controls it was clearing are not beside it on a phone. */
  .vx-rs-newtrip{margin-left:0;margin-right:0;padding-left:8px;padding-right:8px}
  /* ── ⚑ 16px OR MOBILE SAFARI ZOOMS THE PAGE ────────────────────────────
     Not a preference and not a size choice: WebKit forces a viewport zoom
     whenever a focused input computes under 16px, and it does not zoom back
     out. So on an iPhone, tapping "Leave by" on an existing stop threw the
     whole plan out of frame — while the same field inside "Add a trip" behaved,
     because EIGHT controls in that form were already lifted to 1rem for exactly
     this reason. The stop panel was missed.
     ⚑ AND CHROME CANNOT SHOW THIS. It is engine behaviour, not screen width, so
     no amount of device emulation reproduces it — which is why it survived
     every check on the desktop.
     The height goes with it: 24px was sized for 11px text, and it is also well
     under the 44px touch target these rows have always wanted. Stephen's
     density ask is preserved where it costs nothing — the LABELS stay 9px, and
     it is only the controls a finger lands on that grow. */
  /* ⚑ AND HIS CALL OVERRIDES THAT, KNOWINGLY. Stephen 2026-08-27: "reduce the
     font sizes inside the data fields to match the Budget font sizing." The
     Budget field he is pointing at is `#section-budget .vxb-item
     .vxb-amount-input`, which is --fs-amount — .9rem, 14.4px, UNDER the
     threshold above. There is no `maximum-scale` in this page's viewport meta,
     so Budget has always zoomed on focus too, on the same phone he tests on.
     That is the trade he is making and it is a reasonable one: the two surfaces
     read alike, and the behaviour is one he already lives with. Written down
     rather than quietly reverted, because the paragraph above is still TRUE —
     if the zoom becomes annoying, this line is the whole fix.
     The touch target does not go with it: min-height stays, since 38px is about
     the finger and nothing about the type. */
  /* ⚑ REVERTED, BECAUSE HE HIT THE THING I WARNED ABOUT. This was
     --fs-amount (.9rem) for one morning — his ask, "match the Budget font
     sizing", taken with the cost stated: under 16px WebKit force-zooms on focus
     and does not zoom back. He then sent a screenshot of exactly that, mid-word
     in the place field, with the plan scaled up and clipped on both edges:
     "Adding a new location needs attention."

     So 16px is a FLOOR, not a preference. The Budget card can carry .9rem
     because its fields are a short column on a page with room; the plan is a
     dense panel inside a card inside a carousel, and losing the frame there
     costs the couple their place in a five-stop trip. Budget has the same latent
     zoom — it simply has not bitten yet, and is worth a look on its own. */
  .vx-rs-movebody input,.vx-rs-movebody select,
  .vx-rs-movebody .vx-th-input,.vx-rs-movebody .vx-th-pick{
    font-size:1rem;height:auto;min-height:38px}
}
/* ── ⚑ LABEL ABOVE FIELD, EDGE TO EDGE ──────────────────────────────────
   Stephen 2026-08-27: "please put the titles (From, To, Group) above their
   fields and expand the field so everything is aligned left edge to right edge
   with the time boxes."

   ⚑ FOUR RULES SET THIS, AND THE LAST ONE WON. `display:contents` flattened
   each label into the panel's `min-content 1fr` grid — the word in the narrow
   column, the field in the wide one — so From/To/Group sat beside their fields
   while the four clocks sat above theirs. The definition lives HERE, at the end,
   because that is what actually governs; the earlier copies are neutralised at
   source rather than fought with a fifth rule. Same trap that hid the clock
   track this morning, and the fourth time today. */
.vx-rs-mlab{display:flex;flex-direction:column;gap:3px;min-width:0;grid-column:1 / -1}
.vx-rs-mlab > span:first-child{
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.5625rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d);
  white-space:nowrap;align-self:flex-start}
.vx-rs-mlab > input,.vx-rs-mlab > select,.vx-rs-mlab > .vx-th-pick{
  width:100%;min-width:0;box-sizing:border-box}
/* The stacked pieces that must still span both columns. */
/* ⚑ AND THE ADD-A-PLACE PANEL, WHICH LANDED IN A min-content TRACK.
   Stephen 2026-08-27, mid-typing: "Adding a new location needs attention." The
   form is created in JS and inserted as the NEXT SIBLING of the select's label —
   inside `.vx-rs-movebody`, which is a two-column grid. With no grid-column it
   took whatever track came next, which is the `min-content` label column, so
   "Place" and "Address" were typed into a ~150px gutter beside an empty half of
   the panel. Same shape as the Add-a-trip collapse: an element put into a grid
   without saying which cell it wants. */
.vx-rs-mrow,.vx-rs-stopempty,.vx-rs-stopwarn,.vx-rs-mbreak,.vx-addpl{grid-column:1 / -1}
.vx-rs-msel,.vx-rs-mtime,.vx-rs-movebody .vx-th-time{width:100%;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.625rem);font-weight:400;
  line-height:1.55;color:#4a4a4a}
.vx-rs-mtime,.vx-rs-movebody .vx-th-time{width:auto;min-width:130px}
/* The time row behaves like the pickers — label left, control right. */
.vx-rs-stopempty,.vx-rs-stopwarn{margin:0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.625rem);font-weight:400;
  line-height:1.55;color:#4a4a4a}
/* A later departure of the same loop: the same line, quieter, and with no
   caret — there is nothing under it, because the hire is edited once. */
.vx-rs-movewave{color:var(--text-muted,#88928d)}
.vx-rs-move.is-wave .vx-rs-movename{color:var(--text-muted,#88928d)}
/* An empty leg or the plan's own ride home: shown, because it is billed and it
   is on the road, but not a decision — so it reads at the same weight as a
   hold rather than as a stop somebody chose. */
.vx-rs-move.is-derived .vx-rs-movename{color:var(--text-muted,#88928d)}

/* ⚑ NO `display` HERE — the grid above governs every movehead, static or not.
   This said `display:flex`, and `.vx-rs-movehead.is-static` outranks
   `.vx-rs-movehead`, so the wave and derived rows NEVER used the clock track.
   Stephen's card showed it: 'Departure #1' with no clock at all and
   'Departure #2' with its time clipped at the card edge, because in a flex
   row `.vx-rs-cpair{width:100%}` becomes an enormous basis. Measured at 402pt
   with Playwright: the clock box was 216px wide against a 112px track. */
.vx-rs-movehead.is-static{align-items:center;gap:10px;width:100%;
  padding:9px 0;cursor:default}
/* The controls row, on the Budget panel's pill pattern. */
.vx-rs-mrow{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:2px}


.vx-rs-addmove{border-top:1px dashed var(--border,#eae5dd)}
.vx-rs-addmove .vx-rs-addstopbtn{padding:11px 0}
.vx-rs-stop{position:relative;padding-left:20px}
.vx-rs-stopdot{position:absolute;left:3px;top:9px;width:7px;height:7px;
  border-radius:50%;background:var(--green,#2C4A3E)}
.vx-rs-stop-last .vx-rs-stopdot{background:none;
  border:2px solid var(--green,#2C4A3E);width:8px;height:8px;left:2px}
.vx-rs-stop:not(.vx-rs-stop-last)::before{content:'';position:absolute;
  left:6px;top:18px;bottom:-6px;width:1px;
  background:linear-gradient(to bottom,
    rgba(44,74,62,.35) 0, rgba(44,74,62,.35) 3px,
    transparent 3px, transparent 6px);
  background-size:1px 6px}
.vx-rs-stop + .vx-rs-stop{margin-top:8px}
/* The add row IS a row — same rail, same indent, an open dot because nothing
   is there yet. ⚑ 44px target: it is a tap on a phone. */
.vx-rs-addstop{display:flex;align-items:center;min-height:44px}
.vx-rs-stopdot-add{background:none;border:1px dashed rgba(44,74,62,.45);
  width:9px;height:9px;left:2px;top:auto}
.vx-rs-addstopbtn{border:0;background:none;cursor:pointer;padding:4px 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;
  color:var(--green,#2C4A3E)}
.vx-rs-addstopbtn::before{content:'+ ';color:var(--gold,#C8A96E)}
.vx-rs-addstopbtn:hover{text-decoration:underline;text-underline-offset:3px}
/* Removing a stop sits at the end of its own row, never beside the label —
   a destructive control next to a picker is how the wrong one gets tapped. */
.vx-rs-stopdel{margin-left:auto;width:30px;height:30px;flex:0 0 auto;
  border:0;background:none;cursor:pointer;border-radius:50%;
  font-size:var(--fs-cat-title,.9rem);line-height:1;color:var(--text-muted,#88928d)}
.vx-rs-stopdel:hover{background:rgba(44,74,62,.06);color:var(--green,#2C4A3E)}
.vx-rs-stop{display:flex;align-items:center;gap:6px}
.vx-rs-stop > .vx-rs-wlab{flex:1 1 auto;min-width:0}
@media (prefers-reduced-motion:reduce){
  .vx-rs-stop:not(.vx-rs-stop-last)::before{background:rgba(44,74,62,.28)}
}

/* ── WHAT ELSE COULD GO HERE ────────────────────────────────────────────
   Rides we suggested and the couple has not taken, folded into one line per
   day. Stephen: the unticked ones "cause clutter on mobile and lots of
   unnecessary scrolling" — three full rows with a time field and a rider picker
   each, for rides that are not in the plan.

   Quiet by construction: this is an offer, not an omission, so it must not
   compete with the rides that ARE booked. No tint, no border, muted type — it
   reads as a footnote until opened.

   ⚑ 44px MINIMUM TARGET. It is a tap target on a phone and the row it replaces
   was full-height; a 28px line would be tidier and harder to hit. */
.vx-rs-offered{margin:2px 0 6px}
.vx-rs-offeredbtn{display:flex;align-items:center;gap:6px;width:100%;
  min-height:44px;padding:6px 4px;border:0;background:none;cursor:pointer;
  text-align:left;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.76rem;color:var(--text-muted,#88928d)}
.vx-rs-offeredbtn:hover{color:var(--green,#2C4A3E)}
/* ⚑ HIDDEN, NOT UNRENDERED. The rows stay in the document so every projected
   line is still drawn with its checkbox, hour control and × — the invariant
   nineteen assertions protect. Only the screen space goes away, which is the
   whole of the mobile complaint. */
.vx-rs-offeredrows{display:none}
.vx-rs-offered.is-open .vx-rs-offeredrows{display:block}
.vx-rs-offeredcaret{display:inline-block;transition:transform .15s ease}
.vx-rs-offered.is-open .vx-rs-offeredcaret{transform:rotate(90deg)}
.vx-rs-offered.is-open .vx-rs-offeredbtn{color:var(--green,#2C4A3E)}
@media (prefers-reduced-motion:reduce){
  .vx-rs-offeredcaret{transition:none}
}

/* WHICH SHEET. Two words, not a settings panel — the old view has to be one
   tap away while a live wedding is being tested against the new one. */
.vx-rs-switch{display:inline-flex;gap:0;margin:0 0 18px;padding:2px;border-radius:100px;
  background:rgba(44,74,62,.06);border:1px solid rgba(44,74,62,.10)}
.vx-rs-swbtn{padding:6px 15px;min-height:32px;border:0;border-radius:100px;cursor:pointer;
  background:none;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;font-weight:500;
  color:var(--text-muted,#88928d)}
.vx-rs-swbtn.is-on{background:#fff;color:var(--green,#2C4A3E);
  box-shadow:0 1px 2px rgba(44,74,62,.10)}

/* Four across on a laptop, two-by-two on a phone — never a squeezed row of
   four, where "First call" wraps to three lines and the number it labels ends
   up smaller than the label. Reuses the stat card the activities sheet already
   uses, so the two views agree about what a summary looks like. */
.vx-rs-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:0 0 20px}
@media (max-width:640px){.vx-rs-stats{grid-template-columns:repeat(2,minmax(0,1fr))}}
.vx-rs-stats .vx-th-statvalue{font-variant-numeric:tabular-nums}
.vx-rs-stats .vx-th-statvalue small{font-size:.62em;color:var(--text-muted,#88928d)}
/* "No rides" is a settled answer for a couple driving themselves, not a gap —
   quieter than a number, but never a warning colour. */
.vx-rs-none{font-size:.7em;color:var(--text-muted,#88928d)}

.vx-rs-dayhead{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  margin:22px 0 2px;padding-bottom:5px;border-bottom:1px solid rgba(44,74,62,.18);
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--green,#2C4A3E);font-weight:600}
.vx-rs-rows>.vx-rs-dayhead:first-child{margin-top:0}
.vx-rs-daydate{color:var(--text-muted,#88928d);letter-spacing:.03em;text-transform:none;font-size:.68rem}

/* ONE LINE. The grid is the mockup's, minus the columns he ruled off the sheet:
   no vehicle, no price, no headcount. */
/* ONE LINE, in the mockup's column order: include · when · event · vehicle ·
   remove. Nothing wraps to a second line — the whole point.
   THE OFFSET COLUMN IS GONE (2026-08-09). Stephen's testers "articulate in day
   of week and start time", so the clock became the field and the offset went
   back to being the model. The 66px it held goes to the clock, which now has to
   hold a span like 11:30p-1:30a AND be tapped. */
/* ⚑ THE FACE IS THREE THINGS. Stephen 2026-08-17: "the only items on a plan
   are the time, event title and the expand arrow" — the Budget pattern, where
   a category opens to line items and a line item opens to its detail. Who
   rides, the include checkbox and the × all moved into the panel. Two columns
   now, and the anchor's T−0 label tucks in front of the clock. */
/* ⚑ SIZED TO WHAT IT HOLDS. Stephen 2026-08-17: "do the time entry fields
   need that much space?" Measured: a 132px column for 44px of text — 31%% of
   the row for a clock. The track was sized for a SPAN like "11:30pm-1:30am",
   and the sheet has shown only the start time since 2026-08-09 ("let's only
   use the start time in the plan row") — the width outlived the design that
   needed it, and width:100%% stretched the button to fill whatever was left.
   Still a FIXED track, not auto: the titles line up at one x down the sheet,
   and a ragged left edge is what the left-aligned clock was for. */
/* ⚑ A THIRD COLUMN FOR THE ×. The face was `76px minmax(0,1fr)` — two
   columns — so the delete became a third grid item and wrapped onto its own
   line under every title, doubling the height of the whole sheet. Stephen,
   looking at it: "the × is there but needs to be right justified."
   `auto` rather than a fixed width, so the column collapses to nothing on the
   rows that carry no delete — a locked line, a continuation, the anchor.

   The 76px clock column went on 2026-08-18: the time moved into the panel and
   the face became the title and the ×, which is a Budget category row exactly. */
/* ── ⚑ A MOVEMENT ROW IS A BUDGET ROW ────────────────────────────────────
   Stephen 2026-08-18, holding the two screens side by side: "the × is to the
   left of the title — I would like the movements to look like the Budget card."

   The Budget's own row is `.vxb-item`: a flat line, title left, meta right,
   separated by a dashed rule and nothing else. No box per row, no tint, no
   shadow — the CARD is the section around them. That restraint is the thing he
   keeps calling simple, and copying the shape means copying what it leaves out.

   Flex rather than grid on purpose: the face's leading cell is now empty (the
   clock moved into the panel), and an empty grid cell still consumes a track —
   which is what put the × on the wrong side of the title. Flex ignores what is
   not there. */
.vx-rs-row{display:flex;align-items:center;gap:12px;
  padding:11px 0;border-bottom:1px dashed var(--border,#eae5dd)}

/* ── THE DECISIONS, INSIDE ────────────────────────────────────────────
   They lead the panel: these are the three a couple opened the row to
   change, and the stop stack beneath is reference. */
.vx-rs-dethead{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin:0 0 12px;padding:0 0 12px;border-bottom:1px solid rgba(44,74,62,.10)}
.vx-rs-detinc{display:inline-flex;align-items:center;gap:7px;min-height:44px;
  cursor:pointer;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;
  color:var(--green,#2C4A3E)}
/* THE HOUR, WHERE IT IS EDITED NOW. First in the panel because it is the field
   a couple opens a row to change most often. */
/* ⚑ HER LINE, NOT THE FIELD'S. The editable Time holds the real minute because
   that is what the plan runs on; this is the floored quarter-hour she acts on,
   and it reads as a sentence rather than as another control. */
.vx-rs-ready{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin:0 0 10px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem}
.vx-rs-readylab{font-size:.66rem;letter-spacing:.04em;text-transform:uppercase;
  color:var(--text-muted,#88928d)}
.vx-rs-readyval{font-family:var(--ff-m,ui-monospace,monospace);font-size:.95rem;
  font-weight:500;color:var(--green,#2C4A3E)}
.vx-rs-readyto{color:var(--text-muted,#88928d);font-size:.78rem}
.vx-rs-detat{display:flex;flex-direction:column;gap:3px;flex:0 0 132px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.66rem;letter-spacing:.04em;
  text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-rs-detat .vx-rs-whenin{width:100%}
.vx-rs-detwho{flex:1 1 190px;min-width:0}
.vx-rs-detwho .vx-th-pick{width:100%}
.vx-rs-dethead .vx-rs-cell-del{margin-left:auto}
/* ── THE RIDE BACK, WITH ITS OWN CLOCK ────────────────────────────────
   What the indented ↳ row held alone. Reads as part of one activity. */
.vx-rs-backs{margin:12px 0 0;padding:10px 0 0;border-top:1px solid rgba(44,74,62,.08)}
.vx-rs-back{display:flex;gap:10px;align-items:baseline;padding:3px 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem}
.vx-rs-backclock{flex:0 0 62px;font-family:var(--ff-m,ui-monospace,monospace);
  font-size:.74rem;color:var(--green,#2C4A3E)}
.vx-rs-backlab{min-width:0;color:var(--text-muted,#88928d)}
.vx-rs-row.is-off{opacity:.45}
/* ══════════════════════════════════════════════════════════════════════
   ONE SIZE ON THE SHEET. Stephen 2026-08-17: "please make all of the fonts on
   the page the same as the event header."

   ⚑ MEASURED FIRST: the sheet was running NINE different DM Sans sizes —
   9.92, 10.88, 11.2, 11.52, 12, 12.16, 12.48, 12.8 and 13.76px — each one set
   where its rule happened to be written. Nobody chose a scale; nine people
   chose a number. That is the same defect as the four hand-kept chrome offsets
   this morning, one layer up.

   So there is one token and everything a couple READS points at it. The clock
   keeps DM Mono, because tabular figures are what line the column up, but it
   takes the same size — a different face at the same size reads as a
   deliberate distinction; a different size reads as an accident.

   WHAT DELIBERATELY STAYS DIFFERENT, and it is a short list:
     · .vx-th-title — Cormorant 24px, the section heading. It is the display
       face and the only thing on the sheet that should not be body text.
     · the pin marks (○ ●) and T−0 — glyphs, not words.
   ══════════════════════════════════════════════════════════════════════ */
.vx-rs{--vx-rs-fs:.86rem}
.vx-rs .vx-rs-gaptitle,.vx-rs .vx-rs-gapadd,.vx-rs .vx-rs-gapno,
.vx-rs .vx-rs-movelab,.vx-rs .vx-rs-restorebtn,.vx-rs .vx-rs-restore,
.vx-rs .vx-rs-addbtn,.vx-rs .vx-rs-addhint,.vx-rs .vx-rs-depthqr,
.vx-rs .vx-th-lede,.vx-rs .vx-th-gap,.vx-rs .vx-rs-note,
.vx-rs .vx-rs-idealede,.vx-rs .vx-rs-ideaptr,.vx-rs .vx-rs-ideaptrbtn,
.vx-rs .vx-rs-offeredbtn,.vx-rs .vx-rs-clock,.vx-rs .vx-rs-daydate,
.vx-rs .vx-rs-dayhead,.vx-rs .vx-rs-zonetitle,.vx-rs .vx-rs-zonewhy{
  font-size:var(--vx-rs-fs)}
/* The caret is a glyph beside the title and reads at the title's size. */
.vx-rs .vx-rs-caret{font-size:var(--vx-rs-fs)}

/* ── THE GAP LINE: A QUESTION WITH TWO ANSWERS ────────────────────────
   It carries no panel, so both answers sit under the question in the content
   column rather than in face cells the row no longer has. */
.vx-rs-gapacts{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:6px 0 2px}
.vx-rs-gapacts > *{flex:0 0 auto}
.vx-rs-gaprow .vx-rs-what{flex:1 1 auto;display:block;min-width:0}
/* ⚑ THE ONE TITLE ON THE SHEET THAT WRAPS. The others are labels and are
   clipped to keep every row one height; this is a sentence, and clipping it to
   "No ride back yet for We…" removes the half that says WHO. */
.vx-rs-gaprow .vx-rs-gaptitle{white-space:normal;overflow:visible;text-overflow:clip;
  display:block}
/* T−0 is the spine, so it reads as one — a rule above and below rather than a
   colour, which would be the only saturated thing on a calm sheet. */
.vx-rs-row.is-anchor{border-top:1px solid rgba(44,74,62,.30);
  border-bottom:1px solid rgba(44,74,62,.30);background:rgba(44,74,62,.03)}
.vx-rs-cell-inc{display:flex;align-items:center;justify-content:center}
.vx-rs-inc{width:17px;height:17px;accent-color:var(--green,#2C4A3E);cursor:pointer;margin:0}
/* A FOLLOW-ON MOVE. Stephen 2026-08-09: "moves also on the master timeline" —
   so the 3:00p ride home is a line at 3:00p instead of hiding inside the 1:00p
   activity. It is not a decision of its own, so it carries a continuation mark
   where the checkbox sits and reads its group rather than asking again. */
.vx-rs-cont{font-size:.9rem;line-height:1;color:rgba(44,74,62,.32)}
/* A GROUP WITH NO WAY BACK, as a LINE where the ride back would be. Stephen
   2026-08-09 — it was a sentence under thirty rows, which is the least-read
   place in the product for its most expensive omission.
   GOLD, NOT RED. Nothing has gone wrong: this is the next useful thing to
   decide, and the charter forbids rendering it as a failure. */
/* ⚑ AND IT BELONGS TO THE ACTIVITY ABOVE IT, NOT BESIDE IT. Stephen,
   2026-08-15: "the ride-back warning should not be outside of the activity
   box." It was drawn as a peer row — same grid, same full-width separator — so
   a question about Blake's side read as its own line in the day, sitting
   between two unrelated activities.
   The server already places it one minute after the movement that stranded
   them, so the row above IS its subject. This says so: the separator above it
   is removed so the two share one block, and it is inset from the left so the
   nesting is visible rather than implied. The gold stays — it is the next
   decision, never a failure. */
.vx-rs-gaprow{background:rgba(200,169,110,.07);border-top:none;
  margin-left:26px;padding-left:8px;
  border-left:2px solid rgba(200,169,110,.45)}
/* The row it hangs from keeps no rule between them, so the pair reads as one
   activity with an open question inside it. */
.vx-rs-row:has(+ .vx-rs-gaprow){border-bottom:none}
/* TOO SMALL FOR A CHARTER — a fact, not a warning. It sits at the top of the
   same expand every row has, in the muted voice the sheet uses for everything
   it knows but is not telling you to act on. No colour: the couple is choosing
   convenience against cost and neither answer is the wrong one. */
.vx-rs-bulknote{margin:0 0 9px;padding:0 0 8px;
  border-bottom:1px solid rgba(44,74,62,.07);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;line-height:1.45;
  color:var(--text-mid,#4A4A4A)}
.vx-rs-bulknote-trade{display:block;margin-top:2px;color:var(--text-muted,#88928d)}
.vx-rs-gapmark{display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;border-radius:5px;border:1px dashed var(--gold,#C8A96E);
  font-size:.8rem;line-height:1;color:var(--gold-deep,#A07840)}
.vx-rs-gapclock{color:var(--text-muted,#88928d)}
.vx-rs-gaptitle{font-weight:500;color:var(--text-mid,#4A4A4A)}
/* ⚑ ITS OWN WIDTH, NOT THE CELL'S. width:100% filled the face column the gap
   line used to have; in the answers row it stretched to 306px and pushed the
   second answer onto its own line. */
.vx-rs-gapadd{width:auto;padding:4px 10px;min-height:30px;border-radius:7px;cursor:pointer;
  background:#fff;border:1px solid var(--gold,#C8A96E);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;font-weight:500;
  color:var(--gold-deep,#A07840);white-space:nowrap}
.vx-rs-gapadd:hover{background:var(--gold,#C8A96E);color:#fff}
.vx-rs-title.is-cont{font-weight:400;color:var(--text-muted,#88928d)}
.vx-rs-movelab{color:var(--text-muted,#88928d)}
.vx-rs-modeecho{display:inline-block;padding:4px 2px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.76rem;color:var(--text-muted,#88928d);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:100%}
.vx-rs-pin{font-family:var(--ff-m,'DM Mono',monospace);font-size:.55rem;letter-spacing:.06em;
  color:var(--green,#2C4A3E);font-weight:600;white-space:nowrap}
/* LEFT, as on the mockup. Right-justified, the times ended flush against the
   event names and every row began at a different x — the eye had nothing to run
   down. Stephen 2026-08-08: "the hours are right justified and not left
   justified in the view." */
.vx-rs-clock{font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;
  font-variant-numeric:tabular-nums;color:var(--green,#2C4A3E);text-align:left;
  /* A span like 11:30pm-1:30am is the longest thing this column ever holds; let
     it wrap and that one row is taller than every other on the sheet. */
  white-space:nowrap}
/* THE CLOCK IS THE FIELD NOW. Everything the offset column used to do — be
   typed into, be the cause the clock was the effect of — collapsed into the one
   control a couple was already reading. Two boxes were saying the same thing in
   two languages, and the language nobody speaks was the one you had to type in.

   THE RESTING STATE IS A BUTTON, so no form control exists for iOS to zoom to.
   Tapping swaps in a real input and iOS may zoom then, which is the moment it is
   welcome. The alternatives were all worse: maximum-scale=1 kills pinch-zoom,
   transform:scale breaks the hit target, and bumping to 16px on :focus is a
   trick whose behaviour varies by iOS version. */
/* ONE CELL, TWO THINGS: the field, and the fact beside it. The mark sits
   OUTSIDE the border — inside it read as a stray character in something you
   type into rather than as a statement about the row. Stephen 2026-08-09:
   "the dot should not be inside the time field." */
.vx-rs-when{display:flex;align-items:center;gap:6px;min-width:0}
.vx-rs-when > .vx-rs-clock{flex:0 0 auto;min-width:0}
/* ⚑ NO BOX. The clock was a bordered white button so a tap could swap in a real
   input without iOS zooming the page. Stephen 2026-08-17 made the face display
   only — "editable with the expanded block" — so there is no tap, no swap, no
   input, and nothing left for the border to promise. Six field-shaped boxes down
   the left of a sheet meant to be READ were the heaviest thing on it. */
.vx-rs-clock.is-pinned{color:var(--green,#2C4A3E);font-weight:500}
.vx-rs-whenin{width:100%;padding:4px 8px;min-height:30px;border-radius:7px;
  border:1px solid var(--green,#2C4A3E);background:#fff;
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;
  font-variant-numeric:tabular-nums;color:var(--green,#2C4A3E)}
.vx-rs-whenin:focus{outline:none;border-color:var(--green,#2C4A3E)}
/* A HELD LINE IS MARKED, QUIETLY. The dot states a fact about the row; it is not
   the control. Stephen 2026-08-09: "clicking on the [pin] or seeing the dot next
   to the time was hard to explain how to lock" — so the control moved into the
   details as a checkbox that says what it does in words. */
/* ALWAYS PRESENT, ALWAYS RIGHT OF THE TIME, so the difference between a held
   line and a moving one is a difference you can see rather than an absence you
   have to notice. `margin-left:auto` pins it to the far edge of the box on every
   row, which is what makes the column scannable — the times stay left justified
   and the marks line up on the right. */
.vx-rs-pinmark{flex:0 0 auto;font-size:.62rem;line-height:1;
  color:rgba(44,74,62,.28)}
.vx-rs-pinmark.is-held{color:var(--gold-deep,#A07840)}
.vx-rs-until{color:var(--text-muted,#88928d)}
/* AN EXCLUDED ROW KEEPS ITS CONTROLS. Stephen 2026-08-08: hiding them made the
   unchecked lines a different SHAPE from every other row, which reads as broken
   rather than as off. The whole row is already dimmed; that is what says it is
   not in the plan. */
.vx-rs-row.is-off .vx-rs-clock,
.vx-rs-row.is-off .vx-rs-mode{visibility:visible}

/* LOCK — one word, on the same line as the two places. Stephen 2026-08-09:
   'make "Does not move" just "lock" to keep on one row with the "Starts" and
   "Ends"'. The two-line explanation under the old checkbox was teaching a
   concept the tooltip can carry once a couple has met it. */
.vx-rs-holdbox{width:16px;height:16px;margin:0;flex:0 0 16px;
  accent-color:var(--green,#2C4A3E);cursor:pointer}
.vx-rs-holdlab-inline{flex:0 0 auto;cursor:pointer}
/* THE BOX AND ITS WORD ARE ONE CONTROL and read on one line. Every other
   .vx-rs-wlab stacks a caption over a field, and the phone rule that does so
   is a single class declared further down the sheet — so it won on order and
   put "Lock" UNDERNEATH its own checkbox. Two classes here, which wins on
   specificity wherever either rule happens to sit. */
.vx-rs-wlab.vx-rs-holdlab-inline{flex-direction:row;align-items:center;gap:6px}

/* ADD AN EVENT — the mockup's own row, examples and all, now finishing the job.
   TWO LINES: what and when on the first, where and who on the second. It used to
   be one line that produced an unfinished row — a name, an hour, and a route
   nobody had described going onto the manifest as though someone had. */
/* THE SAME COLUMNS AS A ROW, so the + sits under the checkboxes, the when under
   the whens and the name under the event names.
   ⚑ IT SAID THAT AND IT WAS NOT TRUE. The when column was 74px against a row's
   112px, so every clock on the sheet lined up except the one you type. The
   comment described the intention; these numbers now match .vx-rs-row.
   ⚑ AND NOW IT IS THE ROW'S OWN TRACK LIST, character for character, because
   the face finally holds the row's own four things: + / when / what / who.
   Change .vx-rs-row and this must change with it; a gate compares them. */
/* ⚑ AND THE ADD BOX FOLLOWS IT, TRACK FOR TRACK. Stephen's rule since
   2026-08-09 — the new-record form must look exactly like the rows it makes,
   or it reads as a form bolted to the bottom of a sheet. The row went to two
   tracks, so this does: clock and name on the face, and WHO moves down into
   the detail this box already had, exactly where the rows now keep it. */
/* Track for track with .vx-rs-row — the Add box IS a row, and a gate fails
   the build if they drift apart. Both lost the 76px clock column on
   2026-08-18 when the time moved into the panel. */
/* Track for track with .vx-rs-row — the Add box IS a row, and a gate holds them
   together. Both became flex lines on 2026-08-18 when the clock left the face. */
.vx-rs-add{display:flex;align-items:center;gap:12px;

  /* A NEW RECORD, NOT THE NEXT ROW. Stephen 2026-08-09: it "is hard to
     differentiate a new record from the last line of The Day After". The tint
     is the lightest thing that separates them — the sheet has no other
     saturated surface and should not gain one.
     ⚑ THE TINT IS PAINTED, NOT LAID OUT. The first version bought its
     breathing room with margin:-8px against padding:10px, which lines the
     columns up correctly and pushes the box 8px past the viewport on a 375px
     phone — scrollWidth 383 against clientWidth 375, a sideways scroll on the
     one screen that cannot afford one. A spread shadow in the same colour
     reaches outside the box WITHOUT joining the layout, so the padding stays
     at the row's own 2px and the columns still line up at every width.
     ⚑ NOT --green AT LOW ALPHA. #2C4A3E is so dark and desaturated that 5% of
     it over the cream page composites to hue 43° — amber, a warm grey. Raising
     the opacity made it WORSE (50°), because more of a near-neutral only
     deepens the cream. It needs a greener pigment at the same weight: this
     composites to 90° at chroma 8, against chroma 7 before. Green at last, and
     no louder. Measured, not eyeballed. */
  margin:14px 0 6px;padding:8px 2px;border-radius:10px;
  background:rgba(44,110,80,.09);box-shadow:0 0 0 8px rgba(44,110,80,.09)}
.vx-rs-add:focus-within{background:rgba(44,110,80,.13);
  box-shadow:0 0 0 8px rgba(44,110,80,.13)}
/* The button keeps its size; only its right edge is pinned to the × column. */
/* WHO RIDES SITS IN THE DETAIL NOW, beside the row's own — it is placed by the
   detail's flow rather than by a face column that no longer exists. */
.vx-rs-adddet .vx-rs-addwho{width:100%;min-width:0}
/* The action ends the detail line rather than sitting in the × column. */
.vx-rs-add .vx-rs-adddet .vx-rs-addbtn{grid-column:auto;margin-left:auto;width:auto;
  min-width:132px;flex:0 0 auto;align-self:end}
/* A DATE PICKER AND A TIME, not a sentence. The typed form stays on the rows,
   where you are nudging an hour you can already see; creating something is the
   case with nothing to nudge, and the one that has to reach outside the
   weekend. A calendar cannot be misread the way "Thu" was. */
.vx-rs-adddate{width:100%;min-height:30px;padding:4px 8px;border-radius:7px;text-align:left;
  border:1px solid rgba(44,74,62,.16);background:#fff;
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.76rem;
  color:var(--green,#2C4A3E)}
.vx-rs-adddate:hover{border-color:var(--gold,#C8A96E)}
/* ⚑ iOS IGNORES text-align ON A DATE INPUT. Safari paints the value inside a
   shadow element of its own, so `text-align:left` on the input styles nothing
   and the date sat centred on the phone while every other value on the sheet
   was left — Stephen, on the device: "no change". The pseudo-element below is
   the only handle iOS gives you, and -webkit-appearance:none is what stops the
   native control from re-centring it. The calendar button is its own
   pseudo-element and is untouched.
   NOT CATCHABLE IN THE HARNESS: it renders in a desktop engine emulating a
   phone, where the plain text-align works. Real-device only. */
.vx-rs-adddate{-webkit-appearance:none;appearance:none}
.vx-rs-adddate::-webkit-date-and-time-value{text-align:left;margin:0}
.vx-rs-adddate::-webkit-datetime-edit{text-align:left}
/* ONE LINE UNTIL THERE IS SOMETHING TO SAY. A five-control form was the last
   thing on a sheet whose whole argument is that a line is one line. Closed it
   is an invitation; the moment they touch a field it becomes the form that
   stops them having to come back. */
/* ⚑ WIDE: ALWAYS THERE. The face is the row's own four columns and the detail
   line is one line beneath it, so the whole thing is the height of an open
   activity and reads as the next line waiting rather than as a form that
   unfolds. Stephen 2026-08-09: "the Add area is always expanded... it has
   never been one line."
   NARROW: ONE LINE UNTIL TAPPED — see the phone block far below. Stacked, the
   same seven controls are taller than the screen and push the Add button off
   the bottom, which is the state his 9:43 screenshot caught. */
.vx-rs-adddet{display:flex}
.vx-rs-addplus{text-align:center;font-size:1.05rem;color:var(--green,#2C4A3E)}
/* Left justified like every time on the sheet above it. Stephen 2026-08-09:
   "for consistency of date & time always left justified." It was right aligned
   back when it held a signed offset, where the sign wanted to be flush. */
.vx-rs-add .vx-rs-addat{grid-column:1;width:100%;min-height:30px;text-align:left}
/* AT REST IT IS A ROW TITLE, not a field: same font, same weight, same colour,
   no box at all. A border appears when it is hovered or being typed into, which
   is the only moment it needs to look like an input. */
/* ⚑ THE WRAPPER IS THE GRID ITEM NOW, not the input. Stephen 2026-08-17: the
   description "scrolls off the screen" — an input clips its placeholder at one
   line and cannot wrap, so the examples that teach a couple what belongs on a
   run sheet were the part being cut. They sit under the field instead, free to
   take a second line, and the field keeps a prompt short enough to always fit. */
.vx-rs-addnamewrap{grid-column:2;min-width:0;display:flex;flex-direction:column;gap:2px}
.vx-rs-addnamewrap .vx-rs-addname{grid-column:auto;width:100%}
.vx-rs-addhint{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.68rem;
  line-height:1.35;color:var(--text-muted,#88928d);padding:0 2px}
.vx-rs-addname{grid-column:2;min-width:0;padding:4px 8px;min-height:30px;border-radius:7px;
  border:1px solid transparent;background:transparent;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;font-weight:500;
  color:var(--text-mid,#4A4A4A)}
.vx-rs-addname::placeholder{font-weight:400;color:var(--text-muted,#88928d)}
.vx-rs-addname:hover{border-color:rgba(44,74,62,.16);background:#fff}
.vx-rs-addname:focus{border-style:solid;border-color:var(--green,#2C4A3E);
  background:#fff;outline:none}
/* Sized like the group picker it sits under, not like a call to action — the
   row is one line of controls, and a big pill made the whole block read as a
   separate form pinned to the bottom of the sheet. */
.vx-rs-addbtn{width:100%;padding:4px 10px;min-height:30px;border-radius:7px;
  cursor:pointer;background:var(--green,#2C4A3E);border:1px solid var(--green,#2C4A3E);
  color:#fff;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500}
.vx-rs-addbtn:hover{background:var(--gold-deep,#A07840);border-color:var(--gold-deep,#A07840)}
/* THE SECOND LINE — where it starts, where it ends, who is in it, and whether it
   holds its own time. Indented to the when column so it reads as belonging to
   the line above rather than as a form of its own. */
/* THE DETAIL LINE IS A .vx-rs-where. It carries the open row's own class, so
   Starts at / Ends at / Lock cannot drift into a second look — which is what
   FROM / TO / WHO in small caps above their boxes had already become. */
.vx-rs-adddet{grid-column:2 / -1;margin:2px 0 0}
/* STILL USED BY THE EXCURSION ADD ROW, whose two fields — When, Kind of place —
   have no twin on an open activity and so keep the stacked-label form. Deleting
   these with the plan form's copy left that row unstyled and it rendered fine
   in the gate, which reads markup rather than layout. */
.vx-rs-addlab{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1 1 150px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.66rem;letter-spacing:.04em;
  text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-rs-addsel{width:100%;min-width:0;min-height:30px;padding:4px 8px;border-radius:7px;
  border:1px solid rgba(44,74,62,.16);background:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;letter-spacing:0;
  text-transform:none;color:var(--text,#2A2E2C)}
.vx-rs-addsel:hover{border-color:var(--gold,#C8A96E)}
@media (max-width:760px){
   /* ⚑ THE ADD BOX FOLLOWS THE ROW. It restated a two-column grid at phone
      width — 76px for the clock, one track for the name. Both it and the row
      became flex lines when the clock moved into the panel, so a grid template
      here is inert and the areas below name tracks that no longer exist.
      Wrapping is what puts the detail line underneath now. */
   .vx-rs-add{flex-wrap:wrap;row-gap:6px;column-gap:8px;padding:9px 2px}




  /* NO `grid-column:auto` HERE. `grid-area` already sets the column, and
     resetting it afterwards auto-placed the when field and the whole detail
     block into the 26px + column — 26px wide, unusable, and it rendered without
     erroring. The desktop rules above place by grid-column, so every one of
     them needs its area named here or it keeps the desktop column number. */
  .vx-rs-addplus{grid-area:plus;align-self:start;margin-top:4px}
  /* ⚑ NO `grid-column:auto` AFTER `grid-area`. It resets the column the area
     just set, and the field auto-places into the 26px + column — 26px wide,
     unusable, and it renders without erroring. This is the SECOND time these
     rules have been caught by it; the desktop block places by grid-column, so
     every field needs its area named here and nothing after it. */
  .vx-rs-adddate{font-size:1rem}
  .vx-rs-add .vx-rs-addat{grid-area:at;width:100%;font-size:1rem}
  /* ON DESKTOP THIS IS THE ROW'S TITLE and carries no border, because the
     titles it sits under carry none either. On a phone it leads the box, and a
     borderless line of grey text at the top of a tinted panel reads as a
     heading rather than as the field you are meant to fill in first. */
  .vx-rs-add .vx-rs-addnamewrap{grid-area:name}
  .vx-rs-add .vx-rs-addname{font-size:1rem;
    border-color:rgba(44,74,62,.16);background:#fff}
  .vx-rs-adddet .vx-rs-addwho{font-size:1rem}
  /* COLLAPSED IS GENUINELY ONE LINE — not the face plus a hidden detail. The
     when and the who stack on a phone too, so leaving them visible makes the
     "collapsed" state three rows tall and saves nothing worth having. */
  /* ⚑ ONLY THE DETAIL HIDES NOW. This was a three-selector list that also hid
     the hour and the who; the who moved into the detail on 2026-08-17 and the
     hour is on the face, so hiding it would leave a form with no time in it.
     (Removing the third selector and leaving its comma made the whole list
     invalid, which CSS does silently — the same shape as an unresolved var()
     deleting a property. Caught by measuring the live grid, not by reading.) */
  .vx-rs-add:not(.is-open) .vx-rs-adddet{display:none}
  /* AND THE HIDDEN ROWS MUST STOP PAYING RENT. grid-template-areas keeps its
     tracks whether or not anything occupies them, so an empty row still charges
     a row-gap: box around a 31px field. */
  .vx-rs-add:not(.is-open){padding:10px 2px;row-gap:0;
    grid-template-areas:"at name"}
  /* The × column has no meaning once the face is stacked, and leaving the
     spacer at column 5 spawns three empty implicit tracks. */
  .vx-rs-addend{display:none}
  .vx-rs-add .vx-rs-adddet .vx-rs-addbtn{width:100%;margin-left:0;
    min-width:136px;min-height:34px}
  .vx-rs-adddet{grid-area:det}
  /* One per line on a phone — three side by side clip their own option text,
     and a picker you cannot read the current value of is worse than a scroll. */
  .vx-rs-addlab{flex:1 1 100%}
  .vx-rs-addsel{font-size:1rem}
  .vx-rs-addgap{display:none}
  .vx-rs-addname{grid-area:name;font-size:1rem}
  .vx-rs-addbtn{grid-area:btn;justify-self:end;width:auto;min-width:136px;min-height:34px}
  /* ── ⚑ "+ ADD A TRIP" ON A PHONE: ONE COLUMN, AND 16px LIKE EVERYTHING ELSE ──
     Stephen 2026-08-26, from his phone: the TITLE label rendered as "TLE" with
     its input overflowing the panel.

     MEASURED in his Chrome: the Title input computed 16px while every field
     beside it computed 9px. `.vx-rs-newtrip .vx-rs-addname` pins 9px at 0,0,2,0 —
     and `.vx-rs-add .vx-rs-addname{font-size:1rem}`, thirty lines above this,
     is ALSO 0,0,2,0 and comes later, so it won on source order alone. The new
     trip form lives inside `.vx-rs-add`, so the old adder's mobile rule reaches
     into it. Same shape as every other decision this codebase has lost to a
     tie broken by position rather than intent.

     ⚑ AND 1rem IS THE RIGHT ANSWER, NOT THE BUG. Every control in this block
     is 1rem on purpose: iOS Safari zooms the whole page when you focus an input
     under 16px. Shrinking the Title to match its 9px neighbours would have
     "fixed" the mismatch by reintroducing the zoom on every field.

     So the fields all go UP to 16px and the row STACKS — two 16px inputs and
     their labels do not share 261px of phone, which is the clipping he
     photographed. */
  /* ⚑ AND IT MOVES WITH THE STOP PANEL, ALWAYS. Stephen asked for the create
     form to BE the stop panel — "the 'Add a stop' format should be the
     standard" — so a size that applies to one and not the other is the split
     this pair has already been fixed out of once. Same token, so there is one
     decision here rather than two numbers. The stacking above is unaffected: it
     is about two fields sharing 261px, not about which size they are. */
  .vx-rs-newtrip input,
  .vx-rs-newtrip select,
  .vx-rs-newtrip .vx-rs-addname{font-size:1rem}
}
.vx-rs-what{min-width:0;display:flex;align-items:baseline;gap:8px;overflow:hidden}
.vx-rs-title{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-trip,.8125rem);
  font-weight:500;color:var(--text-mid,#4A4A4A);line-height:1.35;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The span an activity runs over, and the way into its movements. */
/* 2026-08-08 (Stephen) — PINNED HOURS. A pinned row keeps its clock when the
   ceremony moves, so its offset becomes the derived number and reads as one.
   Only the pinned state is styled: the ordinary sheet is unchanged, because
   dimming the clock on every unpinned row would dim nearly every row on a
   sheet whose whole job is to be read by time. */
.vx-rs-moved{margin:0 0 8px;padding:8px 12px;border-radius:8px;
  background:rgba(58,107,89,.06);border:1px solid rgba(58,107,89,.16);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;line-height:1.5;
  color:var(--text-mid,#4A4A4A)}
/* STILL NO `font:inherit` ANYWHERE ON THE CLOCK. It is declared after
   .vx-rs-clock and carries the same specificity, so the shorthand would win and
   reset family, size and font-variant-numeric back to the row's DM Sans —
   losing the tabular figures that keep the time column aligned, which is most
   of what makes the sheet scannable. That cost an afternoon once.
   THE CLOCK'S OWN RULES LIVE ABOVE. A second .vx-rs-clock
   block down here used to reset background, border and padding to none, and
   being later it would silently undo the field the couple now types into — the
   more-specific-winner trap this file has been caught by before. */

/* JUST THE CARET, at the size of the words beside it. "2 moves" was our unit
   on their sheet — a movement is how an operator quotes and how the fleet is
   solved, and it answers a question no couple asked. What they want from this
   control is "there is more in here". */
.vx-rs-legs{flex:0 0 auto;width:22px;height:22px;padding:0;border-radius:6px;
  cursor:pointer;background:none;border:1px solid transparent;
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;
  color:var(--text-muted,#88928d)}
.vx-rs-legs:hover{border-color:rgba(44,74,62,.18)}
.vx-rs-legs:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
/* The caret is what makes it read as a control. Rotating rather than swapping
   glyphs so the open and shut states are obviously the same button. */
.vx-rs-caret{display:inline-block;transition:transform .12s ease}
.vx-rs-legs.is-open{border-color:rgba(44,74,62,.35);color:var(--green,#2C4A3E)}
.vx-rs-legs.is-open .vx-rs-caret{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.vx-rs-caret{transition:none}}
/* ⚑ THE STOPS SIT UNDER THE TRIP'S OWN TITLE. Stephen 2026-08-19: "there is
   more room to move the data left and align under the left edge of the Trip
   title." This indented the whole list 96px — a third of a phone's width spent
   on hierarchy that the marker column and the panel's own indent already carry,
   and it was pushing the place names into an ellipsis they did not need.

   The marker HANGS in that 2px gutter so the two place names line up with the
   trip's title above them, which is the alignment he asked for rather than
   merely a smaller gap. */
.vx-rs-leglist{padding:4px 0 10px 20px;border-bottom:1px solid rgba(44,74,62,.08)}
.vx-rs-leglist .vx-rs-leaveat{margin-left:-20px}
/* WHERE IT STARTS AND ENDS, above the movements it needs. Two labelled
   selects rather than a form: the couple is correcting two facts, not filling
   anything in. */
/* The movements block is always drawn, so every expanded row is the same two
   blocks in the same order. An empty one says so rather than ending the box
   early — a section that vanishes teaches the couple to expect a different
   shape each time they open a line. */
.vx-rs-legs-list{margin:6px 0 0}
.vx-rs-legnone{margin:0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;
  color:var(--text-muted,#88928d)}
/* THE NAME, EDITABLE WHERE THE REST OF THE ACTIVITY'S FACTS ARE. It sits above
   the two places because it is what the line IS, and they are where it goes. */
.vx-rs-rename{display:flex;align-items:center;gap:7px;margin:0 0 8px;min-width:0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.68rem;letter-spacing:.04em;
  text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-rs-renamein{flex:1 1 auto;min-width:0;max-width:320px;min-height:30px;padding:4px 8px;
  border-radius:7px;border:1px solid rgba(44,74,62,.16);background:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--text,#2A2E2C)}
.vx-rs-renamein:hover{border-color:var(--gold,#C8A96E)}
.vx-rs-renamein:focus{border-color:var(--green,#2C4A3E);outline:none}
.vx-rs-where{display:flex;flex-wrap:wrap;gap:10px 16px;margin:0 0 8px}
.vx-rs-wlab{display:flex;align-items:center;gap:7px;min-width:0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-eyebrow,.62rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d);
  /* "Starts at" is two words and was breaking across two lines beside a
     control that is one line tall. */
  white-space:nowrap}
/* ⚑ A STOP'S OWN ANSWERS, indented under the place they belong to. They are
   facts ABOUT that leg — who is aboard, and when — so they must not read as
   further stops in the stack. The rule above draws the connector, so this sits
   inside it rather than beside it. */
/* ── ⚑ ONE STOP IS ONE BLOCK ─────────────────────────────────────────────
   Stephen 2026-08-18: "there are field misalignments in this form. We need to
   group all of the elements for the trip together and then add the next stop."

   The fields were siblings of the connector rail, so each one set its own width
   and they stepped in and out down the column. Now every stop is a single grid:
   the inherited "from" line, the destination, who is aboard, and when — all on
   one left edge, all one width. */
/* ⚑ THE × ON THE ROW FACE. At the far end from the expand arrow, quiet until
   reached for — deleting is not the thing this row is for, it is the thing you
   occasionally need. Everything removed is restorable from the foot of the
   sheet, so a stray thumb costs nothing. */
.vx-rs-facedel{margin-left:auto;order:99;flex:0 0 auto;appearance:none;background:none;
  border:0;cursor:pointer;padding:2px 4px;line-height:1;
  font-size:var(--fs-cat-title,.9rem);
  color:var(--text-muted,#b3b9b4);transition:color .15s}
.vx-rs-facedel:hover{color:#b94040}
/* Bigger tap target on a phone without taking more room on the line. */
@media (max-width:560px){ .vx-rs-facedel{padding:6px 8px;margin-right:-4px} }
.vx-rs-stopblock{align-items:start}
.vx-rs-stopgrid{grid-column:2/-1;display:grid;gap:6px 10px;
  grid-template-columns:minmax(0,1fr) minmax(0,auto);min-width:0}
.vx-rs-stopgrid > label{min-width:0}
.vx-rs-stopgrid .vx-rs-wsel,.vx-rs-stopgrid .vx-th-time{width:100%;max-width:none}
/* The leg it starts from, stated rather than asked — it is the previous stop's
   destination and a couple should never have to retype it. */
/* ── ⚑ ON THE BUDGET CARD'S SCALE ────────────────────────────────────────
   Stephen 2026-08-18: "please make sure the style, fonts and font sizes are the
   same as the Budget card, for that is a simple design."

   The stop block had grown a dozen ad-hoc sizes — .68rem, .72rem, .66rem, 10.5px,
   11.5px, 12.5px — each chosen for the line it was on. The Budget card has four
   named tokens and uses nothing else, and that discipline IS the simplicity:

     --fs-cat-title  .9rem   the thing a row is about
     --fs-caption    .78rem  values, names, the words you read
     --fs-eyebrow    .62rem  labels above a field
     --ff-b          DM Sans everything

   Every rule below is one of those four. No new sizes. */
.vx-rs-stoplab{font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:var(--fs-eyebrow,.62rem);letter-spacing:.02em;
  color:var(--text-muted,#88928d);flex:0 0 auto}
/* Where the chain already knows the answer, it says so instead of asking —
   a caption, because it is something we are telling them. */
.vx-rs-stopderived,.vx-rs-stopempty{grid-column:1/-1;margin:1px 0 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-eyebrow,.62rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d)}
.vx-rs-stopempty{font-style:italic}
/* The chain has to END somewhere, and saying so is the difference between a plan
   a couple has finished and one they abandoned half-built. */
.vx-rs-stopend{grid-column:1/-1;margin:6px 0 0;padding-top:6px;
  border-top:1px solid var(--border,#eae5dd);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-eyebrow,.62rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d)}
.vx-rs-stopwho{grid-column:2/-1;display:flex;flex-wrap:wrap;align-items:center;
  gap:6px 12px;margin:4px 0 2px}
.vx-rs-stopwho .vx-rs-wsel{max-width:190px}
.vx-rs-stoptime{padding:4px 6px;min-height:30px;border-radius:7px;background:#fff;
  border:1px solid rgba(44,74,62,.16);font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:var(--fs-caption,.78rem);color:var(--text,#2F3B35)}
.vx-rs-stoptime:focus{border-color:var(--green,#2C4A3E);outline:none}
/* The switch between "leave at" and "arrive by" is a change of MEANING, not a
   command, so it reads as a link rather than competing with the row's buttons. */
.vx-rs-stopmode{background:none;border:0;padding:2px 0;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-eyebrow,.62rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d);text-decoration:underline;
  text-underline-offset:2px}
.vx-rs-stopmode:hover{color:var(--green,#2C4A3E)}
@media (max-width:430px){
  .vx-rs-stopwho{gap:4px 8px}
  .vx-rs-stopwho .vx-rs-wsel{max-width:100%}
}
/* ⚑ THE STEP THAT TURNS A PLAN INTO A SHORTLIST. Moved from Plan to Compare
   2026-08-21 — the search fills the table below it, so it now sits at the TOP
   of the tab it feeds rather than at the bottom of the one it left. Margins
   flipped to match: the space belongs under the card, above the grid.
   Full width on a phone because it is the next thing to do. */
.vx-tp-findops{margin:0 0 18px;padding:16px;border-radius:12px;
  background:rgba(200,169,110,.07);border:1px solid rgba(200,169,110,.28)}
/* ⚑ LEAN, ONCE THE CARDS CARRY THE EXPLAINING. 2026-08-22. The card was 180px
   of button plus a paragraph about what the search does and why to call early.
   The Find surface now says that where it matters — the depth line before the
   list, and each operator's own sources beside each fact — so the paragraph is
   the same sentence twice and it sits between a couple and the answer. */
.vx-tp-findops.is-lean{padding:0;background:none;border:0;margin:0 0 10px}
.vx-tp-findops.is-lean .vx-tp-findnote{display:none}
.vx-tp-findops.is-lean .vx-tp-findbtn{padding:8px 16px;font-size:.82rem}
/* ⚑ INLINE-FLEX SO THE SPINNER SITS BESIDE THE WORDS — 2026-09-09.
   Stephen, testing: "the Find Operators button on the 'plan' shifts to two
   lines when a spinner is active." `.ai-spinner` is a DIV with a width and a
   height, and this button was `inline-block`, so the spinner took a line of its
   own and the label dropped underneath it — a control that changes SHAPE the
   moment it is pressed, which is the opposite of the calm the press is meant to
   buy. The house pattern injects that div on every AI action, so the button has
   to be able to hold it. */
.vx-tp-findbtn{appearance:none;border:0;border-radius:999px;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:11px 22px;background:var(--green,#2C4A3E);color:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.92rem;font-weight:500;
  letter-spacing:.01em;transition:background .15s,transform .12s}
.vx-tp-findbtn:hover:not(:disabled){background:#22392f;transform:translateY(-1px)}
.vx-tp-findbtn:disabled{opacity:.55;cursor:default;transform:none}
/* The sentence explains the whole workflow in one breath — search, check the
   dates, send the manifest — so a couple knows what the press starts. */
.vx-tp-findnote{margin:10px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.78rem;line-height:1.5;color:var(--text-muted,#88928d);max-width:52ch}
@media (max-width:430px){ .vx-tp-findbtn{width:100%} }

/* ── ⚑ THE SEARCH CONTROL UNDER THE COMPARE GRID — 2026-09-09 ──────────
   Stephen: the button "should be at the bottom and be refresh list". It moved
   out of the lede and into its own foot, and the foot shipped with NO RULE AT
   ALL — a green button flush against the bottom edge of the table, no gap, no
   alignment. Caught by a gate author reading the markup, not by any assertion:
   every gate here proves the button EXISTS and WORKS, and none of them can see
   that it is touching the grid. Styling is still the thing this repo verifies
   with its eyes.

   ⚑ THE SPACING IS THE RETIRED CONTAINER'S, not a new opinion. `.vx-tp-findops`
   carried `margin:0 0 18px` above the trips; the same 18px now sits ABOVE the
   button instead of below it, because the control follows its table rather than
   introducing the next thing. */
.vx-tp-findfoot{margin:18px 0 4px;display:flex;justify-content:center}
/* Full-width on a phone matches .vx-tp-findbtn's own 430px rule — a centred
   pill and a full-width pill disagreeing about the same breakpoint is how a
   button ends up centred inside a container it already fills. */
@media (max-width:430px){ .vx-tp-findfoot{display:block} }
/* ⚑ WHAT THE CURRENT ANSWER BUYS, beside the picker rather than inside it.
   Stephen 2026-08-18: "I know if my choice results in needing 5 vehicles."
   Read-only and quiet — the select is the writer; this is the consequence. It
   is deliberately NOT a pill: a pill reads as a state to act on, and there is
   nothing here to press. */
/* ⚑ HOW THIS TRIP RUNS, ON THE TRIP ITSELF. Replaces `.vx-rs-onetrip`, whose
   checkbox was retired 2026-08-27 when the choice moved onto the trip — the
   rules for it are gone with it rather than left behind styling nothing.

   ⚑ AND THE SELECT DECLARES 16px OUTRIGHT. This row is NOT inside
   `.vx-rs-movebody`, so it does not inherit that panel's mobile lift, and an
   input under 16px force-zooms iOS on focus — the bug that threw the plan out
   of frame this morning. ios-input-zoom-validate discovers surfaces rather than
   naming them now, so this would have been caught; declaring it is cheaper than
   being caught. */
.vx-rs-shaperow{display:block;padding:2px 0 10px}
.vx-rs-shaperow .vx-rs-mlab{display:flex;flex-direction:column;gap:3px}
.vx-rs-shaperow .vx-rs-mlab > span{
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-stopdet,.5625rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d);white-space:nowrap}
.vx-rs-shaperow select{width:100%;min-width:0;font-size:1rem;min-height:38px}
.vx-rs-wfleet{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:var(--fs-eyebrow,.62rem);
  letter-spacing:.02em;color:var(--text-muted,#88928d);white-space:nowrap;
  align-self:center;padding-left:2px}
.vx-rs-wsel{min-width:0;max-width:230px;padding:4px 6px;min-height:30px;border-radius:7px;
  cursor:pointer;background:#fff;border:1px solid rgba(44,74,62,.16);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.75rem;color:var(--text-mid,#4A4A4A)}
.vx-rs-wsel:hover{border-color:var(--gold,#C8A96E)}
/* Where the list comes from, and the way out when a place is not on it. */
.vx-rs-wnote{margin:2px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.68rem;color:var(--text-muted,#88928d)}
.vx-rs-wadd{padding:1px 8px;margin-left:2px;border-radius:100px;cursor:pointer;
  background:none;border:1px solid rgba(44,74,62,.22);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.68rem;
  color:var(--green,#2C4A3E)}
.vx-rs-wadd:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
@media (max-width:760px){
  .vx-rs-where{flex-direction:column;gap:8px}
  .vx-rs-wlab{align-items:flex-start;flex-direction:column;gap:3px}
  .vx-rs-wsel{width:100%;max-width:none;font-size:1rem;min-height:34px}
}
.vx-rs-leg{display:flex;gap:12px;padding:3px 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;color:var(--text-muted,#88928d)}
.vx-rs-legclock{flex:0 0 68px;font-family:var(--ff-m,'DM Mono',monospace);
  font-variant-numeric:tabular-nums;text-align:right}
.vx-rs-legname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:760px){ .vx-rs-leglist{padding-left:20px} }
.vx-rs-row.is-anchor .vx-rs-title{color:var(--green,#2C4A3E);font-weight:600}
/* EVERY LINE IS A MOVEMENT. Stephen 2026-08-08: "why is there a difference
   between a 'suggestion' and a movement? Everything is a movement and the check
   includes the movement in the manifest or it is excluded."
   He is right, and the distinction was mine leaking out: whether a line already
   has a priced stage behind it is an implementation detail, not something a
   couple should be able to see. The lighter treatment for a suggested event is
   gone — one appearance, one vocabulary, and the checkbox is what decides
   whether it reaches the operator. */

/* HOW THEY GET THERE. Quiet until it is touched — it is on every row, so a
   bordered control on each one would read as fifteen unanswered questions
   rather than fifteen answers already given. */
.vx-rs-cell-mode{min-width:0}
/* THE SAME SHAPE AS THE HOUR BOX BESIDE IT — same padding, radius, height and
   text size. They were 25px/3px/r6/.78rem against 30px/4px/r7/.72rem, which is
   two controls on one line pretending to be different kinds of thing. */
.vx-rs-mode{width:100%;padding:4px 6px;min-height:30px;border-radius:7px;cursor:pointer;
  background:#fff;border:1px solid rgba(44,74,62,.16);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;color:var(--text-mid,#4A4A4A)}
.vx-rs-mode:hover{border-color:var(--gold,#C8A96E)}
/* Driving themselves is an ANSWER, not an omission. It gets the gold the rest
   of the product uses for a couple's own decision — never grey, which would
   read as "we could not price this". */
.vx-rs-row.is-selfdrive .vx-rs-mode{border-color:rgba(200,169,110,.55);
  background:rgba(200,169,110,.09);color:var(--gold-deep,#A07840)}

/* The ×. Quiet until hovered, and a full row away from the checkbox — the two
   controls mean opposite things and must never be neighbours on a phone. */
.vx-rs-del{width:26px;height:26px;padding:0;border:1px solid transparent;border-radius:6px;
  cursor:pointer;background:none;line-height:1;font-size:1rem;color:var(--text-muted,#88928d)}
.vx-rs-del:hover{color:#A5301E;border-color:rgba(165,48,30,.28)}
/* The gap row's second answer. A quiet text button rather than a glyph,
   because "they are making their own way back" cannot be said in an x and a
   title= cannot be read on a phone. Sits beside "Add the ride back" so the row
   reads as the question it is. */
.vx-rs-gapno{appearance:none;background:none;border:1px solid transparent;border-radius:6px;
  padding:4px 8px;cursor:pointer;white-space:nowrap;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;
  color:var(--text-muted,#88928d);text-decoration:underline;text-underline-offset:3px}
.vx-rs-gapno:hover{color:var(--green,#2C4A3E);border-color:rgba(44,74,62,.18);text-decoration:none}

/* ── The transport totals strip ───────────────────────────────────────
   Stephen, 2026-08-11: "I really want it like the Budget card and locked as a
   third menu on the header so it is always visible."

   So it is the SAME object as .vx-budget-totals-strip, one tab over: full
   bleed out of the card's padding, one line, label beside value, dividers
   between. A rounded box with stacked captions read as a card sitting in the
   content; this reads as chrome, which is what a locked bar has to do.

   ⚑ IT PINS UNDER THE TAB STRIP, not under the header. Budget has no tab strip
   so its bar sits at --vx-chrome-bottom; this one has the guide's phase-nav
   above it and would otherwise hide behind it. That second offset is MEASURED
   into --vx-tp-nav-h from the real element — hardcoding it is the drift
   --vx-chrome-bottom exists to end, and it would be wrong the moment the tabs
   wrap to two lines on a phone. */
/* ⚑ THE HOST STICKS, NOT THE BAR — and this is the whole bug Stephen saw as
   "the menu does not lock like the Budget". A sticky element travels only
   within its PARENT'S box, and the bar's parent is a host whose height is
   exactly the bar's height. Zero travel, so it never stuck: it scrolled away
   like ordinary content while every offset in the stylesheet was correct.
   Putting the stickiness on the host makes rootEl the parent, which is the
   whole guide, which is the distance it needs.

   IMMEDIATELY UNDER THE VERA ROW — the same slot the Budget bar takes on its
   own tab — and the tab strip moves down to sit under THIS. That only works
   because the host is drawn before the nav in the DOM: sticky holds an element
   at or below its natural position and can never lift it above something that
   precedes it. */
#vxTpTotalsHost{
  position:sticky;
  top:var(--vx-chrome-bottom);
  z-index:26;
}
#vxTpTotalsHost:empty{display:none}
/* ⚑ THE TOTALS STRIP'S OWN STYLING WENT WITH IT, 2026-08-26. The bar it
   dressed (TRIPS / USAGE HOURS / ADDITIONAL HOURS / FLEET) was retired — see
   the note in interviews/verdeaux-interview.js where _rsTotalsStrip stood.

   ⚑ `#vxTpTotalsHost` ABOVE STAYS, AND SO DOES ITS `:empty{display:none}`.
   The host is still drawn before the tab strip and still measured into
   `--vx-tp-totals-h`, which the sticky offsets below read. An empty host is 0
   tall, which is precisely what those offsets want — removing the element
   would make every one of them fall back to a constant that goes stale. */
@media (max-width:480px){ .vx-rs-gapno{font-size:.68rem;padding:4px 4px} }
/* EXCURSION IDEAS — a menu, not a second plan. It is deliberately quieter than
   the sheet above it: no checkboxes, no clocks, no vehicle question. Those are
   what a line earns by being chosen. */
.vx-rs-ideas{margin:26px 0 0;padding:16px 0 0;border-top:1px solid rgba(44,74,62,.12)}
.vx-rs-ideahead{margin:0 0 12px}
/* ⚑ ON PREP THE SECTION IS THE HEADING. The table moved off Plan the day
   (Stephen 2026-08-16 — it "made the 'Plan' too long to scroll on mobile"), and
   there it sits directly under its own h3, so the rule that separated it from
   the sheet above would be a line under a title. */
#vx-tp-ideas .vx-rs-ideas{margin-top:8px;padding-top:0;border-top:none}
#vx-tp-ideas.is-saving{opacity:.6;transition:opacity .12s ease}
/* THE POINTER LEFT BEHIND. A door that moves and leaves no sign is a feature
   that has quietly gone — and this is the only way to write down a seventh
   idea. Reads as a sentence, not a call to action. */
.vx-rs-ideaptr{margin:22px 0 0;padding:14px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.76rem;line-height:1.5;color:var(--text-muted,#88928d);
  border-top:1px solid rgba(44,74,62,.12)}
.vx-rs-ideaptrbtn{padding:0;border:0;background:none;cursor:pointer;
  font-family:inherit;font-size:inherit;font-weight:600;
  color:var(--gold-deep,#A07840);text-decoration:underline;text-underline-offset:2px}
.vx-rs-ideaptrbtn:hover{color:var(--green,#2C4A3E)}
@media(pointer:coarse){
  /* His users are on phones; an underlined word in a paragraph is a 16px
     target. The line-box grows, the sentence does not break. */
  .vx-rs-ideaptrbtn{display:inline-block;min-height:44px;line-height:44px}
}
.vx-rs-idealede{margin:3px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.74rem;line-height:1.45;color:var(--text-muted,#88928d)}
.vx-rs-idearows{display:flex;flex-direction:column}
.vx-rs-idearow{display:grid;grid-template-columns:minmax(120px,1fr) 132px 116px 116px 26px;
  gap:10px;align-items:center;padding:8px 0;border-bottom:1px solid rgba(44,74,62,.07)}
.vx-rs-ideaname{min-width:0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.85rem;
  color:var(--text,#2A2E2C);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vx-rs-ideawhen,.vx-rs-ideawho{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;
  color:var(--text-muted,#88928d);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vx-rs-ideaadd{justify-self:end;padding:4px 12px;min-height:30px;border-radius:100px;cursor:pointer;
  background:#fff;border:1px solid rgba(44,74,62,.28);font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.7rem;font-weight:500;color:var(--green,#2C4A3E);white-space:nowrap}
.vx-rs-ideaadd:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
/* Only the couple's own ideas carry a ×; ours keep the column so the buttons
   still line up. An empty slot rather than a shifted row. */
.vx-rs-ideadel{width:26px;height:26px;padding:0;border:1px solid transparent;border-radius:6px;
  cursor:pointer;background:none;line-height:1;font-size:1rem;color:var(--text-muted,#88928d)}
.vx-rs-ideadel:hover{color:#A5301E;border-color:rgba(165,48,30,.28)}
.vx-rs-ideadel.is-empty{display:inline-block;cursor:default}
/* ADD AN IDEA — quieter than the sheet's Add row, because what it produces is a
   note rather than a line of the weekend. No hour: an idea nobody has agreed to
   does not get a clock, and that is the whole difference between the two
   tables. */
.vx-rs-ideaadd-row{display:grid;grid-template-columns:26px minmax(120px,1fr) 150px 150px 116px;
  gap:10px;align-items:end;margin:12px 0 0;padding:9px 2px}
.vx-rs-ideaadd-row .vx-rs-addplus{align-self:center}
.vx-rs-ideaadd-row .vx-rs-addnamewrap{grid-column:auto;align-self:center}
.vx-rs-ideaadd-row .vx-rs-addname{grid-column:auto}
.vx-rs-ideaadd-row .vx-rs-addlab{flex:1 1 auto}
.vx-rs-ideaadd-row .vx-rs-addbtn{grid-column:auto}
@media (max-width:760px){
  .vx-rs-ideaadd-row{grid-template-columns:26px minmax(0,1fr);
    grid-template-areas:"plus name" ".    when" ".    kind" ".    btn";
    row-gap:6px;column-gap:8px}
  .vx-rs-ideaadd-row .vx-rs-addplus{grid-area:plus;align-self:start;margin-top:4px}
  .vx-rs-ideaadd-row .vx-rs-addnamewrap{grid-area:name}
  .vx-rs-ideaadd-row .vx-rs-addname{font-size:1rem}
  .vx-rs-ideaadd-row .vx-rs-addlab:nth-of-type(1){grid-area:when}
  .vx-rs-ideaadd-row .vx-rs-addlab:nth-of-type(2){grid-area:kind}
  .vx-rs-ideaadd-row .vx-rs-addbtn{grid-area:btn;justify-self:end;width:auto;
    min-width:136px;min-height:34px}
}
/* On a phone the name takes the line and the two facts sit under it, with the
   button holding the right edge — the same shape the sheet's rows collapse to,
   so the two tables still read as one page. */
@media (max-width:760px){
  .vx-rs-idearow{grid-template-columns:minmax(0,1fr) auto 26px;
    grid-template-areas:"name btn del" "when btn del" "who btn del";row-gap:2px}
  .vx-rs-ideadel{grid-area:del;align-self:center}
  .vx-rs-ideaname{grid-area:name;white-space:normal}
  .vx-rs-ideawhen{grid-area:when}
  .vx-rs-ideawho{grid-area:who}
  .vx-rs-ideaadd{grid-area:btn;align-self:center;min-height:34px}
}
/* WHY A TIME WAS NOT TAKEN. Gold, not red — nothing has gone wrong, the sheet
   simply needs a different way of saying it, and the note says which. */
.vx-rs-note{margin:6px 0 0;padding:8px 12px;border-radius:8px;
  background:rgba(200,169,110,.10);border:1px solid rgba(200,169,110,.32);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;line-height:1.5;
  color:var(--text-mid,#4A4A4A)}
/* EARLIER · LATER — hidden until the couple's own weekend reaches into them.
   Set apart from the spine by a rule and a quieter heading, not by a different
   kind of row: inside, they are the same activities with the same controls. */
.vx-rs-zone{margin:0 0 18px;padding:0 0 4px}
.vx-rs-zone + .vx-rs-dayhead{margin-top:0}
.vx-rs-zonehead{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  margin:0 0 6px;padding:0 0 6px;border-bottom:1px solid rgba(44,74,62,.18)}
.vx-rs-zonetitle{font-family:var(--ff-h,'Cormorant Garamond',serif);font-size:1.02rem;
  font-weight:600;color:var(--green,#2C4A3E)}
.vx-rs-zonewhy{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;
  color:var(--text-muted,#88928d)}
/* ── THE PREP SCAN POINTS (2026-08-09) ─────────────────────────────────────
   Stephen: scan points as the page intro, "watch now or come back to the full
   video if they have any questions." Five lines, capped — a wall of bullets is
   the same bounce as a long video, just cheaper to scroll past. */
.vx-prep-scan{margin:0 0 20px;padding:16px 18px;border-radius:12px;
  background:rgba(200,169,110,.07);border:1px solid rgba(200,169,110,.26)}
.vx-prep-scaneyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
.vx-prep-scanlist{margin:10px 0 0;padding-left:18px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;line-height:1.62;
  color:var(--text-mid,#4A4A4A)}
.vx-prep-scanlist li + li{margin-top:6px}
/* THE PLAY CONTROL CARRIES ITS REAL LENGTH. The tab is called 10-Min Prep
   because that is the prep SESSION; a first-time user reads it as the runtime.
   Saying "2 min" is the cheapest win available on watch rate, and honest. */
.vx-prep-watch{margin:14px 0 0;display:inline-flex;align-items:center;gap:9px;
  padding:8px 16px;border-radius:100px;cursor:pointer;
  background:var(--green,#2C4A3E);color:#fff;border:none;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;font-weight:500}
.vx-prep-watch:hover{background:var(--gold-deep,#A07840)}
.vx-prep-watchdot{display:inline-flex;width:18px;height:18px;border-radius:50%;
  background:rgba(255,255,255,.18);align-items:center;justify-content:center;
  font-size:8px;padding-left:2px}
/* The dark slot: says the video is coming without implying the page is
   unfinished, because the points above are the whole lesson already. */
.vx-prep-watchsoon{margin:12px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.76rem;line-height:1.5;color:var(--text-muted,#88928d)}

/* ── THE MANIFEST TAB (2026-08-09) ─────────────────────────────────────────
   Stephen: the manifest "is lost at the bottom of the Plan". Its own page now,
   opening with what is still open — the last checklist before it is sent. */
.vx-mf{max-width:900px}
.vx-mf-empty{padding:8px 0 24px}
/* ⚑ THE SEARCH THAT ENDS THE REVIEW STEP. Stephen 2026-08-30: review the day,
   then "launch a lookup that finds vendors". It sits after the manifest and the
   privacy line, because it is the thing you do once the sheet reads right. */
.vx-mf-go{margin:22px 0 4px;padding:18px 0 0;
  border-top:1px solid var(--line,#D8D2C6);text-align:center}
.vx-mf-go-l{margin:8px 0 0;font-size:.76rem;color:var(--text-muted,#88928d)}
.vx-mf-gaps{margin:0 0 18px;padding:12px 14px;border-radius:10px;
  background:rgba(200,169,110,.09);border:1px solid rgba(200,169,110,.30)}
/* CLEAR IS ITS OWN STATE, and it is green rather than the absence of gold — a
   plan with nothing open should feel finished, not merely unflagged. */
.vx-mf-gaps.is-clear{background:rgba(58,107,89,.06);border-color:rgba(58,107,89,.22)}
.vx-mf-gapshead{margin:0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;
  line-height:1.5;color:var(--text-mid,#4A4A4A)}
.vx-mf-gaplist{margin:8px 0 0;padding-left:18px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;line-height:1.65;
  color:var(--text-mid,#4A4A4A)}
/* ⚑ DECISIONS, NOT GAPS — and deliberately NOT gold. Gold is this sheet's
   "something is open" colour; a decision we already made for the couple is
   settled, so it takes the same green the cleared state uses. Reading the two
   blocks in order should feel like "here is what we sorted out" followed by
   "here is what is left", never like two kinds of warning. */
.vx-mf-decs{margin:0 0 18px;padding:12px 14px;border-radius:10px;
  background:rgba(58,107,89,.06);border:1px solid rgba(58,107,89,.22)}
.vx-mf-decshead{margin:0 0 8px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;line-height:1.5;font-weight:600;color:var(--text-mid,#4A4A4A)}
.vx-mf-declist{margin:0;padding:0;list-style:none;display:grid;gap:10px}
.vx-mf-declist li{display:grid;gap:2px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.8rem;line-height:1.6;color:var(--text-mid,#4A4A4A)}
.vx-mf-declist b{font-weight:600;color:var(--text-dark,#2A2A2A)}
/* The override line is the point of the block, not a footnote — it is what
   makes the decision a proposal. Muted, but never smaller than the reason. */
.vx-mf-declist em{font-style:normal;color:var(--text-muted,#88928d)}

/* ⚑ THE PLAIN ITINERARY. It leads the manifest and the operator sheet follows
   it, so it is set as prose to be READ — a comfortable measure, generous
   leading, no rules or chrome. Deliberately not a card: a bordered box would
   make it look like one more panel among panels rather than the thing being
   confirmed. */
.vx-plain{margin:18px 0 0}
/* ⚑ FIRST ON THE PAGE NOW, so it opens flush. Stephen 2026-08-31, from his
   phone: "on mobile we need to get to the content quickly". An 18px gap above
   the first thing on a screen is 18px of nothing to scroll past. */
.vx-mf > .vx-plain:first-child{margin-top:0}
/* And the operator heading, demoted from page title to section title, needs the
   separation a mid-page heading earns — it was getting none as a first child. */
.vx-mf-opshead{margin-top:26px;padding-top:18px;
  border-top:1px solid var(--border,#eae5dd)}
.vx-plain-head{margin:0 0 10px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;font-weight:600;color:var(--text-mid,#4A4A4A)}
.vx-plain-day{margin:0 0 14px}
.vx-plain-daylab{margin:0 0 5px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.76rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--text-muted,#88928d)}
.vx-plain-day p{margin:0 0 8px;max-width:62ch;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.86rem;line-height:1.7;
  color:var(--text-dark,#2A2A2A)}
.vx-plain-ask{margin:12px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.8rem;line-height:1.6;color:var(--text-mid,#4A4A4A)}
/* A link, not a button: it moves you to the box, it does not do anything. */
.vx-plain-link{appearance:none;background:none;border:0;padding:0;font:inherit;
  color:var(--green,#2C4A3E);font-weight:500;text-decoration:underline;
  text-underline-offset:2px;cursor:pointer}
.vx-plain-link:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px}

/* ⚑ THE SIGN-OFF. Gold, because these are open questions — it is the same
   "something wants your attention" colour the gap list uses, and it turns green
   only when every guess has been agreed. */
.vx-sign{margin:16px 0 0;padding:12px 14px;border-radius:10px;
  background:rgba(200,169,110,.07);border:1px solid rgba(200,169,110,.28)}
.vx-sign-head{margin:0 0 9px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;font-weight:600;color:var(--text-mid,#4A4A4A)}
.vx-sign-list{margin:0;padding:0;list-style:none;display:grid;gap:11px}
.vx-sign-list li{display:grid;gap:5px;justify-items:start;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;line-height:1.6;
  color:var(--text-mid,#4A4A4A)}
.vx-sign-says{color:var(--text-dark,#2A2A2A)}
.vx-sign-ok{font-style:normal;color:var(--green,#2C4A3E);font-weight:500}
/* A changed assumption is not an alarm — it is a thing to look at again. */
.vx-sign-stale{font-style:normal;color:var(--text-muted,#88928d)}
.vx-sign-btn,.vx-sign-all{appearance:none;border:1px solid var(--border,#eae5dd);
  background:var(--surface,#fff);border-radius:999px;padding:6px 13px;
  font:inherit;font-size:.76rem;min-height:34px;cursor:pointer;
  color:var(--text-dark,#2A2A2A)}
.vx-sign-all{margin:11px 0 0}
.vx-sign-btn:hover,.vx-sign-all:hover,
.vx-sign-btn:focus-visible,.vx-sign-all:focus-visible{
  border-color:var(--green,#2C4A3E);color:var(--green,#2C4A3E)}
.vx-sign-btn:focus-visible,.vx-sign-all:focus-visible{
  outline:2px solid var(--gold,#C8A96E);outline-offset:2px}

/* ⚑ THE VERA DIALOG ON THE MANIFEST. Quiet by default: it is an alternative to
   the controls above it, not a replacement, and a box that shouts would read as
   the primary way to work. Gold border, because this is the one block on the
   page that is a conversation rather than a statement. */
.vx-vera{margin:18px 0 0;padding:13px 14px;border-radius:10px;
  background:rgba(200,169,110,.06);border:1px solid rgba(200,169,110,.26)}
.vx-vera-head{margin:0 0 8px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;font-weight:600;color:var(--text-mid,#4A4A4A)}
.vx-vera-say,.vx-vera-q,.vx-vera-note,.vx-vera-err{
  margin:0 0 8px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;
  line-height:1.6;color:var(--text-mid,#4A4A4A)}
.vx-vera-q{font-weight:600;color:var(--text-dark,#2A2A2A)}
.vx-vera-err{color:var(--danger,#9B3B2F)}
/* The note is the promise that nothing has happened yet — it must stay legible,
   so it is muted by colour and not by size. */
.vx-vera-note{margin:8px 0 0;color:var(--text-muted,#88928d)}
/* ⚑ THE ACTION LIST IS THE STATE OF THE CONVERSATION, so it reads as a list of
   things about to happen, not as prose. */
.vx-vera-acts{margin:0 0 10px;padding-left:18px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;line-height:1.65;
  color:var(--text-dark,#2A2A2A)}
.vx-vera-lab{display:block;margin:0}
.vx-vera-in{width:100%;box-sizing:border-box;padding:9px 11px;border-radius:8px;
  border:1px solid var(--border,#eae5dd);background:var(--surface,#fff);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;line-height:1.5;
  color:var(--text-dark,#2A2A2A);resize:vertical}
.vx-vera-in:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:1px}
.vx-vera-row{display:flex;flex-wrap:wrap;gap:8px;margin:9px 0 0}
.vx-vera-row:first-of-type{margin-top:0}

/* A pointer to another tab, styled as a link rather than a button: it moves you,
   it does not do anything. */
.vx-tp-tomanifest{margin:18px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.8rem;line-height:1.55;color:var(--text-muted,#88928d)}
.vx-tp-golink{appearance:none;background:none;border:none;padding:0;cursor:pointer;
  font:inherit;color:var(--green,#2C4A3E);font-weight:500;text-decoration:underline;
  text-underline-offset:2px}
.vx-tp-golink:hover{color:var(--gold-deep,#A07840)}
.vx-rs-restore{margin:12px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.75rem;
  color:var(--text-muted,#88928d)}
.vx-rs-restorebtn{margin-left:4px;padding:2px 10px;min-height:26px;border-radius:100px;cursor:pointer;
  background:#fff;border:1px solid rgba(44,74,62,.28);font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.7rem;font-weight:500;color:var(--green,#2C4A3E)}
.vx-rs-restorebtn:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}

/* A phone puts the WHEN on one line and the WHAT beneath it, with the checkbox
   spanning both so it still reads as the row's first control. Stacking the
   offset under the clock instead — the obvious first try — makes every row
   three lines tall and pushes "27h 30m before" wider than the clock column it
   is trying to sit under. */
/* A PHONE IS TWO LINES, which is the mockup's own row and the reason it reads
   better than the first cut. Stephen, comparing the two on a phone: "the
   mock-up is the cleaner look I am seeking."

     [✓]  Lake Minnetonka Cruise                    ×
          1pm · 27h 30m before   [ Shuttle      ⌄ ]

   The name leads, because it is what you are looking for. WHO and the ROUTE
   come off entirely — carrying them wrapped the row to four lines, and that
   single detail line was the whole difference between the two screenshots.
   "Run 1 of 2" stays, tucked under the clock: without it her two Lake
   Minnetonka rows are identical but for the time. */
@media (max-width:760px){
  /* TWO LINES, as in the mockup: the name leads because it is what you are
     looking for, and the when and the vehicle share the line beneath it. The
     when box is wider than the old clock — it holds "5:00p -9:00p" and is
     tapped — so it takes an auto column and the picker holds the right edge. */
  /* ⚑ TWO LINES BECOME ONE. With the checkbox, the picker and the × inside,
     the row has only a clock and a title left — they fit on one line at
     phone width, and a day sheet of single-height rows is what it was
     always trying to be. */
   /* ⚑ NOTHING TO RE-COLUMN. The clock moved into the panel and the row became
      a flex line matching .vxb-item, so only the padding is worth keeping here. */
   .vx-rs-row{padding:9px 2px}


  .vx-rs-cell-inc{grid-area:inc;align-self:center}
  /* IT DOES NOT WRAP. Letting the title run onto a second line pushes the moves
     chip down with it and every long row becomes three lines — and a sheet of
     unequal row heights is the thing Stephen has rejected twice. The name is
     clipped and carries the whole title in its tooltip, exactly as it did when
     the row was narrower. */
  .vx-rs-what{grid-area:what;min-width:0}
  .vx-rs-cell-del{grid-area:del;align-self:start}
  /* At rest the hour is a BUTTON, so nothing here has to reach 16px and the row
     is not sized up to meet a form control it does not have. The input still
     gets 16px — but only while it exists, which is only while the couple is
     typing in it, and a zoom at that moment is welcome. */
  .vx-rs-clock{font-size:.82rem}
  .vx-rs-whenin{font-size:1rem}
  /* ⚑ THE PLACEMENT BELONGS TO THE GRID CHILD, AND THE GRID CHILD MOVED.
     These properties sat on .vx-rs-clock, which WAS the row's third cell until
     the pin mark needed somewhere to live and .vx-rs-when was wrapped around it.
     After that the clock was a flex child, so grid-area did nothing.

     ⚑ AND THE 132px min-width IS GONE (2026-08-17). It was propping open a
     BUTTON that would otherwise collapse to 20px around 45px of nowrap text.
     There is no button now — the face is display only — so the clock is text
     sized to itself, and the min-width had stopped protecting anything and
     started doing harm: 132px inside a 76px track, overflowing it and printing
     the hour over the top of the title. Measured on the live deploy. */
  .vx-rs-when{grid-area:clock;justify-self:start;width:auto;min-width:0}
  .vx-rs-clock{text-align:left;white-space:nowrap;font-size:.78rem}
  .vx-rs-title{font-size:.86rem}
  .vx-rs-mode{font-size:.78rem}
  .vx-rs-cell-mode{grid-area:mode;margin-top:0;justify-self:stretch;min-width:0}
  /* ⚑ THE BOX WAS THROWING AWAY 61px. Stephen 2026-08-10: the group pick is
     too wide on a phone. Measured at 375px: the mode area has 197px available
     and this pinned it to 136, so five of seven labels overflowed a box that
     had the room all along. Shortening the words was only half the fix.
     Stretch instead of end-align, and let it fill its own grid area. */
  .vx-rs-mode{width:100%;min-width:0;min-height:34px}
  /* T−0 carries no control and no ×, so it is two lines rather than three. */
  .vx-rs-row.is-anchor .vx-rs-cell-mode{display:none}
}

/* SAVE TO CONTACT — the compare grid's own row. Sized like a cell value, not
   like a call to action: it sits in a grid of facts and should read as one more
   thing the row offers rather than as a banner across it. */
/* 2026-08-08 (Stephen: "the Save to contact row has a padding problem") — every
   compare row is locked to 84px, and .vx-cmp-cell stacks from the top, so a
   26px button sat against the top edge with ~47px of dead space beneath it.
   Auto margins in a column flex container absorb that space evenly and centre
   the button in its cell. No :has(), no extra class, no markup change. */
.vx-cmp-save{margin-top:auto;margin-bottom:auto;
  padding:3px 12px;min-height:26px;border-radius:100px;cursor:pointer;
  background:#fff;border:1px solid rgba(44,74,62,.28);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;font-weight:500;
  color:var(--green,#2C4A3E);white-space:nowrap}
.vx-cmp-save:hover:not(:disabled){border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
.vx-cmp-save:disabled{cursor:default}
/* ⚑ THE ONE CELL A COUPLE TYPES INTO. Google returns a business, never a
   person, so "Who you call" is empty until they fill it — styled as a quiet
   field rather than a form control so an empty one reads like the honest dash
   beside it instead of an unanswered question. */
.vx-cmp-cname{width:100%;box-sizing:border-box;margin:auto 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;
  color:var(--charcoal,#33352f);background:transparent;
  border:0;border-bottom:1px dashed rgba(44,74,62,.22);
  border-radius:0;padding:3px 2px;text-align:center}
.vx-cmp-cname::placeholder{color:var(--text-muted,#b3b0a8);font-style:italic}
.vx-cmp-cname:focus{outline:none;border-bottom-color:var(--gold,#C8A96E);
  background:rgba(200,169,110,.05)}
/* ── WHERE THEIR VEHICLES ARE ─────────────────────────────────────────────
   The FMCSA census row. Same pill as Save-to-contact, because it is the same
   kind of thing: an action the couple takes on one vendor, not a fact the
   grid already holds. Nothing here runs on a paint. */
.vx-cmp-census{margin-top:auto;margin-bottom:auto;
  padding:3px 12px;min-height:26px;border-radius:100px;cursor:pointer;
  background:#fff;border:1px solid rgba(44,74,62,.28);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;font-weight:500;
  color:var(--green,#2C4A3E);white-space:nowrap}
.vx-cmp-census:hover:not(:disabled){border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}
/* ⚑ THE FINDING, and the only saturated thing in the row. Gold, not red:
   ninety minutes of billed clock is a QUESTION FOR THE CALL, not a fault.
   Per the reduce-stress charter nothing on this sheet renders as an alarm. */
.vx-cmp-census-flag{display:block;margin-top:5px;padding:4px 8px;border-radius:6px;
  background:rgba(200,169,110,.13);border:1px solid rgba(200,169,110,.34);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;line-height:1.35;
  color:var(--gold-deep,#A07840);cursor:help}
/* A DECLINE READS AS QUIET, NOT AS A WARNING. "Not found under this name" is
   about the registry's indexing, never about the operator — so it gets the
   muted treatment every unknown on this grid gets, and no colour at all. */
.vx-cmp-census-soft{display:block;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.7rem;line-height:1.4;color:var(--text-muted,#88928d);cursor:help}
.vx-cmp-census-fleet{display:block;margin-top:4px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;
  color:var(--text-mid,#4A4A4A)}
.vx-cmp-census-src{display:block;margin-top:3px;
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.02em;
  color:var(--text-muted,#88928d);cursor:help}
/* BEST PLACED — the one line on this row that is a recommendation rather than
   a fact, so it leads the cell and is the only green thing on it. Green, not
   gold: gold is reserved for a finding that costs the couple something, and
   this is the opposite. */
.vx-cmp-census-best{display:block;margin-bottom:5px;padding:3px 9px;border-radius:100px;
  align-self:flex-start;background:rgba(44,110,80,.12);border:1px solid rgba(44,110,80,.3);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.68rem;font-weight:500;
  letter-spacing:.01em;color:var(--green,#2C4A3E);cursor:help}
/* The same block on a Setup card. It reuses the census classes above, so the
   two surfaces cannot describe one operator differently — only the container
   differs, because a card is not a grid cell. */
.vx-vendor-card-census{margin:8px 0 0;padding:8px 0 0;
  border-top:1px solid rgba(44,74,62,.08);
  display:flex;flex-direction:column;align-items:flex-start;gap:3px;text-align:left}
.vx-vendor-card-census .vx-cmp-census-flag{margin-top:4px}
/* A card inherits its own type scale, so the garage address arrived bigger
   than the vendor's name. It is a fact in a stack of facts, not a heading. */
.vx-vendor-card-census .vx-cmp-cell-value{font-family:var(--ff-m,'DM Mono',monospace);
  font-size:.74rem;font-weight:400;color:var(--green,#2C4A3E);max-height:none;
  -webkit-mask-image:none;mask-image:none}
/* ⚑ THIS ROW IS NOT A ONE-LINE FACT. .vx-cmp-cell caps at 84px with
   overflow:hidden — right for "12 vehicles", and it silently squashed the
   census cell's four stacked elements until the address itself collapsed to
   zero height and vanished while the flag below it stayed. The cap keeps row
   rhythm; rhythm is per ROW, and the grid stretches every cell in a row to
   the tallest, so lifting it here costs nothing and loses nothing. */
.vx-cmp-cell.is-census{max-height:none;flex-direction:column;align-items:flex-start;
  justify-content:flex-start;gap:0}
.vx-cmp-cell.is-census > *{flex:0 0 auto;max-height:none;-webkit-mask-image:none;mask-image:none}
/* Saved is a settled state, not a disabled one — it says what happened. */
.vx-cmp-save.is-done{background:rgba(44,74,62,.06);border-color:rgba(44,74,62,.14);
  color:var(--text-muted,#88928d)}
.vx-cmp-save.is-failed{border-color:rgba(165,48,30,.4);color:#A5301E}

/* THE HANDOUT IS THE WHOLE WEEKEND. Screen filtering must never reach the
   operator's document — a vendor sheet missing two of three days is worse than
   no sheet at all. */
@media print{
  .vx-tp-nav,.vx-tp-map{display:none !important}
  .vx-tw-day.is-off{display:block !important}
}
.vx-tp-mapimg{display:block;width:100%;height:auto;border-radius:10px;
  border:1px solid rgba(44,74,62,.12);background:rgba(44,74,62,.03)}
.vx-tp-mapfail{display:none;margin:0;padding:14px 16px;border-radius:10px;
  background:rgba(44,74,62,.04);border:1px solid rgba(44,74,62,.10);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;color:var(--text-muted,#88928d)}
.vx-tp-map.is-mapless .vx-tp-mapimg{display:none}
.vx-tp-map.is-mapless .vx-tp-mapfail{display:block}
.vx-tp-layers{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:10px 0 0}
.vx-tp-layerlbl{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--text-muted,#88928d);margin-right:2px}
.vx-tp-layer{min-height:34px;padding:6px 12px;border-radius:100px;cursor:pointer;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.72rem;
  background:#fff;color:var(--text-mid,#4A4A4A);border:1px solid rgba(44,74,62,.16)}
.vx-tp-layer.is-on{background:rgba(200,169,110,.16);border-color:var(--gold,#C8A96E);
  color:var(--gold-deep,#A07840);font-weight:500}
/* The legend is the accessibility channel the map image cannot carry: Mapbox
   static paths have no dash support, so on the picture colour is alone. Here the
   pattern is a real SVG line and the vehicle is named in words. */
.vx-tp-legend{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:6px 18px}
.vx-tp-legrow{display:flex;align-items:center;gap:7px}
.vx-tp-swatch{flex:0 0 auto}
.vx-tp-legname{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;
  color:var(--text,#1C1C1C)}
.vx-tp-legmeta{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;color:var(--text-muted,#88928d)}
.vx-tp-legnote{margin:7px 0 0;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-style:italic;font-size:.86rem;color:var(--text-muted,#88928d)}
/* An assumption reads differently from a fact. Gold rule, never a warning
   colour — it is a gap with a next action, not a failing. */
.vx-tp-why.is-assumed{padding:11px 14px;background:rgba(200,169,110,.08);
  border-left:2px solid var(--gold,#C8A96E);border-radius:0 8px 8px 0;font-style:italic}

/* ── The side trips, offered rather than sold ────────────────────────────
   Most couples skip most of these, and the card says so. The ones this
   wedding's own numbers point at come first; the rest sit behind one tap. */
.vx-tp-trips{margin:20px 0 0;padding-top:16px;border-top:1px solid rgba(44,74,62,.10)}
.vx-tp-trips-h{margin:0 0 4px;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-size:1.15rem;font-weight:500;color:var(--green,#2C4A3E)}
.vx-tp-trips-note{margin:0 0 13px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;
  line-height:1.5;color:var(--text-muted,#88928d)}
.vx-tp-triplist{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.vx-tp-trip{padding:13px 15px;background:#fff;border:1px solid rgba(44,74,62,.12);border-radius:10px}
.vx-tp-trip.is-likely{border-left:3px solid var(--gold,#C8A96E)}
.vx-tp-trip-q{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.88rem;font-weight:500;
  color:var(--text,#1C1C1C);line-height:1.45}
.vx-tp-trip-because{margin-top:5px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;
  color:var(--gold-deep,#A07840)}
.vx-tp-trip-why{margin-top:6px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;
  line-height:1.55;color:var(--text-mid,#4A4A4A)}
.vx-tp-trip-typical{margin-top:5px;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-style:italic;font-size:.86rem;color:var(--text-muted,#88928d)}
.vx-tp-trip-add{margin-top:11px}
.vx-tp-more{margin:12px 0 0;padding:9px 16px;min-height:38px;border-radius:100px;cursor:pointer;
  background:transparent;border:1px dashed rgba(44,74,62,.28);
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;color:var(--text-muted,#88928d)}
.vx-tp-more:hover{border-color:var(--gold,#C8A96E);color:var(--gold-deep,#A07840)}

/* The maps and the offers are screen furniture — the packet is what prints. */
@media print{
  html.vx-printing-packet #vx-packet-host .vx-tp-map,
  html.vx-printing-packet #vx-packet-host .vx-tp-trips{display:none !important}
}

/* ── The operator packet ─────────────────────────────────────────────────
   The document that TRAVELS. Addresses, clock times, passenger counts — and
   not one dollar figure, because a quote written against a known budget is
   that budget rather than a competitive price. The couple's worksheet above
   keeps the money and stays on screen.

   Hidden by default; the couple opens it to read exactly what an operator
   will receive before sending it. */
.vx-qp{margin:16px 0 0;padding:18px 20px 20px;background:#fff;
  border:1px solid rgba(44,74,62,.14);border-radius:10px}
.vx-qp[hidden]{display:none}
.vx-qp-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin:0 0 14px;padding-bottom:10px;border-bottom:1px solid rgba(44,74,62,.10)}
.vx-qp-title{margin:0;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-size:1.25rem;font-weight:500;color:var(--green,#2C4A3E)}
.vx-qp-date{font-family:var(--ff-m,'DM Mono',monospace);font-size:.72rem;
  letter-spacing:.06em;color:var(--text-muted,#88928d)}
.vx-qp-day{margin:0 0 16px}
.vx-qp-daylabel{margin:0 0 8px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.66rem;
  letter-spacing:.11em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
.vx-qp-rides{list-style:none;margin:0;padding:0}
.vx-qp-ride{padding:10px 0 11px;border-bottom:1px solid rgba(44,74,62,.06)}
.vx-qp-ride:last-child{border-bottom:none}
.vx-qp-when{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 10px;margin-bottom:5px}
.vx-qp-time{font-family:var(--ff-m,'DM Mono',monospace);font-size:.8rem;font-weight:500;
  color:var(--green,#2C4A3E)}
.vx-qp-riders{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:500;
  color:var(--text-mid,#4A4A4A)}
.vx-qp-riders.is-unknown{font-style:italic;font-weight:400;color:var(--text-muted,#88928d)}
.vx-qp-must{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.7rem;
  color:var(--gold-deep,#A07840);padding:1px 7px;border:1px solid rgba(200,169,110,.42);
  border-radius:10px}
/* The shape of a continuous service — vehicles staged and an interval, printed
   under the time so an operator reads it before the addresses. Not a warning
   colour: this is how the night runs, not something that went wrong. */
.vx-qp-shape{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;line-height:1.45;
  color:var(--text-mid,#4A4A4A);margin:0 0 6px;padding:5px 9px;border-radius:8px;
  background:rgba(44,74,62,.045)}
.vx-qp-stop{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;margin-top:3px}
.vx-qp-role{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--text-muted,#88928d);min-width:56px}
.vx-qp-place{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:500;
  color:var(--text,#1C1C1C)}
.vx-qp-addr{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.76rem;
  color:var(--text-mid,#4A4A4A)}
.vx-qp-addr.is-missing{color:var(--gold-deep,#A07840);border-bottom:1px dashed rgba(200,169,110,.55)}
/* 2026-08-07 — who to call at this stop, from the contact directory. Quieter
   than the address on purpose: the address is what the operator routes to, the
   name and number are what they need only if something goes wrong. Renders
   only when a contact matched, so it never becomes a row of blanks. */
.vx-qp-who{display:block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.7rem;
  letter-spacing:.03em;color:var(--text-muted,#88928d);margin-top:1px}
.vx-qp-block{margin:16px 0 0;padding-top:13px;border-top:1px solid rgba(44,74,62,.10)}
.vx-qp-h{margin:0 0 8px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.66rem;
  letter-spacing:.11em;text-transform:uppercase;color:var(--gold-deep,#A07840)}
.vx-qp-needs{list-style:none;margin:0;padding:0}
.vx-qp-needs li{display:flex;flex-wrap:wrap;gap:2px 10px;padding:5px 0;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem}
.vx-qp-nlabel{color:var(--text-muted,#88928d);min-width:150px}
.vx-qp-nvalue{color:var(--text,#1C1C1C);font-weight:500}
.vx-qp-confirm{margin:0;padding-left:18px}
.vx-qp-confirm li{margin:0 0 6px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;
  color:var(--text-mid,#4A4A4A);line-height:1.5}
.vx-qp-note{margin:14px 0 0;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);
  font-style:italic;font-size:.92rem;color:var(--text-mid,#4A4A4A)}
.vx-qp-contact{margin:6px 0 0;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;
  color:var(--text-muted,#88928d)}
.vx-qp-actions{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}

/* Print. Scoped to a class the print button sets, and routed through a
   body-direct host — because this page carries an UNCONDITIONAL print rule
   (`body>*:not(#print-area){display:none!important}`) that blanks anything
   nested in the layout tree. The earlier `.vx-tw` print block never fired for
   exactly that reason; a plain visibility trick is silently dead here.

   What prints is the PACKET. The worksheet stays on screen with the money. */
@media print{
  html.vx-printing-packet body > *{display:none !important}
  html.vx-printing-packet body > #vx-packet-host{display:block !important}
  html.vx-printing-packet body{padding:0 !important;background:#fff !important}
  html.vx-printing-packet #vx-packet-host .vx-qp{display:block !important;
    border:none;padding:0;margin:0;font-size:11pt}
  html.vx-printing-packet #vx-packet-host .vx-qp-actions{display:none !important}
  html.vx-printing-packet #vx-packet-host .vx-qp-ride{break-inside:avoid;page-break-inside:avoid}
  html.vx-printing-packet #vx-packet-host .vx-qp-day{break-inside:avoid}
  html.vx-printing-packet #vx-packet-host .vx-qp-block{break-inside:avoid}
}
.vx-readiness-foot{margin:18px 0 0;padding:12px 16px;background:rgba(200,169,110,.08);border-left:2px solid var(--gold-deep,#A07840);border-radius:0 8px 8px 0;font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-style:italic;font-size:.95rem;color:var(--text-mid,#4A4A4A);line-height:1.5}

.vdx-r-card{background:white;border:1px solid rgba(0,0,0,0.08);border-left:3px solid var(--gold-deep,#A07840);border-radius:12px;padding:18px 22px;transition:border-color .15s,box-shadow .15s}
.vdx-r-card:hover{border-left-color:var(--green,#2C4A3E);box-shadow:0 2px 12px rgba(44,74,62,.06)}
.vdx-r-head{display:flex;align-items:center;gap:12px;margin-bottom:12px;flex-wrap:wrap}
.vdx-r-head-spacer{flex:1}
.vdx-r-num{flex-shrink:0;width:26px;height:26px;border-radius:50%;background:var(--green,#2C4A3E);color:white;font-family:var(--ff-m,'DM Mono',monospace);font-size:.78rem;font-weight:600;display:inline-flex;align-items:center;justify-content:center}
.vdx-r-summary{padding:10px 14px;border-radius:8px;margin-bottom:12px;background:rgba(161,134,80,.05);border-left:2px solid rgba(161,134,80,.45)}
.vdx-r-summary .vdx-r-lbl{color:var(--gold-deep,#A07840);margin-bottom:4px}
.vdx-r-summary-text{font-family:var(--ff-b);font-size:.95rem;line-height:1.55;color:var(--ink);margin:0;font-weight:400}
.vdx-r-ask{padding:12px 16px;border-radius:8px;margin-bottom:12px;background:rgba(44,74,62,.05);border-left:2px solid var(--green,#2C4A3E)}
.vdx-r-ask .vdx-r-lbl{color:#2C4A3E;margin-bottom:6px}
.vdx-r-q{font-family:var(--ff-d,'Cormorant Garamond',serif);font-size:1.2rem;font-style:italic;color:var(--green,#2C4A3E);margin:0;line-height:1.35;font-weight:500}
.vdx-r-gap-badge{flex-shrink:0;font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--amber-risk,#C97B3A);background:rgba(201,123,58,.08);border:1px solid rgba(201,123,58,.3);border-radius:10px;padding:3px 8px;align-self:center;font-weight:500;white-space:nowrap}
.vdx-r-why{font-family:var(--ff-b);font-size:.88rem;line-height:1.55;color:var(--text-mid);margin:0 0 12px}
.vdx-r-why strong{color:var(--ink);font-weight:500}
.vdx-r-bad,.vdx-r-push{padding:10px 14px;border-radius:8px;margin-bottom:8px}
.vdx-r-bad{background:rgba(185,64,64,.04);border-left:2px solid rgba(185,64,64,.35)}
.vdx-r-push{background:rgba(58,107,89,.05);border-left:2px solid rgba(58,107,89,.4)}
.vdx-r-lbl{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px}
.vdx-r-bad .vdx-r-lbl{color:#a23030}
.vdx-r-push .vdx-r-lbl{color:#3D6355}
.vdx-r-bad-quote{font-family:var(--ff-d,'Cormorant Garamond',serif);font-style:italic;font-size:.92rem;line-height:1.55;color:#a23030}
.vdx-r-push-quote{font-family:var(--ff-b);font-size:.92rem;line-height:1.55;color:var(--ink)}
.vdx-r-empty{padding:24px;text-align:center;font-style:italic;color:var(--text-muted);background:var(--cream);border:1px dashed var(--border-g);border-radius:12px}
@media (max-width:768px){
  .vdx-r-card{padding:14px 16px}
  .vdx-r-head{gap:10px;margin-bottom:10px}
  .vdx-r-num{width:22px;height:22px;font-size:.7rem}
  .vdx-r-ask{padding:10px 12px;margin-bottom:10px}
  .vdx-r-q{font-size:1.08rem}
  .vdx-r-bad,.vdx-r-push{padding:9px 12px}
}

.vx-dec-day{display:flex;flex-direction:column;gap:10px}
.vx-dec-day-label{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep);margin:18px 0 4px;font-weight:500}
.vx-dec-day:first-child .vx-dec-day-label{margin-top:0}
.vx-dec-entry{background:var(--white);border:1px solid var(--border-g);border-left:3px solid var(--gold);border-radius:10px;padding:16px 20px;display:grid;grid-template-columns:1fr auto;gap:8px 16px;align-items:start}
.vx-dec-entry[data-kind="vendor_locked"]{border-left-color:var(--gold-deep)}
.vx-dec-entry[data-kind="contract_review_applied"]{border-left-color:var(--green-mid,#3a6b59)}
.vx-dec-entry[data-kind="concurrent_edit_resolved"]{border-left-color:#b07b3f}
.vx-dec-entry[data-kind="budget_target_set"],
.vx-dec-entry[data-kind="category_target_adjustment"],
.vx-dec-entry[data-kind="guest_count_adjustment"]{border-left-color:rgba(90,140,122,.55)}
.vx-dec-entry-head{grid-column:1 / -1;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.vx-dec-kind{display:inline-flex;align-items:center;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--green);background:var(--green-pale,#eaf0ed);padding:3px 9px;border-radius:999px;font-weight:500}
.vx-dec-entry[data-kind="vendor_locked"] .vx-dec-kind{color:var(--gold-deep);background:rgba(200,169,110,.18)}
.vx-dec-entry[data-kind="concurrent_edit_resolved"] .vx-dec-kind{color:#925e2a;background:rgba(176,123,63,.16)}
.vx-dec-entry[data-kind="contract_review_applied"] .vx-dec-kind{color:var(--green-mid,#3a6b59);background:rgba(58,107,89,.14)}
.vx-dec-context{font-family:var(--ff-d);font-size:1.1rem;color:var(--charcoal);line-height:1.4;margin:6px 0 0;font-weight:400;flex:1;min-width:200px}
.vx-dec-context em{color:var(--gold);font-style:italic}
.vx-dec-time{font-family:var(--ff-m);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted);white-space:nowrap;text-align:right}
.vx-dec-actor{display:block;font-family:var(--ff-m);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-top:2px}
.vx-dec-rationale{grid-column:1 / -1;font-family:var(--ff-d);font-size:.95rem;color:var(--text-mid);line-height:1.55;font-style:italic;margin:8px 0 0;padding:10px 14px;border-left:2px solid var(--border-g);background:rgba(250,247,242,.5)}
.vx-dec-meta{grid-column:1 / -1;font-family:var(--ff-m);font-size:.62rem;letter-spacing:.04em;color:var(--text-muted);margin-top:6px;display:flex;gap:14px;flex-wrap:wrap}
.vx-dec-meta b{font-weight:500;color:var(--charcoal);letter-spacing:0;font-family:var(--ff-b);font-size:.72rem}
/* 2026-05-28 (Stephen "Hardening C — decision confidence decay"):
   staleness chip + Re-confirm action on aging or budget-shifted
   decisions. Stale entries also fade the container slightly so the
   list visually surfaces what needs revisiting. */
.vx-dec-stale{display:inline-flex;align-items:center;font-family:var(--ff-m);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;padding:3px 9px;border-radius:999px;font-weight:500;margin-left:auto}
.vx-dec-stale.is-aging{color:var(--text-muted);background:rgba(28,28,28,.05);border:1px solid rgba(28,28,28,.08)}
.vx-dec-stale.is-stale{color:#a23030;background:rgba(220,80,80,.08);border:1px solid rgba(220,80,80,.25)}
.vx-dec-entry.is-stale{opacity:.72;border-left-color:rgba(176,68,68,.55)!important}
.vx-dec-entry.is-stale:hover{opacity:1}
.vx-dec-reconfirm{margin-top:6px;appearance:none;background:transparent;border:1px solid var(--border-g);color:var(--green);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;padding:5px 12px;border-radius:999px;cursor:pointer;transition:all .15s ease;font-weight:500}
.vx-dec-reconfirm:hover{background:var(--green);color:var(--white);border-color:var(--green)}
.vx-dec-reconfirm:disabled{opacity:.6;cursor:default}
@media (max-width:560px){
  .vx-dec-entry{grid-template-columns:1fr;padding:14px 16px}
  .vx-dec-time{text-align:left;margin-top:4px}
  .vx-dec-context{font-size:1rem}
}

/* Locked-decision celebration toast */
.vx-celebrate-toast{position:fixed;bottom:32px;left:50%;transform:translateX(-50%);background:linear-gradient(135deg,var(--gold-pale),var(--green-pale));border:1px solid var(--gold);border-radius:999px;padding:14px 26px;font-family:var(--ff-d);font-size:1rem;color:var(--green);box-shadow:0 8px 24px rgba(200,169,110,.3);z-index:850;font-weight:500;display:flex;align-items:center;gap:10px;animation:vx-celebrate-in .5s cubic-bezier(.22,1.5,.36,1)}
.vx-celebrate-toast em{color:var(--gold);font-style:italic}
@keyframes vx-celebrate-in{from{opacity:0;transform:translateX(-50%) translateY(20px) scale(.9)}to{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}}

/* ═══ Embedded Research interview detail panel (inside #section-interviews) ══ */
.vdx-embed[hidden]{display:none}
.vdx-embed{max-width:1100px;margin:1.5rem auto 0;padding:0 clamp(20px,5vw,48px);position:relative;z-index:1}
/* 2026-04-28: header restructured. Back button on its own line above
   the title. Title block sits below, left-aligned full-width. Stats
   meta sits flush right on wide screens, drops below on narrow. */
.vdx-embed-head{display:flex;align-items:flex-start;gap:1.25rem;margin-bottom:1.25rem;flex-wrap:wrap}
.vdx-embed-back-row{width:100%;margin-bottom:.75rem}
.vdx-embed-back{appearance:none;background:transparent;border:1px solid var(--border-g);border-radius:999px;padding:7px 14px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;letter-spacing:normal;color:var(--text-mid);cursor:pointer;transition:all .15s}
.vdx-embed-back:hover{background:var(--green-pale);color:var(--green);border-color:var(--green)}
.vdx-embed-title-wrap{flex:1;min-width:220px;text-align:left}
.vdx-embed-eyebrow{font-family:var(--ff-m);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);margin:0 0 .3rem;font-weight:500}
.vdx-embed-title{font-family:var(--ff-d);font-size:clamp(1.6rem,3.2vw,2.25rem);font-weight:400;color:var(--green);letter-spacing:-.01em;line-height:1.1;margin:0}
.vdx-embed-title em{color:var(--gold);font-style:italic}
.vdx-embed-sub{font-size:.9rem;color:var(--text-muted);line-height:1.55;margin:.45rem 0 0;max-width:620px}
.vdx-embed-sub[hidden]{display:none}
.vdx-embed-meta{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.vdx-embed-stat{display:flex;align-items:baseline;gap:5px}
.vdx-embed-stat-num{font-family:var(--ff-d);font-size:1.2rem;font-weight:400;color:var(--charcoal)}
.vdx-embed-stat-num.italic{color:var(--gold);font-style:italic}
.vdx-embed-stat-lbl{font-family:var(--ff-m);font-size:.56rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted)}
.vdx-embed-sep{width:1px;height:20px;background:var(--border-g)}
/* Search-preferences chip — always-visible filter summary above the
   phase tabs. Reads zip / radius / guest count / price tier from the
   wedding row + VerdeauxProfile. Edit jumps to the Compare phase and
   forces the Personalize panel open so the user can tweak inline. */
.vdx-search-prefs-chip{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 1rem;padding:8px 14px;background:var(--cream,#FAF7F2);border:1px solid rgba(200,169,110,.32);border-radius:999px;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.84rem;color:var(--text-mid,#4A4A4A);width:fit-content;max-width:100%}
.vdx-search-prefs-chip[hidden]{display:none}
.vdx-search-prefs-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);font-weight:500}
.vdx-search-prefs-vals{color:var(--ink,#1C1C1C);font-weight:400}
.vdx-search-prefs-edit{appearance:none;background:transparent;border:1px solid var(--border-g,rgba(44,74,62,.22));color:var(--green,#2C4A3E);font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.74rem;font-weight:500;padding:4px 12px;border-radius:999px;cursor:pointer;transition:all .15s;margin-left:auto}
.vdx-search-prefs-edit:hover{background:var(--green-pale,#eaf0ed);border-color:var(--green)}
@media (max-width:560px){
  .vdx-search-prefs-chip{font-size:.78rem;padding:7px 10px;gap:8px}
}
#vdx-interview-root{position:relative}
/* Scope the interview module's .content wrapper when inside the SPA so it
 doesn't collide with the main app's layout rules. */
#vdx-interview-root .content{max-width:100%;margin:0;padding:0}
/* Phase-nav and phase-section already have their own card-style rules in
 verdeaux-interview.css. Ensure phase-nav sits flush with the embed head. */
/* ⚑ THE TAB STRIP PINS UNDER THE CHROME (2026-08-11). It was not sticky at
   all, so on a phone it scrolled up behind the opaque fixed bars within a
   screen of scrolling and took the selected-tab indicator with it — you
   could no longer see which of Plan the day / Manifest / Compare you were
   in. Stephen: "the selected menu disappears on mobile."
   Sticky rather than fixed so it still scrolls with its own guide, and at
   the same z-index as the budget strip: they are the same kind of object
   and never appear together. */
#vdx-interview-root .phase-nav{max-width:100%;padding:0;margin-top:0;
 position:sticky;
 /* Under the totals bar where there is one. --vx-tp-totals-h is 0 on every
    other tab and every other guide, so this is the old rule there. */
 top:calc(var(--vx-chrome-bottom) + var(--vx-tp-totals-h, 0px));
 z-index:25;
 background:var(--cream,#FAF7F2);padding-top:6px;padding-bottom:6px}

@media (max-width:768px){
 .vdx-embed{padding:0 1rem}
 .vdx-embed-head{flex-direction:column;gap:.75rem}
 .vdx-embed-meta{margin-top:.25rem}
}

/* ══════════════════════════════════════════════════════════════════════
   FIND / COMPARE — the operator surface, 2026-08-22
   ──────────────────────────────────────────────────────────────────────
   Every declaration is lifted from the published mockup unchanged; only the
   SELECTORS differ, each prefixed `.vxf `, with the token block moved from
   `:root` onto `.vxf`.

   ⚑ GENERATED BY BRACE MATCHING OVER THE WHOLE TEXT, NEVER LINE BY LINE.
   The first version split rules per line, so a selector list spanning two
   lines —

       .seg button:focus-visible,.card-answer:focus-visible,.sheet-x:focus-visible,
       .act:focus-visible,.addstop:focus-visible{outline:2px solid var(--gold)}

   — became one rule with an UNCLOSED brace and a second rule after it. CSS
   parsing stops dead at an unclosed brace, so five rules reached the browser
   and the remaining 123 did not. The surface rendered as unstyled markup:
   default grey buttons, "Sprinter van" and "not in your plan" running together.
   It looked like the feature was unbuilt. It was built and mute.

   ⚑ AND THE OUTPUT IS COUNTED, NOT ASSUMED: 123 rules in, 123 out, braces
   balanced, zero selectors escaping `.vxf`. find-surface-validate holds all
   four, and asserts a COUNT rather than the presence of any one rule.
   ══════════════════════════════════════════════════════════════════════ */
.vxf{
  /* ⚑ THE GUIDE'S CREAM, NOT A SECOND ONE. These four neutrals were a cool
     grey-green mixed for the standalone mockup, and against the cream the rest
     of the application is painted in they read as a panel bolted onto the page
     rather than part of it — a visible seam at the top edge of the surface.
     They now defer to the application's own tokens, with the mockup values kept
     only as fallbacks so the surface still stands up in isolation. */
  --ground:var(--cream,#FAF7F2);
  --chrome:var(--cream-d,#F0EBE1);
  --surface:var(--white,#FEFCF8);
  --surface-2:var(--warm,#F5F0E8);
  --ink:#23261F;
  --ink-2:#5A6157;
  --ink-3:#89907F;
  --line:rgba(35,38,31,.13);
  --green:#2C4A3E;
  --green-2:#3E6353;
  --green-ink:#EAF0EA;
  --gold:#A07840;            
  
  --gold-ink:#8A6430;
  --warn:#9A6B12;            
  --shadow:0 1px 2px rgba(35,38,31,.06),0 8px 24px rgba(35,38,31,.09);
  --shadow-sheet:0 -8px 40px rgba(35,38,31,.22);
  --r:14px;
}
/* ⚑ NO DARK PALETTE HERE — REMOVED 2026-09-08.
   Stephen, on an iPhone in dark mode: "the compare table is still the old
   version". It was the current version. This surface was the ONLY thing in the
   application carrying a `prefers-color-scheme: dark` block, so on a dark phone
   it painted itself a black slab with mint cards while the guide chrome around
   it — and all twelve other guides — stayed cream. A surface that changes
   colour when nothing else does does not read as a theme. It reads as a
   different, older screen.

   Deleted with it: `html[data-theme="dark"] .vxf{...}`. Nothing in this
   application ever sets `data-theme` — grep it — so that selector could not
   match, and its partner `html:not([data-theme="light"])` therefore matched
   ALWAYS, which is why the media query fired unconditionally.

   ⚑ IF DARK MODE IS EVER WANTED, IT IS AN APPLICATION DECISION, not this
   surface's. The tokens below are the light palette and stay the light
   palette. */
.vxf *{box-sizing:border-box}
.vxf{
  margin:0; background:var(--ground); color:var(--ink);
  font-family:"DM Sans",system-ui,-apple-system,sans-serif;
  line-height:1.5; -webkit-font-smoothing:antialiased;
}
.vxf .seg button:focus-visible, .vxf .card-answer:focus-visible, .vxf .sheet-x:focus-visible, .vxf .act:focus-visible, .vxf .addstop:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxf .daybar{
  display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:16px 20px 8px;
}
.vxf .daybar .d{
  font-family:"DM Mono",monospace;font-size:.68rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-2);
}
.vxf .daybar .dt{font-family:"DM Mono",monospace;font-size:.68rem;color:var(--ink-3)}
.vxf .cards{display:flex;flex-direction:column;gap:12px;padding:4px 20px 24px}
.vxf .cards.is-swipe{
  flex-direction:row;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:4px 20px 20px;gap:12px;
}
.vxf .cards.is-swipe{padding-left:0;padding-right:0}
.vxf .cards.is-swipe .card{
  min-width:290px;scroll-snap-align:center;flex:0 0 auto;
}
.vxf .cards.is-swipe::before, .vxf .cards.is-swipe::after{content:"";flex:0 0 32px}
.vxf .row{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:13px 15px;cursor:pointer;font:inherit;color:inherit;
}
.vxf .row:hover{border-color:var(--green)}
.vxf .row:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxf .row-t{flex:1;min-width:0}
.vxf .row-n{
  display:block;font-size:.92rem;font-weight:500;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
}
.vxf .row-w{
  display:block;font-family:"DM Mono",monospace;font-size:.66rem;
  color:var(--ink-3);margin-top:2px;letter-spacing:.02em;
}
.vxf .row-v{
  font-family:"DM Mono",monospace;font-size:.88rem;font-weight:500;
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.vxf .row-v.is-typed{color:var(--gold)}
.vxf .row-c{color:var(--ink-3);font-size:.95rem;line-height:1}
.vxf .card-up{
  position:absolute;top:10px;right:12px;width:26px;height:26px;
  border-radius:50%;border:1px solid rgba(255,255,255,.28);
  background:rgba(0,0,0,.14);color:var(--green-ink);
  cursor:pointer;font:inherit;font-size:.8rem;line-height:1;
}
.vxf .card-up:hover{background:rgba(0,0,0,.26)}
.vxf .card-up:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxf .card{position:relative}
.vxf .detail{padding:2px 15px 15px;background:var(--surface)}
.vxf .spans{display:flex;gap:0;margin:2px 0 4px;border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);padding:14px 0}
.vxf .span{flex:1;min-width:0;text-align:left;padding-right:10px}
.vxf .span-v{
  display:block;font-size:1.06rem;font-weight:700;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;line-height:1.15;
}
.vxf .span-k{display:block;font-size:.7rem;color:var(--ink-2);margin-top:2px}
.vxf .span.is-walk .span-v{color:var(--warn)}
.vxf .daypager{
  display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;
  flex:1 1 auto;min-height:0;align-items:stretch;
}
.vxf .daypane{
  flex:0 0 100%;scroll-snap-align:start;min-width:0;
  overflow-y:auto;overscroll-behavior:contain;
}
.vxf .daydots{display:flex;gap:6px;justify-content:center;padding:10px 0 2px}
.vxf .daydot{
  height:5px;border-radius:3px;background:var(--line);border:0;padding:0;
  width:22px;cursor:pointer;transition:background .2s,width .2s;
}
.vxf .daydot[aria-current="true"]{background:var(--green);width:34px}
.vxf .daydot:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.vxf .card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;box-shadow:var(--shadow);
}
.vxf .card-face{
  background:linear-gradient(158deg,var(--green) 0%,var(--green-2) 100%);
  color:var(--green-ink);padding:14px 16px 16px;
}
.vxf .card-head{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-bottom:10px;
  
  padding-right:32px;
}
.vxf .card-title{font-size:.82rem;font-weight:500;opacity:.92}
.vxf .sig{display:inline-flex;align-items:center;gap:6px;font-size:.68rem;opacity:.9}
.vxf .sig .dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:0 0 auto}
.vxf .sig.is-warn{color:#F0C97A}
/* ⚑ `.vbtn` REMOVED 2026-09-08 with the cards that emitted it. It styled
   "Contact operator", which existed only on a per-operator card; the grid's
   Phone row is a cell, not a button. Removed in the same edit that retired the
   cards rather than left behind, because dead CSS is indistinguishable from
   CSS whose feature is merely unreachable — and this stylesheet already
   carries ~48 rules from two earlier retirements that nobody dared cut for
   exactly that reason. Verified to zero references first: cutting wide is how
   the size-ladder deletion took `DEADHEAD_NOTE` with it and broke nine gates. */
.vxf .card-face .needs{color:#F0C97A}
.vxf .row .needs{margin-right:-2px}
.vxf .route{
  /* ⚑ CORMORANT, NOT FRAUNCES — the mockup's face was never loaded. The font
     link on this page carries Cormorant Garamond, DM Sans and DM Mono; asking
     for Fraunces silently rendered Georgia, so this surface has never looked
     like the mockup it was lifted from. Cormorant IS the Verdeaux face (the
     wordmark, every report heading) and costs no extra request.
     `font-optical-sizing` goes with it: Cormorant ships no optical axis, so the
     property was inert here even when it resolved. */
  font-family:'Cormorant Garamond',Georgia,serif;font-weight:500;
  font-size:1.32rem;line-height:1.15;margin:0;letter-spacing:-.015em;text-wrap:balance;
}
.vxf .route .arw{opacity:.6;padding:0 .18em}
.vxf .card-meta{
  margin:9px 0 0;font-family:"DM Mono",monospace;font-size:.7rem;
  letter-spacing:.03em;opacity:.82;
}
.vxf .card-when{
  margin:3px 0 0;font-family:"DM Mono",monospace;font-size:.68rem;
  letter-spacing:.02em;opacity:.9;
}
.vxf .card-when b{font-weight:500;color:#F2DCAE}
.vxf .card.is-compact .card-when{font-size:.63rem;margin-top:2px}
.vxf .ans-sub{
  display:block;font-family:"DM Mono",monospace;font-size:.64rem;
  color:var(--ink-3);margin-top:1px;letter-spacing:.03em;
}
.vxf .ans-row{display:flex;align-items:baseline;gap:8px}
.vxf .ans-tag{
  font-family:"DM Mono",monospace;font-size:.6rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-3);
}
.vxf .card-answer{
  width:100%;display:flex;align-items:center;gap:12px;
  background:var(--surface);border:0;border-top:1px solid var(--line);
  padding:13px 16px;cursor:pointer;text-align:left;font:inherit;color:inherit;
}
.vxf .card-answer:hover{background:var(--surface-2)}
.vxf .ans-t{flex:1;min-width:0}
.vxf .ans-k{display:block;font-size:.73rem;color:var(--ink-2);margin-bottom:1px}
.vxf .ans-v{
  display:block;font-size:1.5rem;font-weight:700;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;
}
.vxf .ans-v.is-soft{font-size:1.02rem;font-weight:500;color:var(--ink-2);letter-spacing:0}
.vxf .chev{
  width:28px;height:28px;flex:0 0 auto;border-radius:50%;
  background:var(--green);color:var(--green-ink);
  display:grid;place-items:center;font-size:.9rem;line-height:1;
}
.vxf .card-face{padding:12px 14px 13px}
.vxf .card-head{margin-bottom:7px}
.vxf .route{font-size:1.1rem}
.vxf .card-when{font-size:.65rem;margin-top:3px}
.vxf .card-meta{margin-top:6px;font-size:.65rem}
.vxf .card-answer{padding:10px 14px}
.vxf .ans-k{font-size:.68rem}
.vxf .ans-v{font-size:1.22rem}
.vxf .chev{width:25px;height:25px;font-size:.82rem}
.vxf .leg-grip{
  width:30px;height:30px;flex:0 0 auto;margin-left:6px;border:0;background:none;
  color:var(--ink-3);cursor:grab;line-height:0;border-radius:6px;
  touch-action:none;align-self:center;display:grid;place-items:center;
}
.vxf .leg-grip:hover{color:var(--ink-2);background:var(--surface-2)}
.vxf .leg-grip:active{cursor:grabbing}
.vxf .leg-grip:hover{color:var(--green);background:var(--surface-2)}
.vxf .leg.is-lifted{background:var(--surface-2);border-radius:8px;box-shadow:var(--shadow);position:relative;z-index:2}
.vxf .leg.is-target{border-bottom-color:var(--green)}
.vxf .cards.is-swipe .addcard{min-width:290px;flex:0 0 auto;scroll-snap-align:center}
.vxf .act{
  flex:1;border-radius:999px;padding:12px 10px;font:inherit;font-size:.83rem;
  font-weight:500;cursor:pointer;border:1px solid var(--line);
  background:var(--surface);color:var(--ink);
}
.vxf .act.is-primary{background:var(--green);color:var(--green-ink);border-color:var(--green)}
.vxf .act:hover{border-color:var(--green)}
.vxf .legs{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.vxf .leg{display:flex;gap:12px;padding:12px 0;border-bottom:1px solid var(--line);align-items:baseline}
.vxf .leg-t{
  font-family:"DM Mono",monospace;font-size:.76rem;color:var(--ink-2);
  min-width:52px;font-variant-numeric:tabular-nums;
}
.vxf .leg-b{flex:1;min-width:0}
.vxf .leg-n{font-size:.9rem;margin:0}
.vxf .leg-name{
  background:none;border:0;padding:0;font:inherit;font-size:.9rem;color:inherit;
  cursor:pointer;text-align:left;
}
.vxf .leg-name:hover{color:var(--gold-ink);text-decoration:underline;text-underline-offset:3px}
.vxf .leg-name:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxf .leg-from{
  font-family:"DM Mono",monospace;font-size:.6rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);
}
.vxf .leg.is-origin .leg-name{font-weight:500}
.vxf .leg-d{margin:2px 0 0;font-size:.75rem;color:var(--ink-3)}
.vxf .leg.is-quiet .leg-n{color:var(--ink-2)}
.vxf .leg-tag{
  font-family:"DM Mono",monospace;font-size:.62rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--gold);
}
.vxf .note-sig{color:var(--ink-3)}
.vxf .note-p{margin:0}
.vxf .note-fix{
  margin-top:9px;appearance:none;background:none;border:1px solid var(--gold-ink);
  color:var(--gold-ink);border-radius:999px;padding:6px 13px;font:inherit;
  font-size:.76rem;font-weight:500;cursor:pointer;
}
.vxf .note-fix:hover{background:var(--gold-ink);color:var(--surface)}
.vxf .note{
  margin:16px 0 0;padding:11px 13px;border-radius:10px;background:var(--surface-2);
  border-left:2px solid var(--warn);font-size:.79rem;color:var(--ink-2);
}
.vxf .sheet-acts{display:flex;gap:9px;margin-top:18px}
.vxf .legend{max-width:1080px;margin:0 auto;padding:0 24px 70px;color:var(--ink-3);font-size:.83rem}
.vxf .legend b{color:var(--ink-2);font-weight:500}
@media (prefers-reduced-motion: reduce){
.vxf .sheet, .vxf .scrim, .vxf .toast, .vxf .swipe-fore.is-settling, .vxf .swipe-wrap.is-going{transition:none}
}
.vxf .top{
  position:sticky;top:0;z-index:20;background:var(--ground);
  padding:14px 18px 8px;border-bottom:1px solid var(--line);
  display:flex;align-items:baseline;gap:10px;
}
.vxf .eyebrow{font-size:.62rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);font-weight:500}
.vxf h1{font-family:'Cormorant Garamond',Georgia,serif;font-weight:600;font-size:1.12rem;margin:0;letter-spacing:-.01em}
.vxf .refresh{
  margin-left:auto;appearance:none;border:1px solid var(--line);background:var(--surface);
  color:var(--ink-2);border-radius:999px;padding:5px 12px;font:inherit;font-size:.72rem;
  cursor:pointer;white-space:nowrap;
}
.vxf .refresh:hover{border-color:var(--green);color:var(--green)}
.vxf .pager{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none}
.vxf .pager::-webkit-scrollbar{display:none}
.vxf .leg-t.src-g{color:var(--gold-ink)}
.vxf .leg-t.src-d{color:var(--green)}
.vxf .leg-t.src-x{color:var(--ink-3)}
.vxf .leg-v{
  font-family:'DM Mono',monospace;font-size:.88rem;font-weight:500;
  font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--ink);
}
.vxf .leg-v.is-dash{color:var(--ink-3)}
.vxf a.act{display:inline-flex;align-items:center;justify-content:center;text-decoration:none}
.vxf .act.is-off{
  display:inline-flex;align-items:center;justify-content:center;flex:1;
  border-radius:999px;padding:12px 10px;font-size:.83rem;border:1px dashed var(--line);
  color:var(--ink-3);background:none;
}
.vxf .depth{
  margin:0 0 10px;font-family:'DM Mono',monospace;font-size:.66rem;
  letter-spacing:.02em;color:var(--ink-3);line-height:1.5;
}
.vxf .depth b{color:var(--warn);font-weight:500}
.vxf .foot{padding:0 20px 26px;font-size:.68rem;color:var(--ink-3);line-height:1.6}
.vxf .foot b{color:var(--ink-2);font-weight:500}

/* ── ⚑ ONE CALL, NOT FOUR — the whole-plan list above the class panes ──
   Stephen 2026-08-22: "We must use our data to find Operators that can meet
   the couple's needs with ONE call."

   Only the frame is new. The cards inside are `.card` / `.card-face` /
   `.route` / `.card-when` / `.card-meta`, which this stylesheet already has
   and which already look like the mockup — writing a second card here is the
   mistake this file has made four times. */
.vxf .vxf-whole{margin:0 0 18px;padding:0 0 16px;
  border-bottom:1px solid var(--line,rgba(35,38,31,.13))}
.vxf .vxf-whole-k{margin:0 0 4px;font-family:'DM Mono',monospace;font-size:.58rem;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3,#89907F)}
/* The count is the finding, so it is set like one — same face and weight the
   hero uses for the shape of the day. */
/* ⚑ `.card-weak` REMOVED 2026-09-08 with the cards. The rule it carried — the
   one-signal federal match said in WORDS, never in a `title=` no phone can
   show — did not go with it: it is the grid's "How we matched them" row, which
   is text in a cell and readable by anything that can read the table. */
.vxf .vxf-whole-lede{margin:0 0 12px;
  font-family:'Cormorant Garamond',Georgia,serif;font-weight:500;
  font-size:1.16rem;line-height:1.2;color:var(--ink,#23261F);text-wrap:balance}

/* ⚑ THE OLD COMPARE GRID, HIDDEN BY THE PRESENCE OF THE NEW ONE.
   Stephen 2026-08-22: "the card are to replace the compare table which is still
   visible on the new layout."

   `.vxf-live` goes on the HOST, and only once _vxRenderFindSurface has actually
   rendered cards — so a surface that returns early leaves the table in place
   rather than showing the couple an empty tab.

   ⚑ WHY CSS AND NOT setAttribute('hidden'). These elements are repainted by
   _refreshCompareV2, by the DocCompare surface and by every tab switch, and a
   repaint rebuilds them WITHOUT the attribute — which is exactly why he was
   still seeing the table after it was "hidden" twice. A class on the host
   survives any innerHTML write into a child, because the write never touches
   the host.

   ⚑ #docCompareSurface / #vxCmpWrap ARE CONTRACTS+, not this tab. Its quote
   uploader renders into this page and was appearing inside the transport
   shortlist — "something is loading into the card that should not be there." */
/* ⚑ THE COMPARE TABLE IS NO LONGER ONE OF THEM — 2026-09-08.
   Stephen, comparing Transportation against Venue on his phone: "it does not
   match the other Compare tables." It did not. Every other guide draws the
   shared `CRITERIA x VENDOR 1..5` grid; this one drew a stack of cards and then
   hid the grid underneath — a grid that was already being built, already
   populated, and already carrying nine transport-specific rows that read better
   than anything on the cards ("3 of 5 vehicles", "fleet not filed", a distance
   that names what it measured from).

   So the four selectors that hid it are gone. What still hides:
     .vx-cmp-tabs      the per-class tier strip — five categories of five
                       operators is the reading he retired 2026-08-27, and the
                       table is ONE table of FIVE now.
     .vx-tp-findnote   the search explainer — "a lot of text before we ever
                       scroll to the content."
     #docCompareSurface / #vxCmpWrap
                       Contracts+' quote uploader, which renders into this page
                       and has no business inside a transport shortlist. This
                       one is a BUG FIX, not a preference — keep it. */
.vxf-live .vx-cmp-tabs,
.vxf-live .vx-tp-findnote,
.vxf-live #docCompareSurface,
.vxf-live #vxCmpWrap{display:none !important}



/* ══════════════════════════════════════════════════════════════════════
   .vxh — the Plan's greeting card
   ──────────────────────────────────────────────────────────────────────
   Stephen 2026-08-22: "I want a card like Clear that greets the user with
   facts from their Plan", and "the budget could be moved into the summary of
   each vehicle type."

   ⚑ EVERY RULE IS SCOPED TO .vxh. The Find surface ships 121 rules with 0
   escaping its prefix, and that is why it could be added to a live page
   without touching anything else. Same contract here.

   ⚑ EVERY var() CARRIES A FALLBACK. An unresolved custom property does not
   leave the previous value — it makes the whole declaration `unset`, silently.
   That is what emptied the active tab on hover. These tokens are all defined
   on :root above, but a fallback costs nothing and removes the failure mode.
   ══════════════════════════════════════════════════════════════════════ */
.vxh{margin:0 0 14px}
.vxh-card{
  background:linear-gradient(158deg,var(--green,#2C4A3E) 0%,var(--green-2,#3E6353) 100%);
  color:var(--green-ink,#EAF0EA);
  border-radius:var(--r,14px);
  padding:16px 18px 14px;
  box-shadow:0 1px 2px rgba(35,38,31,.06),0 8px 24px rgba(35,38,31,.09);
}
.vxh-eyebrow{
  margin:0 0 6px;font-family:'DM Mono',monospace;font-size:.58rem;
  letter-spacing:.14em;text-transform:uppercase;opacity:.55;
}
/* The one serif line, same role the mockup gives .route — the thing you read
   first. Cormorant is the house face and is already loaded. */
.vxh-lede{
  margin:0;font-family:'Cormorant Garamond',Georgia,serif;font-weight:500;
  font-size:1.5rem;line-height:1.12;letter-spacing:-.01em;text-wrap:balance;
}
.vxh-arw{opacity:.45;padding:0 .34em}
/* ⚑ ONE ROW PER CLASS. Grid rather than flex so the money column aligns down
   the card however long a class name runs — "Motorcoach" and "Executive
   sedan" cannot push their own totals out of line with each other. */
.vxh-classes{
  margin:13px 0 0;padding:11px 0 0;
  border-top:1px solid rgba(255,255,255,.14);
  display:grid;gap:7px;
}
.vxh-cls{
  display:grid;grid-template-columns:1fr auto;
  align-items:baseline;column-gap:10px;
}
.vxh-cls-n{font-size:.84rem;font-weight:500}
.vxh-cls-m{
  grid-column:1;font-family:'DM Mono',monospace;font-size:.63rem;
  letter-spacing:.03em;opacity:.62;
}
/* Spans both rows of its column so the figure sits against the class name and
   its detail line, not floating beside one of them. */
.vxh-cls-c{
  grid-column:2;grid-row:1 / span 2;align-self:center;
  font-family:'DM Mono',monospace;font-size:.86rem;
  font-variant-numeric:tabular-nums;
}
.vxh-tot{
  margin:12px 0 0;padding:9px 0 0;
  border-top:1px solid rgba(255,255,255,.14);
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
}
.vxh-tot-k{
  font-family:'DM Mono',monospace;font-size:.58rem;
  letter-spacing:.14em;text-transform:uppercase;opacity:.55;
}
.vxh-tot-v{
  font-family:'Cormorant Garamond',Georgia,serif;font-size:1.28rem;
  font-weight:500;font-variant-numeric:tabular-nums;
}
@media (max-width:380px){
  .vxh-lede{font-size:1.3rem}
  .vxh-card{padding:14px 15px 12px}
}




/* ══════════════════════════════════════════════════════════════════════
   .vx-plan-cards — the day sheet as cards
   ──────────────────────────────────────────────────────────────────────
   Stephen 2026-08-22: "add the mockup look that I loved to the Plan and
   Compare steps."

   ⚑ PRESENTATION ONLY. Not one handler, attribute or id moves; the flag
   VX_PLAN_CARDS adds this class and one route span, and off, the DOM is what
   shipped. The day sheet is what he has to EDIT on Monday to re-enter Getting
   Ready — the surface that lost his stops is not being rewritten the week he
   needs it.

   ⚑ AND THE FACE IS LIGHT, WHICH IS A DEPARTURE FROM THE MOCKUP, DELIBERATELY.
   The mockup's card face is a dark green gradient. Auditing what actually sits
   inside .vx-rs-row: .vx-rs-clock is var(--green) — green on green, invisible —
   and .vx-rs-title, .vx-rs-movelab, .vx-rs-tripcaret, .vx-rs-facedel,
   .vx-rs-cont, .vx-rs-pin and .is-anchor .vx-rs-title are all coloured for a
   light background. Inverting the face means re-colouring a dozen children
   correctly, unseen, on the one surface that must work. The COMPOSITION is what
   he responded to — cards instead of a bordered list, the route leading, a
   clear hierarchy — and the dark green is carried by the hero directly above,
   which is how Clear layers it: one dark accent, light content beneath.
   Inverting these faces later is one rule, once he can look at it.
   ══════════════════════════════════════════════════════════════════════ */
/* The face is the top of the card now, not a card itself. */

.vx-plan-cards .vx-rs-row{
  align-items:flex-start;
  margin:0;padding:13px 14px 11px;
  background:none;border:0;border-radius:0;box-shadow:none;
}
/* The face and its detail are SIBLINGS, not nested — so they are joined by
   dropping the radius between them rather than by a wrapper that does not
   exist. `:has()` is already relied on a few rules up (`:has(+ .vx-rs-gaprow)`). */
/* ⚑ THE CALLOUT CAN SIT BETWEEN THEM NOW, and that broke this rule the moment
   it did. The tight-trip note renders under the face — that is where its
   triangle is — so `:has(+ .vx-rs-leglist)` stopped matching whenever one was
   open, and the card grew a rounded corner in its own middle. Both followers
   flatten the face, and the note flattens its own bottom when a stop list
   follows it. Caught by a gate asserting the two were siblings; the honest fix
   was the CSS, not the assertion. */
.vx-plan-cards .vx-rs-tightnote{
  border-left:0;border-right:0;border-bottom:0;border-radius:0;
  border-top:1px solid rgba(200,169,110,.34);
  margin:0;padding:11px 14px 12px;
}
/* ⚑ THE STOPS SIT INSIDE THE CARD, NOT ON ITS EDGE.
   Stephen 2026-08-24: "we also need to fix the stops with a trip for they are
   outside the trip box padding."

   The base rule is `padding:4px 0 10px 20px` — twenty on the left and ZERO on
   the right — which was correct while this list sat in a full-width sheet with
   no box around it. Inside a card it puts every drag grip on the border, and
   the stop text starts six pixels right of the trip name above it, so nothing
   lines up with anything.

   Matched to the face's own 14px so a stop's left edge is the trip name's left
   edge. The stops keep their own 20px rail indent on top of that, which is what
   draws the timeline down the left. */
/* ⚑ THE HANGING TIME NEEDS A GUTTER TO HANG IN. Stephen, twice: "the 'stops'
   within a 'trip' are outside the 'trip' box padding", and on 2026-08-25 a
   screenshot showing ":45a" sliced in half by the card's edge.

   ⚑ A MORE-SPECIFIC RULE UNDID HALF OF A PAIR. Two declarations make the leave
   time hang beside the stop names rather than indent them:

       .vx-rs-leglist{padding-left:20px}
       .vx-rs-leglist .vx-rs-leaveat{margin-left:-20px}

   This block overrode the padding to 14px and left the -20px alone, so the time
   rendered at -6px — six pixels OUTSIDE the card, which has overflow:hidden and
   simply cut it off. The negative margin was not wrong; its partner had moved.

   34px was the card's own 14px padding plus the 20px the marker hung by, so the
   time column started exactly on the card's left edge.

   ⚑ THE MARKER IS GONE, SO THE 20px IS TOO. Stephen 2026-08-27: "push the stop
   titles to align under the hours from the trip card (ie no left padding)."
   `.vx-rs-leaveat` — the thing that hung into that 20px — has not rendered in a
   plan card since the row rebuild routed both times through `_vxPlainClock()`,
   which strips the span and keeps the text. So the indent was paying for an
   element that no longer exists, and a stop name sat 20px right of the duration
   line directly above it. 14px is the card's own padding: the same edge as
   "3h 10m", the trip title, and the date. One text edge down the whole card. */
.vx-plan-cards .vx-rs-leglist{
  margin:0;padding:2px 14px 12px 14px;
  border:0;border-radius:0;background:none;
}
/* ⚑ AND NOTHING HANGS INTO A GUTTER THAT NO LONGER EXISTS. The base sheet pulls
   `.vx-rs-leaveat` 20px left, because on the RUN SHEET the time still sits in
   the margin beside the place names. A card has no such gutter any more — its
   times live in the clock pair on the right — so that negative margin has
   nothing to pull and would push a time 6px outside a card that clips it. That
   is not hypothetical: Stephen sent a screenshot of ":45a" cut in half by the
   card's edge, and plan-cards-validate has guarded the sum ever since. Stated
   here rather than left to arithmetic, so the guard is satisfied by
   construction instead of by a padding that happens to be large enough. */
.vx-plan-cards .vx-rs-leglist .vx-rs-leaveat{margin-left:0}
/* The grip is pulled two pixels right by a base rule written for a list with no
   right edge to hit. Inside a card there is one. */
/* ⚑ THE NOTES THE FACE USED TO CARRY, NOW AT THE TOP OF THE PANEL.
   Stephen 2026-08-27: "only the title and one line for every trip card so the
   cards are always the same size." The handover, the promise and the rota moved
   behind the caret rather than being hidden — see _vxTripNotes. On the face they
   were headline type on one line; here they are prose, so they read at the stop
   name's size and take the muted colour: supporting what the list below says,
   the same way the times are muted against the places. */
.vx-plan-cards .vx-rs-leglist .vx-rs-route{
  display:block;white-space:normal;overflow:visible;text-overflow:clip;
  font-size:var(--fs-stop,.6875rem);line-height:1.5;
  color:var(--text-mid,#5b625a);margin:0 0 7px}
.vx-plan-cards .vx-rs-leglist .vx-rs-movegrip{margin-right:0}
/* ⚑ AND NOTHING INSIDE MAY REACH PAST THE PADDING. A row that lays out wider
   than its container does not overflow visibly on a page that scrolls
   sideways — the deck DOES scroll sideways, so it would simply be lost. */
.vx-plan-cards .vx-rs-leglist > *{max-width:100%}
.vx-plan-cards .vx-rs-leglist .vx-rs-move{margin-left:0;margin-right:0}
/* ⚑ FLUSH WITH THE TITLE, ENDING AT THE CHEVRON — IN A CARD. Stephen
   2026-08-29: "could the indented content 'From, To, etc' start under the 'stop'
   title left edge and go to the right edge of the chevron?"

   The base rule insets 20px + 9px of padding, so a field began 29px right of the
   stop name above it — measured — and 44px on the right, clearing the grip AND
   the chevron. Two small insets that made the panel read as a third indent level
   inside a card that is already indented twice.

   ⚑ SCOPED TO `.vx-plan-cards`, NOT CHANGED AT SOURCE. The base 20px exists to
   clear the RUN SHEET's stop marker, which sits in that gutter
   (`.vx-rs-stop{padding-left:20px}` + an absolutely-placed dot). A card has no
   marker there, so the gutter is empty space here and load-bearing there.

   MEASURED after: the first field's left edge is the title's left edge exactly,
   and the panel ends 24px short of the row — the grip plus the grid's 10px gap,
   which is where the chevron ends. Vertical padding stays: breathing room, not
   indentation. */
.vx-plan-cards .vx-rs-movebody{
  flex:1 0 calc(100% - 24px);margin:0 24px 8px 0;padding:7px 0}
/* Title above, route below — the stacked pair the mockup leads with. It is
   flex:baseline today, which puts them on one line and truncates whichever
   loses. */
.vx-plan-cards .vx-rs-what{
  flex-direction:column;align-items:flex-start;gap:2px;overflow:visible;flex:1 1 auto;
}
/* ⚑ THE NAME LEADS, THE STOPS ARE THE CAPTION — AND THIS IS A SWAP.
   Stephen 2026-08-24: "the Trip name should [be] the font size of the stops and
   the stops should be the font size of the trips."

   It was the other way round for one render, on the argument that the route
   says what a trip DOES while the name only says what they call it. Wrong on
   his own data: "Getting Ready v2" is short and unmistakable, while
   "Equestria West at Bavaria Downs → Spalon Montage" took two lines and pushed
   the caret onto a third. The long string was the headline and the short one
   was the label, which is backwards for both reading and layout. */
.vx-plan-cards .vx-rs-title{
  font-family:'Cormorant Garamond',Georgia,serif;font-weight:500;
  font-size:1.16rem;line-height:1.16;letter-spacing:-.005em;
  color:var(--green,#2C4A3E);opacity:1;text-wrap:balance;
}
.vx-plan-cards .vx-rs-route{
  display:block;margin-top:2px;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-weight:400;
  font-size:.72rem;letter-spacing:.02em;line-height:1.35;
  color:var(--text-mid,#5b625a);
  /* One line, always. A multi-stop trip now says "Multiple stops", but a
     two-ended one can still carry two long venue names. */
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.vx-plan-cards .vx-rs-arw{opacity:.45;padding:0 .22em}
/* The anchor keeps its tint but takes the card's shape; its own border-top was
   drawn for a list and reads as a stray line across a card. */
.vx-plan-cards .vx-rs-row.is-anchor{
  background:rgba(44,74,62,.035);
  border-top:1px solid var(--line,rgba(35,38,31,.13));
}
/* A gap row is a prompt, not a trip — it keeps its amber ground and takes the
   card shape so it sits in the same rhythm. */
.vx-plan-cards .vx-rs-gaprow{
  background:rgba(200,169,110,.09);
  border-color:rgba(200,169,110,.34);
}
@media (max-width:380px){
  .vx-plan-cards .vx-rs-row{padding:11px 12px 10px}
  .vx-plan-cards .vx-rs-route{font-size:1.06rem}
}

/* ══════════════════════════════════════════════════════════════════════
   THE DAY BAR AND THE TRIP DECK
   ──────────────────────────────────────────────────────────────────────
   Stephen 2026-08-24: "can multiple trips carousel within a day but then a user
   pick another day using the bar that was on the mock-up so the screen more
   like the Clear sample and mobile friendly. The Clear cards are the sample
   size for every trip."

   ⚑ THE FIRST CUT SWIPED THE WRONG NOUN. It made a DAY the card, so a Saturday
   with six trips was one tall pane you scrolled inside — the opposite of Clear,
   where every card is one thing at one size and the deck is how you move
   between them. A day is a FILTER. It belongs on a bar you press.
   ══════════════════════════════════════════════════════════════════════ */
/* ⚑ DASHES, NOT PILLS. Stephen 2026-08-25: "replace the Wedding day and The day
   after buttons with the dash indicators… which would allow a user to select any
   day and then scroll through a carousel of trips on that day."

   The labels can go because every card now carries its own DATE in its top-left
   corner — the day is never something a couple reads off a control. The dashes
   say how many days there are and which one they are on, and give the width
   back to the cards. */
.vx-plan-cards .vx-rs-daydash{
  display:flex;gap:8px;justify-content:center;align-items:center;
  padding:4px 0 12px}

/* ⚑ A BAR, NEVER A BOX — AND THIS WAS A SPECIFICITY COLLISION OF MINE.
   Stephen 2026-08-25: "I do not want a box around the selector just a green bar
   if active and a gold bar if not."

   I wrote the dash twice: once as a 4px element with its own background, then
   again as a 22px hit area painting its bar through ::after. The second set
   turned the button transparent — but `.vx-rs-dash.is-on{background:…}` from the
   FIRST set is more specific than `.vx-rs-dash{background:none}` from the
   second, so the active day kept painting a full-height green box. Two rule sets
   for one control, and the older one won where it mattered.

   One set now. The button is never painted; the bar is the ::after, always.
   ⚑ THE HIT AREA IS THE BUTTON, NOT THE BAR. A four-pixel target is not a
   thumb — the button keeps a real height and the bar sits inside it. */
.vx-plan-cards .vx-rs-dash{
  position:relative;height:22px;width:30px;
  border:0;padding:0;margin:0;background:none;cursor:pointer;
  -webkit-appearance:none;appearance:none}
.vx-plan-cards .vx-rs-dash::after{
  content:"";position:absolute;left:0;right:0;top:9px;height:4px;border-radius:3px;
  /* Gold is the couple's own colour everywhere else in the product; a day they
     are not on is a day they can go to, which is an invitation, not a disabled
     state. */
  background:var(--gold,#C8A96E);
  transition:background .18s ease}
.vx-plan-cards .vx-rs-dash.is-on::after{background:var(--green,#2C4A3E)}
.vx-plan-cards .vx-rs-dash:hover::after{background:var(--gold-deep,#A07840)}
.vx-plan-cards .vx-rs-dash.is-on:hover::after{background:var(--green,#2C4A3E)}
.vx-plan-cards .vx-rs-dash:focus-visible{
  outline:2px solid var(--gold,#C8A96E);outline-offset:3px;border-radius:4px}

/* ⚑ THE PEEK IS THE SAME ARITHMETIC, POINTED AT A DIFFERENT THING. Narrower
   than the track, centre-snapped, spacers at each end so the first and last can
   still centre — only now what peeks is the next TRIP, which is what makes it
   read like Clear rather than like a paginated list. */
/* ⚑ EVERY DAY IS IN THE DOCUMENT; ONE IS ON SCREEN. Rendering only the selected
   day failed twenty-four assertions with "17 activities → 8 drawn" — Stephen's
   rule that every projected line is drawn and openable, and that the sheet and
   the price never disagree about what exists. Hidden, not absent, exactly as
   the offers block beside it already resolves the same tension. */
/* ═══════════════════════════════════════════════
   ⚑ THE GREETING — CONTEXT BEFORE THE CARDS, THE WAY CLEAR OPENS
   Stephen 2026-08-25, phone in hand beside the CLEAR+ app: "we need some
   context at the top of the screen like Clear."

   Clear sets a large serif line ("You're all set, Stephen") over one muted
   sentence of instruction, then the card. The proportions are the point: the
   name is the biggest thing on the screen, the instruction is quiet, and both
   together cost about 90px — you know where you stand before you scroll.

   The display face carries the headline because that is the voice this product
   already greets in; the sub is the body face at rest, not a second heading.

   ⚑ SCOPED TO .vx-plan-cards LIKE EVERY OTHER RULE IN THIS BLOCK, and a gate
   holds that line. The greeting renders INSIDE the `.vx-rs-rows.vx-plan-cards`
   wrapper — it leads `coreHtml` — so the scope is accurate rather than
   decorative. Unscoped, `.vx-pg-head` would be a global claim on three short
   class names from a block that belongs to one surface. */
.vx-plan-cards .vx-pg{padding:2px 4px 14px;max-width:100%}
.vx-plan-cards .vx-pg-head{
  margin:0 0 4px;
  font-family:var(--ff-d,'Cormorant Garamond',Georgia,serif);
  font-weight:500;font-size:1.62rem;line-height:1.12;
  letter-spacing:-.005em;color:var(--green,#2C4A3E);
  text-wrap:balance}
.vx-plan-cards .vx-pg-sub{
  margin:0;font-size:.88rem;line-height:1.45;
  color:var(--text-muted,#6E7A73);max-width:34em}
@media (max-width:767px){
  .vx-plan-cards .vx-pg{padding:0 2px 12px}
  .vx-plan-cards .vx-pg-head{font-size:1.46rem}
  .vx-plan-cards .vx-pg-sub{font-size:.84rem}
}

.vx-plan-cards .vx-rs-tripdeck:not(.is-on){display:none}
.vx-plan-cards .vx-rs-tripdeck{
  display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;
  align-items:flex-start;gap:12px;padding:2px 0 4px;
  scrollbar-width:none;-ms-overflow-style:none;
  /* Without this a swipe past the last trip triggers the browser's back
     gesture on iOS — the deck would navigate away from the plan being edited. */
  overscroll-behavior-x:contain}
.vx-plan-cards .vx-rs-tripdeck::-webkit-scrollbar{display:none}
.vx-plan-cards .vx-rs-tripdeck::before,
.vx-plan-cards .vx-rs-tripdeck::after{content:"";flex:0 0 4%}

/* ⚑ ONE TRIP IS ONE CARD, AND EVERY CARD IS THE SAME SIZE. His words: "the
   Clear cards are the sample size for every trip." The card owns the border and
   the radius now — the face and the stop list are its inside, so there are no
   corners to flatten between siblings and no :has() joins to keep in step. */
/* ⚑ EVERY CARD THE SAME HEIGHT, WHICH IS THE POINT OF A DECK.
   Stephen 2026-08-25: "the Trip cards are not the same height", and before
   that: "the Clear cards are the sample size for every trip."

   A `min-height` on the FACE was not enough — the card's total height still
   moved with the title wrapping to a second line, and the create card is taller
   than any of them. Cards that differ read as a styled list; cards that match
   read as a deck.

   ⚑ A FLOOR, NOT A FIXED HEIGHT, AND `align-items:stretch` IS NOT THE ANSWER.
   Stretch would make every card as tall as the tallest — which is right while
   they are all collapsed and very wrong the moment one is expanded, because an
   opened trip carrying six stops would drag its neighbours to the same height.
   A floor gives a uniform deck at rest and lets exactly the opened card grow. */
.vx-plan-cards .vx-rs-trip{
  flex:0 0 88%;max-width:88%;min-width:0;scroll-snap-align:center;
  display:flex;flex-direction:column;min-height:188px;
  background:var(--surface,#fff);
  border:1px solid var(--line,rgba(35,38,31,.13));
  border-radius:var(--r,14px);
  box-shadow:0 1px 2px rgba(35,38,31,.05);
  overflow:hidden}

/* ⚑ ON A DESKTOP THE DECK SHOWS A DECK. Stephen 2026-08-29: "I would like the
   trip cards to be the uniformed spacing on desktop and show more cards to
   scroll in the carousel."

   The 88% card is right on a phone — one trip, centred, thumb-swiped. On a
   960px column it shows ONE card against a third of a screen of nothing, and
   the 4% leading and trailing spacers scale with the viewport, so the gutters
   grow while the 12px gap between cards does not. That is the uneven spacing:
   two different units describing the same rhythm.

   A FIXED card width fixes both at once — three cards visible on a normal
   laptop, one unit of spacing everywhere, and the deck reads as a deck rather
   than as a single card that happens to slide.

   ⚑ AND THE SNAP CHANGES WITH IT. `center` + `mandatory` is right for one card
   at a time and wrong for three: it drags a partly-scrolled deck back to centre
   a card the couple was only glancing past. `start` + `proximity` lets them
   scroll freely and still land tidily. */


/* ══ ⚑ A CLOSED TRIP IS A CARD; AN OPEN ONE IS THE PAGE ══
   Stephen 2026-08-27, from the phone: "since I asked to use a carousel for the
   trips the card boxes are similar to the indented details of the Budget and
   then the data is indented even more for the stop details and is truncated. Is
   there a way to keep the trip on the smaller card but when a trip is expanded
   open to the full width of the page and use the Budget padding as the
   blueprint."

   ⚑ IT IS THE DECK INSET, NOT THE INNER PADDING. Measured on a 402pt iPhone,
   the stop name gets 106pt where the Budget line item gets 192pt, and the whole
   difference is the carousel: 39pt of page and section padding, then the deck's
   4% spacer, then a card that is only 88% of the track. The 34px inside the
   card is the SAME indent Budget gives its line list under the category title
   (20px past the card's own 14px), so it is the one part that was already
   right. Full width alone puts the name column at ~194pt — parity with Budget,
   which is exactly the blueprint he asked for.

   ⚑ THE SIBLINGS GO, RATHER THAN THE OPEN CARD GROWING PAST THEM. Widening a
   card in place inside a mandatory-snap scroll container means the browser
   re-snaps mid-resize and lands the couple on a half-shown card; the spacers,
   the scroll offset and the snap all have to be corrected together and Safari
   arbitrates the order. Hiding the neighbours makes the deck exactly one
   full-width card while it is open: nothing to scroll, nothing to re-snap, and
   closing restores the deck at the trip they were reading. The trade is that
   swiping to another trip means closing this one first — which the day bar
   above still makes obvious, and which is the same gesture Clear asks for. */
.vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open) > .vx-rs-trip:not(.is-open){
  display:none}
/* With one card left there is no track to snap along and no neighbour to
   centre against, so the spacers that buy the peek would only inset the page. */
.vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open){scroll-snap-type:none}
.vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open)::before,
.vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open)::after{flex-basis:0}
.vx-plan-cards .vx-rs-trip.is-open{flex:0 0 100%;max-width:100%}

/* ⚑ THE DESKTOP DECK RULES LIVE HERE, AFTER the open-card rules above, because
   they are the SAME specificity and source order is the entire argument. Placed
   earlier in the file they lose silently — which is exactly how this sheet once
   shipped a `display:grid` that a later `display:flex` beat. */
@media (min-width: 860px) {
  .vx-plan-cards .vx-rs-trip{
    flex:0 0 320px;max-width:320px;scroll-snap-align:start}
  .vx-plan-cards .vx-rs-tripdeck{scroll-snap-type:x proximity}
  /* One unit of spacing, not a percentage that drifts from the gap. */
  .vx-plan-cards .vx-rs-tripdeck::before,
  .vx-plan-cards .vx-rs-tripdeck::after{flex:0 0 2px}

  /* ⚑ AN OPEN CARD STAYS A CARD ON A DESKTOP. Stephen 2026-08-29: "I really
     want the expanded details to be the same size as the compressed trip card."
     It grows DOWN, not out.

     ⚑ THIS DOES NOT CONTRADICT "AN OPEN ONE IS THE PAGE" — it scopes it. That
     rule came from his phone on 2026-08-27, where the card is already 88% of the
     track and "full width" buys 12% and the deck's 4% spacers. On a 960px column
     the same rule turns a 320px card into an 1130px one, the neighbours vanish,
     and the deck a couple was reading rearranges itself under them. The phone
     behaviour below is untouched.

     ⚑ AND THE NEIGHBOURS CAN STAY, because the reason they were hidden was the
     widening itself: resizing a card inside a mandatory-snap track makes the
     browser re-snap mid-resize onto a half-shown card. Nothing widens here, and
     the deck is already `proximity` at this width, so there is nothing to fight.
     The deck top-aligns, so one tall card never drags its siblings. */
  .vx-plan-cards .vx-rs-trip.is-open{flex:0 0 320px;max-width:320px}
  .vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open) > .vx-rs-trip:not(.is-open){
    display:flex}
  .vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open){scroll-snap-type:x proximity}
  .vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open)::before,
  .vx-plan-cards .vx-rs-tripdeck:has(> .vx-rs-trip.is-open)::after{flex-basis:2px}
}
/* ── ⚑ A CARD HAS TO LOOK LIKE ONE OF SEVERAL ─────────────────────────
   Stephen 2026-08-26, from his phone: "the gray on the neutral background does
   not show the swipe to see next card well."

   The deck's whole affordance is the sliver of the NEXT card at the edge of the
   screen, and `--line` is rgba(35,38,31,.13) — thirteen percent of near-black,
   sitting on parchment. On a desktop that restraint is right; on a phone in
   daylight the edge of the card and the edge of the next one both disappear,
   and a deck that reads as a single panel is a deck nobody swipes.

   ⚑ ELEVATION, NOT A HEAVIER LINE. Clear — his own reference for these cards —
   separates them by lift rather than by stroke, and a darker border on a warm
   ground reads as a table. The shadow does the separating; the border is only
   nudged far enough to hold the corners.

   Scoped to the phone: the desktop deck shows whole cards side by side and
   never needed the help. */
@media (max-width:760px){
  .vx-plan-cards .vx-rs-trip{
    border-color:rgba(35,38,31,.2);
    box-shadow:0 2px 10px rgba(35,38,31,.1), 0 1px 2px rgba(35,38,31,.06)}
}
/* ⚑ THE HANDOVER LINE — a fact about the day, deliberately not a warning.
   It sits under the route in the same quiet type, because "two vehicles rather
   than one waiting" is the plan working, not a problem to flag. Given room to
   wrap: it is a sentence, not a label, and clipping it would lose the half that
   rules out the misreading. */
.vx-plan-cards .vx-rs-handover{
  display:block;margin-top:3px;
  white-space:normal;overflow:visible;text-overflow:clip;
  color:var(--text-mid,#5b625a)}

/* ⚑ THE PROMISE — the offer and the stress it survives, in one quiet line.
   Set like the route rather than like a banner: it is the most reassuring thing
   on the card and would read as a warning if it were coloured. */
.vx-plan-cards .vx-rs-promise{
  display:block;margin-top:3px;
  white-space:normal;overflow:visible;text-overflow:clip;
  color:var(--text-mid,#5b625a)}

/* ⚑ THE CAR ROSTER — the evening, arranged. Set in the sheet's own quiet type
   and given room to wrap: it is a list of times, and clipping it would hide the
   later cars, which are exactly the ones a couple is unsure about. The car
   labels carry the weight so the eye can find the groups without a table. */
.vx-plan-cards .vx-rs-rota{
  display:block;margin-top:3px;
  white-space:normal;overflow:visible;text-overflow:clip;
  color:var(--text-mid,#5b625a)}
.vx-plan-cards .vx-rs-rota-car{font-weight:600;color:var(--green,#2C4A3E)}
.vx-plan-cards .vx-rs-rota-sep{color:var(--line,rgba(35,38,31,.35))}

/* The face takes the slack so the foot sits on the bottom edge of every card,
   at the same height across the deck — the white bar on a Clear card. */
.vx-plan-cards .vx-rs-trip > .vx-rs-row{flex:1 1 auto}
/* ⚑ REMOVE TRIP — WORDED, QUIET, AND LAST. Stephen 2026-08-25: "move the
   'Remove trip' inside the details like Clear."
   It reads as text rather than as a button because it is the one destructive
   thing in the panel and should not compete with "Add a stop" directly above
   it. Muted until touched, then it states plainly what it does. */
/* ⚑ REMOVE STOP — the same control as Remove trip, one level up. Stephen
   2026-08-27: "testing supports adding a quiet 'Remove stop' at the foot of the
   expanded panel, mirroring the 'Remove trip'."
   Same type, same muted-until-touched colour, same destructive-action-last
   position. It carries more vertical padding than its twin for one reason: this
   one sits inside a dense panel of 38px fields, and a 24px target beside them
   would be the smallest thing on the row a thumb has to find. */
.vx-plan-cards .vx-rs-delstop{justify-content:flex-start;padding-top:2px;gap:18px}
.vx-plan-cards .vx-rs-delstopbtn{appearance:none;background:none;border:0;padding:10px 0;
  font:inherit;font-size:.76rem;letter-spacing:.01em;min-height:38px;
  color:var(--text-muted,#88928d);cursor:pointer;text-align:left}
.vx-plan-cards .vx-rs-delstopbtn:hover,.vx-plan-cards .vx-rs-delstopbtn:focus-visible{
  color:var(--danger,#9B3B2F);text-decoration:underline}
.vx-plan-cards .vx-rs-delstopbtn:focus-visible{
  outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
/* ⚑ THE NON-DESTRUCTIVE TWIN, and it must not read as the destructive one.
   Same size and same row as Remove stop so the pair reads as one question —
   "what do you want to do with this stop" — but it takes the green on hover
   where its neighbour takes the danger red. The row is flex, so the two sit
   side by side with Remove last: the reversible choice is met first. */
.vx-plan-cards .vx-rs-movestopbtn{appearance:none;background:none;border:0;padding:10px 0;
  font:inherit;font-size:.76rem;letter-spacing:.01em;min-height:38px;
  color:var(--text-muted,#88928d);cursor:pointer;text-align:left}
.vx-plan-cards .vx-rs-movestopbtn:hover,.vx-plan-cards .vx-rs-movestopbtn:focus-visible{
  color:var(--green,#2C4A3E);text-decoration:underline}
.vx-plan-cards .vx-rs-movestopbtn:focus-visible{
  outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
.vx-plan-cards .vx-rs-deltrip{justify-content:flex-start;padding-top:2px}
.vx-plan-cards .vx-rs-deltripbtn{
  appearance:none;background:none;border:0;padding:4px 0;
  font:inherit;font-size:.76rem;letter-spacing:.01em;
  color:var(--text-muted,#88928d);cursor:pointer;text-align:left}
.vx-plan-cards .vx-rs-deltripbtn:hover,
.vx-plan-cards .vx-rs-deltripbtn:focus-visible{
  color:var(--danger,#9B3B2F);text-decoration:underline}
.vx-plan-cards .vx-rs-deltripbtn:focus-visible{
  outline:2px solid var(--gold,#C8A96E);outline-offset:2px}
.vx-plan-cards .vx-rs-cardfoot{margin-top:auto}
.vx-plan-cards .vx-rs-trip.is-off{opacity:.55}
.vx-plan-cards .vx-rs-trip.is-dragging{
  box-shadow:0 8px 26px rgba(35,38,31,.18);border-color:var(--gold,#C8A96E)}

/* ══ THE CARD, LAID OUT THE WAY CLEAR LAYS ONE OUT ══
   Stephen 2026-08-25: "a trip should have the date in the top left corner, the
   number of hours before or after the ceremony start time in the top right
   corner, the trip title positioned like the Clear sample, and the # of days
   until the trip."

   ⚑ EVERY CARD IS THE SAME SIZE — his words, "the Clear cards are the sample
   size for every trip". A deck whose cards differ in height reads as a list
   that has been styled, not as a deck. The face is a column with a fixed
   minimum and the title takes the slack, so a one-word trip and a four-line one
   are the same box. */
.vx-plan-cards .vx-rs-cardtop{
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding:12px 14px 0}
.vx-plan-cards .vx-rs-carddate{
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;
  letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted,#88928d);white-space:nowrap}
/* ⚑ THE DATE SAYS IT CAN BE PRESSED. Stephen 2026-08-29: "I could not change a
   date on a Trip." It always could — from the title — so what was missing was
   not the control but any sign there was one. A dotted underline is the sheet's
   quietest affordance: readable as a label first, offering itself second, which
   is what a card meant to be read wants. */
.vx-plan-cards .vx-rs-carddate[data-rs-dayedit]{
  cursor:pointer;border-bottom:1px dotted var(--line,#D8D2C6);padding-bottom:1px}
.vx-plan-cards .vx-rs-carddate[data-rs-dayedit]:hover,
.vx-plan-cards .vx-rs-carddate[data-rs-dayedit]:focus-visible{
  color:var(--green,#2C4A3E);border-bottom-color:var(--green,#2C4A3E)}
.vx-plan-cards .vx-rs-cardrel{
  font-family:var(--ff-m,'DM Mono',monospace);font-size:.58rem;
  letter-spacing:.06em;color:var(--gold-deep,#A07840);
  white-space:nowrap;text-align:right}
.vx-plan-cards .vx-rs-cardrel.is-anchor{color:var(--green,#2C4A3E)}

/* The face is the body of the card: the title fills it, so every card ends at
   the same height whatever the title does. */
/* ⚑ THE HEADLINE STANDS OFF THE TOP ROW. Stephen 2026-08-25: "the 'trip'
   carousel card should have larger padding between the top row and the 'trip'
   title and look identical to the Clear layout."
   On a Clear card the flight number and time sit in their own register at the
   top, then a deliberate gap, then MDW → MSP as the headline. Eight pixels read
   as one crowded block of four type sizes; this is the gap that separates the
   label from the thing it labels. */
.vx-plan-cards .vx-rs-row{
  flex-direction:column;align-items:stretch;
  margin:0;padding:24px 14px 0;min-height:104px;
  background:none;border:0;border-radius:0;box-shadow:none}
/* ⚑ THE TITLE SITS LOW. Stephen 2026-08-25: "bottom justify the title so it is
   similar to the Clear example." On a Clear card the flight number rides the
   top edge, then air, then MDW → MSP sitting just above the white foot. Centred
   put the headline in the middle of the card with air on both sides, which
   reads as a label floating rather than as a headline anchored to its foot. */
.vx-plan-cards .vx-rs-what{flex:1 1 auto;justify-content:flex-end;padding-bottom:2px}
/* ⚑ THE TITLE IS THE HEADLINE, THE WAY MDW → MSP IS. It clamps rather than
   truncating on one line: a trip called "Guests: Shuttles to the Westin" should
   read, and a card that is the same size as its neighbours cannot let it run. */
.vx-plan-cards .vx-rs-title{
  font-size:1.28rem;line-height:1.14;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
.vx-plan-cards .vx-rs-when{
  order:-1;font-size:.62rem;opacity:.7;align-self:flex-start}

.vx-plan-cards .vx-rs-cardfoot{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin:8px -14px 0;padding:9px 12px 9px 14px;
  border-top:1px solid var(--line,rgba(35,38,31,.10))}
.vx-plan-cards .vx-rs-cardin{
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;
  color:var(--green,#2C4A3E);white-space:nowrap}
.vx-plan-cards .vx-rs-cardfoot .vx-rs-acts{margin-left:auto;margin-top:0}

/* The create card matches the others rather than being a tall dashed box. */
/* ⚑ IDENTICAL TO EVERY OTHER CARD — Stephen 2026-08-26: "I want the 'Add a
   trip' card to look identical to the other cards for branding - this works
   well on the Clear app screens."
   This REVERSES the dashed treatment and the rule that guarded it: plan-swipe
   asserted the pane must be dashed so it could not "impersonate a day". The
   worry was real, but the answer was chrome; his is branding, and the card
   already distinguishes itself by what it SAYS — an eyebrow, "Add a trip", and
   a sentence telling you what belongs there. A day with nothing in it says none
   of that. So the distinction moved from the border to the copy, and the gate
   moved with it rather than being deleted. */
.vx-plan-cards .vx-rs-trip.is-new{
  border-style:solid;border-color:var(--line,rgba(35,38,31,.13))}

/* ⚑ THE CONTROLS SIT BESIDE THE TEXT, NOT UNDER IT.
   Stephen 2026-08-24, photographing the card: "this layout is wrapping."
   `.vx-rs-what` is a COLUMN — the trip name above its route — and the grip, the
   triangle, the flag and the caret were all inside it, so each took a line of
   its own and the card grew a tall empty middle. They are their own group now,
   and it never wraps. */
.vx-plan-cards .vx-rs-acts{margin-top:-2px}
/* A trip's name and route may take the width they need; the controls never
   compete for it. */
.vx-plan-cards .vx-rs-what{min-width:0;flex:1 1 auto}
.vx-plan-cards .vx-rs-title,
.vx-plan-cards .vx-rs-route{max-width:100%}

/* ══ THE CARD THAT MAKES A TRIP — its own pane, the way Clear ends its deck ══
   Stephen 2026-08-24: "the add a trip should be its own tab and the day and
   time are entered similar to the Clear example." */
.vx-plan-cards .vx-rs-daypane.is-new{
  display:flex;flex-direction:column;justify-content:flex-start}
/* ⚑ ONE DASHED BOX, NOT A BOX INSIDE A BOX. Stephen 2026-08-26: "'Add a trip'
   is a box within the card — the dotted line."
   Right, and it was drawn twice: `.vx-rs-trip.is-new` already carries
   `border-style:dashed` (13349), and this pane added a second dashed border and
   a second surface inside it. The CARD keeps the dash, because it is also what
   gives the create affordance the deck's sizing and scroll-snap; the pane is
   just its contents and needs no chrome of its own. */
.vx-plan-cards .vx-rs-newpane{
  padding:16px 15px 14px;
  background:none;border:0;border-radius:0}
.vx-plan-cards .vx-rs-newpane-k{
  margin:0 0 5px;font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;
  letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted,#88928d)}
.vx-plan-cards .vx-rs-newpane-t{
  margin:0;font-family:'Cormorant Garamond',Georgia,serif;font-weight:500;
  font-size:1.32rem;line-height:1.1;color:var(--green,#2C4A3E)}
.vx-plan-cards .vx-rs-newpane-s{
  margin:7px 0 12px;font-size:.76rem;line-height:1.5;color:var(--text-mid,#5b625a)}
/* Inside its own pane the form is the content, so it is open rather than an
   invitation to open something. */
.vx-plan-cards .vx-rs-newpane .vx-rs-add{margin:0;background:none;padding:0}
/* A dot for the create pane reads as an action, not as another day. */
.vx-plan-cards .vx-rs-daydot.is-new{
  background:rgba(200,169,110,.55);width:14px}
.vx-plan-cards .vx-rs-daydot.is-new[aria-current="true"]{
  background:var(--gold,#C8A96E);width:26px}
/* Parked out of the deck, still in the document — nineteen assertions protect
   every projected line being drawn and openable. */
.vx-plan-cards .vx-rs-offerpark{margin:14px 0 0}


@media (max-width:380px){
  .vx-plan-cards .vx-rs-daypane{flex-basis:90%;max-width:90%}
  .vx-plan-cards .vx-rs-daypager::before,
  .vx-plan-cards .vx-rs-daypager::after{flex-basis:5%}
}



/* ══════════════════════════════════════════════════════════════════════
   .vx-botnav — four squared tiles on the bottom edge, phone only
   ──────────────────────────────────────────────────────────────────────
   Stephen 2026-08-25: "On mobile… create a [bar] on the bottom of the screen
   that operates like demo to allow a user to move between the Plan | Compare |
   Interview | Contracts+ and then like Clear more squared tiles."

   ⚑ THE TOP STRIP IS WHERE A THUMB IS NOT. On a phone the tabs sit under the
   header, the totals and the title — furthest from the hand and first to scroll
   away. Clear puts its destinations on the bottom edge and never moves them.

   ⚑ PHONE ONLY. On a laptop the strip is already in reach and a fixed bar would
   just eat the window, so this appears below 768px and the strip keeps the
   desktop. Both exist in the DOM at all widths; only one is ever shown.
   ══════════════════════════════════════════════════════════════════════ */
/* ⚑ THE SEARCH WARMS; THE PAGE DOES NOT ADVERTISE IT. Stephen 2026-08-25:
   "none of screenshot #1 should be on the page" — the Find operators button was
   in it.

   ⚑ AN ATTRIBUTE WAS NOT ENOUGH, AND THAT IS THE INTERESTING PART. The markup
   carries `hidden`, and the button still rendered: `_vxMountFindOperators`
   BUILDS ITS OWN `.vx-tp-findops` box when it wants one, so the hidden div in
   the shell and the div the mount creates are two different elements answering
   to one class. Hiding by class catches both; hiding by attribute caught the
   one that was never the problem.

   Display, not removal — the mount must still run. The shortlist has to exist
   BEFORE Compare is opened and Compare deliberately does not mount the search,
   so deleting the call would drop the operator list back to registry rows. */
.vx-tp-findops{display:none}

/* ⚑ THE BREADCRUMB YIELDS THE BOTTOM EDGE TO THE NAV.
   `#mh-back-bar` is `position:fixed; bottom:0`, 52px tall, full width, at
   z-index 66 — ABOVE the nav's 60. It covered the bottom 23px of the tiles, so
   the labels rendered clipped in half.

   ⚑ I MEASURED THE CENTRE AND CALLED IT CLEAR. `elementFromPoint` at each
   tile's midpoint returned the tile, so the first check said the nav was
   reachable — while its lower edge was under the breadcrumb the whole time.
   Sample an element's EDGES, not its middle.

   Stephen asked for this bar to go on mobile anyway ("hide all of the content
   in screenshot #1"), and two fixed bars competing for one edge is a collision
   by construction. On a phone the nav wins; the desktop keeps its breadcrumb. */
@media (max-width:767px){
  body:has(.vx-botnav) #mh-back-bar{display:none}
  /* ⚑ AND NEITHER IS THE SITE FOOTER. Stephen 2026-08-25, from his phone: "the
     footer menu is not on mobile."
     PRIVACY / TERMS / SUPPORT / ACCOUNT and a copyright line sat directly above
     the bottom nav — two navigations stacked on the same edge, the lower one
     permanent and the upper one legal boilerplate. On a desktop the footer ends
     a long page; on a phone it interrupts the one control that matters. Scoped
     to surfaces that grow a bottom nav, so every other page keeps its footer. */
  body:has(.vx-botnav) .site-footer{display:none}
  /* The help tab sits above the nav rather than on it.

     ⚑ `!important` HERE ONLY BECAUSE THERE IS ALREADY ONE TO BEAT. The mobile
     block sets `.vx-help-tab{bottom:calc(24px + env(safe-area-inset-bottom))
     !important}`, which wins over any specificity this selector could reach —
     the first version of this rule matched the element, computed nothing, and
     the tab went on covering the Contracts+ tile. An !important is the correct
     answer to an !important and the wrong answer to anything else.

     ⚑ AND IT KEEPS THE SAFE-AREA INSET IT IS OVERRIDING. That 24px + env() was
     Stephen's own device pass — the home indicator left the pill half
     off-screen without it. Restated here rather than dropped, with the banner
     and the nav's MEASURED height added on top. `--vx-botnav-h` is published by
     _vxBotNavSync from the bar's own offsetHeight, so this cannot go stale when
     the tiles are restyled. */
  /* ⚑ TWO SELECTORS, BECAUSE THERE ARE TWO RULES TO BEAT AND ONLY ONE OF THEM
     IS OBVIOUS. The mobile block sets `.vx-help-tab{bottom:24px !important}`,
     which the first selector clears. It ALSO carries, 240 lines further down:

         #mh-back-bar.is-visible ~ .vx-help-tab{bottom:calc(8px + env(...))
                                                !important}

     — "when the in-section back bar is showing, the pill docks into that same
     row" (Stephen, 2026-07-08). Specificity 0,1,2,0 against this rule's
     0,1,1,1, both !important, so it won and the pill stayed at 8px. Measured:
     injecting this exact declaration into <head> at runtime moved nothing,
     while an INLINE !important moved it — which is what says "outranked" rather
     than "invalid".

     ⚑ AND ITS PREMISE IS NOW FALSE WITHOUT SAYING SO. The bar is hidden on this
     surface, but `display:none` does not remove `.is-visible`, so the pill went
     on docking to a row nobody can see. The second selector matches that same
     shape at 0,2,2,0 and wins. Left as an override rather than editing the
     docking rule, because that rule is still correct everywhere the bottom nav
     does not exist — which is every other guide in the product. */
  /* ⚑ THE FALLBACK IS 56px, NOT 0. MEASURED 2026-08-26, in his own Chrome:
     with `--vx-botnav-h` unset or 0 the pill's box ends 25px BELOW the top of
     the nav — it sits on the tiles. The variable is published by JS
     (_vxBotNavSync, interviews/verdeaux-interview.js ~3279), so a `0px`
     fallback made a correct layout depend on a script having already run, and
     the failure it produces is precisely the overlap Stephen reported.

     56px clears the measured 49px bar with room, so the unmeasured state is
     merely a little generous instead of broken, and the measured value is only
     ever a small correction rather than a 49px jump. A fallback should be the
     safe answer, never the null one — an unresolved var() that lands on 0 is
     the same trap as an unresolved var() with no fallback at all. */
  body:has(.vx-botnav) #vxHelpTab,
  body:has(.vx-botnav) #mh-back-bar.is-visible ~ #vxHelpTab{
    bottom:calc(24px + env(safe-area-inset-bottom, 0px)
      + var(--vx-envbar-h,0px) + var(--vx-botnav-h,56px)
      /* ⚑ AND THE DOCKED ACTION, when there is one. Stephen 2026-08-26 asked
         for "Find operators" and "Clear this table" locked above the footer —
         a THIRD fixed element on an edge that already holds two. Without this
         term the pill sits on the button, which is the overlap he reported
         this morning arriving again by a different route.

         0px is the right fallback here, unlike --vx-botnav-h's 56px: most
         surfaces have no dock at all, so the unmeasured state IS zero rather
         than an unknown. _vxDockSync publishes the measured value the moment
         one mounts. */
      + var(--vx-actiondock-h,0px)) !important}

  /* ── The docked action bar itself ─────────────────────────────────────
     Phone only, and only where the bottom nav exists — on desktop these cards
     stay in the document flow where they were, so nothing above 767px moves. */
  /* ⚑ NO SAFE-AREA INSET HERE — THE NAV ALREADY OWNS IT.
     Stephen 2026-08-26: "when I add to Home screen the bottom menus are
     removed." Standalone is a different layout, not a cropped one: the manifest
     says `display:standalone`, Safari's toolbar goes, and
     `env(safe-area-inset-bottom)` stops being ~0 and becomes the 34px home
     indicator.
     `.vx-botnav` pads itself by that inset ("THE HOME INDICATOR EATS THE LAST
     ROW"), so `--vx-botnav-h` — a MEASURED offsetHeight — already contains it.
     Adding it again here counted it twice and floated this bar 34px above the
     nav with a gap under it. Invisible in Chrome, invisible in simulator Safari
     WITH the toolbar, visible only on the Home Screen install — which is how he
     actually uses it. This file already warns about exactly this at the
     Contracts+ bar: "double-counting the inset in standalone mode".
     The dock's own padding drops it for the same reason: this bar does not
     touch the screen edge, the nav below it does. */
  body:has(.vx-botnav) .vx-tp-dock{
    position:fixed;left:0;right:0;z-index:60;
    bottom:calc(var(--vx-envbar-h,0px) + var(--vx-botnav-h,56px));
    margin:0;padding:10px 14px;
    background:var(--bg, #FBFAF8);
    border-top:1px solid rgba(44,74,62,.14);
    box-shadow:0 -6px 18px -12px rgba(24,28,31,.35);
    display:flex;gap:10px}
  body:has(.vx-botnav) .vx-tp-dock > button{flex:1 1 auto;min-height:44px}
  /* The scroll container has to end above the dock or the last trip is behind
     it — a fixed bar hides content it does not push.

     ⚑ THE FIRST VERSION OF THIS RULE MATCHED NOTHING. It named `.vx-guide-body`
     and `.vx-phase-body`, and neither class exists on this page — MEASURED live
     in his Chrome during UAT: the dock's own parent chain is
     `.phase-section#vdx-phase-6` (22px of padding) inside a `body` that scrolls.
     A 66px bar over 22px of clearance hides 38px of the last card, and it was
     invisible only because his plan was short enough not to scroll yet.

     A CSS rule is not wrong when it looks wrong; it is wrong when it selects
     nothing, and that failure is silent. Hence the gate now checks the class it
     targets actually appears in the markup — asserting the rule TEXT exists
     proved only that I had typed it. */
  body:has(.vx-botnav):has(.vx-tp-dock) .phase-section{
    padding-bottom:calc(var(--vx-actiondock-h,0px) + 22px)}
}

/* ── Clear this table ───────────────────────────────────────────────────
   Quiet by default. It removes work, so it should not look like the primary
   action next to a button that creates it — but it is a real control a couple
   is meant to find, not a hidden one. */
.vx-tp-clearbtn{
  appearance:none;border:1px solid rgba(44,74,62,.28);background:transparent;
  color:var(--text-mid,#5A6B63);border-radius:9px;padding:11px 16px;
  font:inherit;font-size:.9rem;cursor:pointer;min-height:44px}
.vx-tp-clearbtn:hover{border-color:rgba(185,64,64,.45);color:#B94040}
.vx-tp-clearbtn:focus-visible{outline:2px solid #B94040;outline-offset:2px}
.vx-tp-cmpactions{display:flex;justify-content:flex-end;margin:18px 0 4px}
/* ── The bottom bar's three parts ─────────────────────────────────────── */
/* ⚑ THE SAME PILLS, NOT SIMILAR ONES. Every value below is copied from the
   control it has to match on the guide index — `#mh-back-btn` for Home,
   `.vx-help-tab`'s mobile block for Help — so the two screens are identical
   through the transition rather than approximately alike.
   ⚑ AND `min-height:38px` IS GONE. It was mine, for touch, and it was the whole
   height difference he spotted: it forced a taller box than the index pill's
   natural ~29px. These are below the 44pt guideline, but they are the size he
   already ships everywhere else, and matching is the ask. */
.vx-botnav-side{
  -webkit-text-size-adjust:100%;text-size-adjust:100%;
  appearance:none;background:transparent;border:1px solid rgba(44,74,62,.2);
  border-radius:20px;padding:6px 16px;flex:0 0 auto;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.78rem;font-weight:500;
  color:var(--green,#2C4A3E);cursor:pointer;display:flex;align-items:center;gap:5px;
  white-space:nowrap}
.vx-botnav-side:active{background:rgba(44,74,62,.06)}
.vx-botnav-side:focus-visible{outline:2px solid var(--green,#2C4A3E);outline-offset:2px}
/* Help reads as the assistive one, matching the pill it replaces here. */
.vx-botnav-side[data-bot-help]{
  background:var(--gold-deep,#A07840);border-color:transparent;color:#fff;
  border-radius:18px;padding:9px 18px;gap:6px;
  font-family:var(--ff-d,'Cormorant Garamond',serif);font-style:italic;
  font-size:12.5px;letter-spacing:.08em}

/* ⚑ THE ARROWS DO NOT MOVE WHEN THE WORD DOES. Stephen 2026-08-26: "is there
   any way to make the menu area consistent so the arrows are in the same
   location on every tab - that would be ideal."
   `justify-content:center` centred all three children as a GROUP, so "Plan"
   (4 letters) and "Contracts+" (10) pushed the arrows to different places and
   the control moved under his thumb between tabs. Pinned to the edges of the
   stepper instead, with the label taking the space between them. */
.vx-botnav-step{
  flex:1 1 auto;min-width:0;display:flex;align-items:center;
  justify-content:space-between;gap:2px}
.vx-botnav-arw{
  appearance:none;background:transparent;border:0;cursor:pointer;
  width:34px;min-height:38px;flex:0 0 auto;
  font-size:1.15rem;line-height:1;color:var(--green,#2C4A3E)}
/* ⚑ DIMMED, NOT HIDDEN. A control that vanishes at the end of a list moves the
   one beside it; dimming keeps the row still and says "this is the edge". */
.vx-botnav-arw:disabled{opacity:.22;cursor:default}
.vx-botnav-arw:focus-visible{outline:2px solid var(--green,#2C4A3E);outline-offset:2px;border-radius:8px}

/* ⚑ EVERY TAB KEEPS ITS BUTTON, ONE IS SHOWN. The arrows work by clicking the
   hidden buttons, so their handlers must stay in the document — hiding by
   `display:none` on the others is what makes one label read as the position
   without giving the stepper a second source of truth. */
.vx-botnav-now{
  appearance:none;background:transparent;border:0;display:none;
  /* Takes the room between the two arrows and centres in it, so the word moves
     and the controls do not. */
  flex:1 1 auto;text-align:center;
  padding:0 4px;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;cursor:default;
  /* ⚑ AND SAFARI STOPS RESIZING IT. Stephen: "the font sizing for Plan looks
     smaller than Compare." It is not the font-size — nothing in this file ever
     set `text-size-adjust`, so iOS Safari's default `auto` INFLATES text by a
     factor derived from its block's width. One label at a time, each a
     different length, each inflated differently. Chrome does not do this at any
     width, which is why every measurement on the desktop said the two were
     identical. Pinned here rather than globally: `html{-webkit-text-size-adjust
     :100%}` is the usual fix and probably the right one, but it would change
     type across the whole product on iOS and that deserves its own look. */
  -webkit-text-size-adjust:100%;text-size-adjust:100%;
  font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.82rem;font-weight:600;
  letter-spacing:.01em;color:var(--green,#2C4A3E)}
.vx-botnav-now.is-on{display:block}

/* ⚑ AND THE FLOATING PILLS STAND DOWN where the bar carries them. Two Homes and
   two Helps on one screen is worse than none — and the help pill floating above
   this row is exactly the stack this change exists to remove. */
body:has(.vx-botnav) #vxHelpTab{display:none!important}
.vx-botnav{display:none}
@media (max-width:767px){
  .vx-botnav{
    /* ⚑ ONE ROW: HOME, WHERE YOU ARE, HELP. Stephen 2026-08-26: "can we add the
       nav bar between the home & help pills showing the tab that the user is on
       and left & right arrows on the edge of the nav to move between tabs?"
       Four equal tiles became a stepper, which does three things at once — it
       gives Home back (the guide had no way out at all), it states the current
       section instead of making a couple read four labels to find the lit one,
       and it collapses the pill / nav / pill stack that every overlap bug on
       this edge tonight came from. */
    display:flex;align-items:center;justify-content:space-between;gap:8px;
    /* ⚑ ABOVE THE BRANCH BANNER, WHICH OWNS THE BOTTOM EDGE ON EVERY PREVIEW.
       `--vx-envbar-h` is set by that banner AFTER measuring itself. The `0px`
       fallback is load-bearing twice over: production never sets the variable,
       and an unresolved var() with no fallback does not fall back to the
       previous value — it makes the whole declaration `unset`, which would drop
       `bottom` entirely and float the nav at the top of the window. */
    position:fixed;left:0;right:0;bottom:var(--vx-envbar-h,0px);z-index:60;
    /* ⚑ THE SAME SURFACE #mh-back-bar USES, NOT A SECOND ONE. Stephen
       2026-08-27, comparing the two screens: "the footer on the transportation
       guide is not aligned to the footer on all of the other mobile screens"
       — "Color and position."

       Position was the offset, fixed earlier today (both bars now sit at
       `bottom:var(--vx-envbar-h)`), and the paddings already matched. COLOUR was
       still two different footers: this was `--surface` (WHITE) with a 16px
       lift, while every other mobile screen uses `#mh-back-bar` — near-opaque
       CREAM, a 12px backdrop blur, and no shadow. On a cream page that reads as
       a distinct white panel floating over the content rather than as the same
       footer the rest of the app has.

       Copied from that rule literally rather than approximated, so a later
       restyle of one cannot silently diverge from the other. The shadow goes
       with it: the blur is what separates the bar from what scrolls under it
       there, and two separation devices on one edge is what made this look like
       a different component. */
    background:rgba(250,247,242,.96);
    backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
    border-top:1px solid rgba(44,74,62,.1);
    /* ⚑ THE HOME INDICATOR EATS THE LAST ROW. Without the safe-area inset the
       bottom tile sits under iOS's own bar and cannot be pressed. */
    /* ⚑ THE INDEX BAR'S OWN PADDING — Stephen 2026-08-26: "could you set the
       'Home' and 'Help' pills in the same location as the index pills so the
       screen is identical when a user navigates."
       `#mh-back-bar` is `padding:10px 16px calc(10px + safe-area)`. Matching it
       here is what puts the two pills at the same x on both screens, so moving
       between the guide index and a guide does not shift the controls under a
       thumb. */
    /* ⚑ CENTRED IN THE BAND, NOT PINNED TO ITS TOP EDGE. Stephen 2026-08-27:
       "could the pills and the new navigation be aligned to the center rather
       than top of the footer for that may help the feeling of out of
       alignment."

       He is reading it correctly. `align-items:center` centres the items in the
       CONTENT BOX, and the content box had 10px above and 10px + the
       home-indicator inset below — measured on his phone, 10px against 45px. So
       the pills sat hard against the top edge of a band that ran 35px further
       down than they did.

       ⚑ AND THE INSET IS NOT OURS TO CENTRE INTO. That 34px is the space iOS
       reserves for the home indicator; putting a control in it means the OS
       takes the swipe. So the reserve stays exactly where it is and is MIRRORED
       on top instead — the pills end up centred in the visible bar, and nothing
       moves into the indicator's zone. The cost is that the footer grows by the
       inset, which is 0 on any device without one. */
    /* ⚑ THE INSET IS THE PADDING — IT IS NOT ADDED TO IT. Stephen 2026-08-27:
       "could we align to the bottom edge and reduce the top padding... to equal
       the 35px and not have an extra 35px for that uses a lot of space."

       Two versions were wrong in opposite directions. `10px` over
       `10px + inset` put the pills hard against the top of the band (10 against
       45). Mirroring the inset on top centred them and cost 35px of a phone,
       which is what he is objecting to here.

       `max()` is the answer both were missing: the home indicator's 34px is
       space that ALREADY EXISTS below the bar, so the bar's own bottom padding
       should be absorbed by it rather than stacked on top of it. Bottom space is
       34px on a device with an indicator and 10px on one without — never 44 —
       and the bar keeps its bottom edge on the screen's. */
    padding:10px 16px;
    padding-bottom:max(10px, env(safe-area-inset-bottom,0px))}
  /* ⚑ THE DEMO'S FORMAT, NOT A TAB BAR. Stephen 2026-08-25: "I would like the
     new footer menu be formatted just like the demo (screenshot)" — whose row
     reads `Vera | Chat | Budget | Vendor+ | Contracts+`: plain labels, hairline
     pipes between them, the current one simply bold. No tiles, no rules, no
     indicator bar.

     ⚑ THIS REPLACES "SQUARED TILES", WHICH WAS ALSO HIS. On 2026-08-24 he asked
     for "more squared tiles" like Clear; the demo he has been living in does it
     with type alone and he prefers that. Both instructions are his and the
     later one wins — recorded so the older note in the git history does not
     read as a rule being broken.

     ⚑ THE TAP TARGET DOES NOT SHRINK WITH THE TYPE. The label is small; the
     button still stands 48px, because a thumb aims at the control and not at
     the word. */
  .vx-botnav-tile{
    border:0;background:none;cursor:pointer;
    min-height:48px;padding:10px 2px;
    display:flex;align-items:center;justify-content:center;
    position:relative;
    font-family:var(--ff-b,'DM Sans',sans-serif)}
  /* The pipe belongs BETWEEN labels, so every tile but the first draws one on
     its leading edge. Centred on the gap rather than sitting against a word. */
  .vx-botnav-tile + .vx-botnav-tile::before{
    content:'';position:absolute;left:0;top:50%;
    width:1px;height:12px;margin-top:-6px;
    background:var(--line,rgba(35,38,31,.22))}
  .vx-botnav-t{
    font-size:.78rem;font-weight:400;letter-spacing:.005em;
    color:var(--text-muted,#88928d);white-space:nowrap}
  /* Bold and dark is the whole selected state — that is what the demo does. */
  .vx-botnav-tile.is-on .vx-botnav-t{color:var(--green,#2C4A3E);font-weight:600}
  .vx-botnav-tile:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:-2px}
  /* The sheet must be able to scroll clear of the bar, or its last card is
     permanently under it. */
  #vdx-interview-root{padding-bottom:76px}
  /* ⚑ AND THE TOP STRIP STANDS DOWN. Two navigations for the same four
     destinations is the couple deciding which one is the real one. */
  .vx-botnav ~ .phase-nav,
  .phase-nav:has(~ .vx-botnav){display:none}

  /* ══ THE GUIDE CHROME STANDS DOWN ON A PHONE ══
     Stephen 2026-08-25: "On mobile, I want to hide all of the content in
     screenshot #1" — the Back link, the Vendor+ eyebrow, the Transportation
     title, the blurb, "26 QUESTIONS / 5 VENDOR SLOTS", and the totals bar.

     ⚑ READ OFF THE LIVE DOM, NOT GUESSED. `.vdx-embed-head` and
     `.vdx-embed-back-row` are SHARED CHROME across all thirteen guides — a bare
     rule here would strip every one of their headers on a phone, and I would
     not find out from this guide. I searched for this markup twice in the
     interview module and the shell and it is in neither; the classes came from
     inspecting the rendered page.

     ⚑ SCOPED BY THE BOTTOM BAR ITSELF, which is the neatest hook available: it
     is rendered only for transport, so `:has(.vx-botnav)` is true exactly where
     this is wanted and false everywhere else. The two facts stay in step by
     construction — a guide that grows a bottom bar loses its top chrome, and one
     that does not keeps it. No guide key to keep in sync, no second list.

     What is lost is nothing a couple needs mid-plan: the title of the page they
     are looking at, a count of questions they are not answering here, and a
     totals bar whose four figures the hero card below restates. What replaces
     it is the plan, at the top of the screen, where the deck can be reached
     without scrolling. */
  /* ⚑ THE BACK PILL COMES BACK — Stephen 2026-08-26, testing the standalone
     install against CLEAR: "we will need to re-add the 'Back to all guides'
     pill on the top of the transportation guide for that is the way all guides
     navigate and that is okay for Clear has blank space on their screen and it
     is useful to the calmness of the app."
     A partial reversal of his own 2026-08-25 sweep, and the distinction is
     exact: the title, the blurb, the question count and the totals bar are
     CONTENT a couple does not need mid-plan, and they stay hidden. The back
     pill is NAVIGATION, and it is the gesture every other guide uses — the one
     piece of that header whose absence made this guide behave unlike the
     twelve beside it. The space it costs is the point rather than the price. */
  #vdx-interview-detail:has(.vx-botnav) .vdx-embed-head,
  #vdx-interview-detail:has(.vx-botnav) #vxTpTotalsHost{display:none}
}


/* ⚑ THE CONTROL GROUP IS NOT PART OF THE CARD LOOK, so it lives in its own
   element. `.vx-rs-acts` has to work with VX_PLAN_CARDS off — the grip, the
   triangle, the flag and the caret belong beside a trip's text on the plain
   sheet too, and the reason they wrapped was that they were inside
   `.vx-rs-what`, which is a column. Grouping them is the fix; the card look is
   a separate question. */
.vx-rs-acts{
  flex:0 0 auto;display:flex;align-items:center;gap:2px;
  margin-left:auto;align-self:flex-start}


/* ══ THE TIGHT-TRIP TRIANGLE AND WHAT IT SAYS ══
   Stephen 2026-08-24: "I want to show the triangle and when they click on the
   warning use a callout box to show that they need to be ready 15 mins earlier
   so they can depart on-time."

   ⚑ GOLD, NOT RED, AND THAT IS THE CHARTER. "Reduce stress, never alarm" —
   there is no overdue, no at-risk, no red anywhere in this product. A time the
   day cannot honour is a decision waiting, which is what the couple's own gold
   is for everywhere else.

   ⚑ AND IT IS A BUTTON. The flag beside it is a <span> with a `title=`, which
   an iPhone never shows — a tooltip is a desktop affordance and most of the
   traffic is a phone. */
.vx-plan-cards .vx-rs-tight,
.vx-rs-tight{
  flex:0 0 auto;border:0;background:none;cursor:pointer;
  padding:2px 4px;margin:0 0 0 2px;line-height:1;
  font-size:.86rem;color:var(--gold-deep,#A07840)}
.vx-rs-tight:hover{color:var(--green,#2C4A3E)}
.vx-rs-tight:focus-visible{outline:2px solid var(--gold,#C8A96E);outline-offset:2px;border-radius:4px}
.vx-rs-tight[aria-expanded="true"]{color:var(--green,#2C4A3E)}
.vx-rs-tightnote{
  margin:0;padding:11px 14px 12px;
  background:rgba(200,169,110,.10);
  border-left:3px solid var(--gold,#C8A96E)}
/* Inside a card the note sits between the face and the stop list, so it takes
   no radius of its own — rounding it would read as a third card. */
.vx-plan-cards .vx-rs-tightnote{
  border-left:0;border-top:1px solid rgba(200,169,110,.34);
  margin:0;padding:11px 14px 12px}
.vx-rs-tightlede{
  margin:0 0 6px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.82rem;line-height:1.45;color:var(--text,#2A2E2C)}
.vx-rs-tightlede b{color:var(--green,#2C4A3E);font-weight:600}
.vx-rs-tightwhy{
  margin:0 0 5px;font-family:var(--ff-b,'DM Sans',sans-serif);
  font-size:.74rem;line-height:1.5;color:var(--text-mid,#5b625a)}
.vx-rs-tightwhy:last-child{margin-bottom:0}

/* ══ THE TRIP'S OWN GRIP ══
   Stephen 2026-08-24: "I want to re-order trips within a day if ordering
   changes." The storage has existed for a while — `__order[day]` is written and
   the endpoint ranks each band by it — so this is the handle that was missing.

   ⚑ `touch-action:none` IS LOAD-BEARING, and the note on the stop grip says
   why: this row sits inside a horizontally-scrolling deck inside a vertically
   scrolling page. Without it the browser claims the gesture before the first
   pointermove arrives and the row never moves — on a phone, which is most of
   the traffic. */
.vx-rs-tripgrip{
  flex:0 0 auto;border:0;background:none;cursor:grab;
  padding:6px 2px 6px 8px;margin:0;line-height:1;
  font-size:.9rem;color:var(--text-muted,#88928d);opacity:.55;
  touch-action:none;-webkit-user-select:none;user-select:none}
.vx-rs-tripgrip:hover{opacity:1;color:var(--green,#2C4A3E)}
.vx-rs-tripgrip:active{cursor:grabbing}
.vx-rs-tripgrip:focus-visible{
  outline:2px solid var(--gold,#C8A96E);outline-offset:2px;border-radius:4px;opacity:1}
/* The card lifts while it is being placed, so it reads as picked up rather than
   as the list glitching. */
.vx-plan-cards .vx-rs-row.is-dragging{
  box-shadow:0 8px 26px rgba(35,38,31,.18);
  border-color:var(--gold,#C8A96E);opacity:.97}


/* ⛑ HEADER E — one header on every page — 2026-09-15. Stephen picked "E" in the Simulator: solid
   cream, the wordmark at 1.4rem, "Log in" as text and a single green pill (Early Access, or the page's own
   primary action), then the menu or avatar. Scoped to the header so it wins over the page's older header
   rules; scripts/header-e-validate.js holds every page to it. */
body > header{background:var(--cream,#FAF7F2);border-bottom:1px solid rgba(200,169,110,.28)}
header .logo{font-family:var(--ff-d,'Cormorant Garamond','Cormorant Fallback',Georgia,serif);font-size:1.4rem;font-weight:500;letter-spacing:.04em;color:var(--green,#2C4A3E);text-decoration:none;font-style:normal}
header .logo em{font-style:italic;color:var(--gold,#C8A96E)}
header .header-pill{appearance:none;-webkit-appearance:none;background:none;border:0;border-radius:0;box-shadow:none;padding:10px 4px;min-height:0;font-family:var(--ff-b,'DM Sans','DM Sans Fallback',system-ui,sans-serif);font-size:.86rem;font-weight:500;letter-spacing:0;text-transform:none;color:var(--green,#2C4A3E);text-decoration:none;white-space:nowrap;cursor:pointer;transform:none}
header .header-pill:hover{color:var(--gold-deep,#A07840);background:none;border:0;transform:none}
header #vxDemoSavePill, header .header-pill.header-auth-btn.is-signed-in{appearance:none;-webkit-appearance:none;align-items:center;height:38px;min-height:0;padding:0 18px;border:0;border-radius:999px;box-shadow:none;background:var(--green,#2C4A3E);color:var(--cream,#FAF7F2);font-family:var(--ff-b,'DM Sans','DM Sans Fallback',system-ui,sans-serif);font-size:.84rem;font-weight:500;letter-spacing:0;text-transform:none;text-decoration:none;white-space:nowrap;cursor:pointer;transform:none}
header #vxDemoSavePill:hover,header .header-pill.header-auth-btn.is-signed-in:hover{background:var(--green-mid,#3D6355);color:var(--cream,#FAF7F2);transform:none}


  #vxNoDateNudge{margin:2px 0 16px;padding:16px 18px;border:1px solid rgba(200,169,110,.38);border-radius:14px;background:var(--cream-warm,#F0EBE1)}
  #vxNoDateNudge .vxb-nodate-eyebrow{font-family:var(--ff-m,'DM Mono',monospace);font-size:var(--fs-eyebrow,.62rem);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,#A07840);font-weight:500;margin:0 0 6px}
  #vxNoDateNudge .vxb-nodate-copy{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.9rem;line-height:1.5;color:var(--ink,#2C2C2C);margin:0 0 12px}
  #vxNoDateNudge .vxb-nodate-cta{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:.8rem;font-weight:500;color:#fff;background:var(--gold-deep,#A07840);border:none;border-radius:100px;padding:9px 16px;cursor:pointer}
  #vxNoDateNudge .vxb-nodate-cta:active{opacity:.85}
  #section-budget .vxb-band-head{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.16em;text-transform:uppercase;color:var(--text-muted,#8a8478);font-weight:500;padding:16px 2px 8px;line-height:1.4}
  #section-budget .vxb-band-head.is-booked{color:var(--green-mid,#3a6b59)}
  #section-budget .vxb-band-head.is-now{color:var(--gold-deep,#A07840)}
  #section-budget .vxb-section.vxb-band-dim{opacity:.55}


.file-actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap;justify-content:flex-end}
.btn-redact{display:inline-flex;align-items:center;gap:7px;font-family:var(--ff-b);font-size:.82rem;font-weight:500;letter-spacing:.02em;color:var(--green);background:var(--white);border:1.5px solid var(--border-g);padding:9px 18px;border-radius:40px;cursor:pointer;transition:all .25s ease;white-space:nowrap}
.btn-redact:hover{border-color:var(--gold);background:rgba(200,169,110,.08);transform:translateY(-1px)}
.btn-redact[hidden]{display:none}
.vx-redact-host{position:fixed;inset:0;z-index:10050;background:rgba(28,28,28,.74);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;padding:18px;font-family:var(--ff-b)}
.vx-redact-host[hidden]{display:none}
.vx-redact-panel{background:var(--cream);border:1px solid var(--border-g);border-radius:var(--radius-lg);box-shadow:0 18px 60px rgba(28,28,28,.34);width:min(960px,96vw);max-height:94vh;display:flex;flex-direction:column;overflow:hidden}
.vx-redact-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:20px 24px 6px}
.vx-redact-title{font-family:var(--ff-d);font-size:1.45rem;font-style:italic;color:var(--green)}
.vx-redact-page{font-family:var(--ff-m,'DM Mono',monospace);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted,#88928d);white-space:nowrap}
.vx-redact-intro{padding:0 24px;font-size:.82rem;line-height:1.55;color:var(--ink-muted);margin:0 0 12px}
.vx-redact-stage{flex:1;min-height:0;overflow:auto;display:flex;align-items:center;justify-content:center;background:rgba(44,74,62,.06);margin:0 24px;border-radius:var(--radius);padding:14px}
.vx-redact-canvas{display:block;max-width:100%;touch-action:none;cursor:crosshair;border-radius:4px;box-shadow:0 2px 12px rgba(28,28,28,.18);background:#fff}
.vx-redact-tools{display:flex;align-items:center;gap:10px;padding:12px 24px 4px}
.vx-redact-tool{font-family:var(--ff-b);font-size:.78rem;font-weight:500;color:var(--green);background:var(--white);border:1px solid var(--border-g);padding:7px 14px;border-radius:30px;cursor:pointer;transition:all .2s ease}
.vx-redact-tool:hover:not(:disabled){border-color:var(--gold);background:rgba(200,169,110,.08)}
.vx-redact-tool:disabled{opacity:.4;cursor:not-allowed}
.vx-redact-count{font-size:.74rem;color:var(--text-muted,#88928d);margin-left:auto}
.vx-redact-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 24px 20px}
.vx-redact-skip{font-family:var(--ff-b);font-size:.82rem;color:var(--ink-muted);background:none;border:none;cursor:pointer;padding:8px 6px;text-decoration:underline;text-underline-offset:3px}
.vx-redact-skip:hover{color:var(--ink)}
.vx-redact-next{font-family:var(--ff-b);font-size:.85rem;font-weight:500;letter-spacing:.02em;color:var(--cream);background:var(--green);border:none;padding:11px 26px;border-radius:40px;cursor:pointer;transition:all .25s ease;white-space:nowrap;box-shadow:0 4px 20px rgba(44,74,62,.2)}
.vx-redact-next:hover:not(:disabled){background:var(--green-mid);transform:translateY(-2px)}
.vx-redact-next:disabled{opacity:.55;cursor:wait}
@media (max-width:520px){
 .vx-redact-title{font-size:1.25rem}
 .vx-redact-stage{margin:0 14px;padding:10px}
 .vx-redact-head,.vx-redact-intro,.vx-redact-tools,.vx-redact-foot{padding-left:16px;padding-right:16px}
 .vx-redact-next{flex:1}
}


.plan-clp { background:var(--white,#FEFCF8); border:1px solid var(--border-g,rgba(44,74,62,.12)); border-radius:18px; margin:0 0 28px; overflow:hidden; box-shadow:0 2px 12px rgba(28,28,28,.05); }
.plan-clp-tabs { display:flex; gap:0; border-bottom:1px solid rgba(44,74,62,.10); background:rgba(232,237,229,.4); }
.plan-clp-tab { flex:1; padding:14px 16px; font-family:var(--ff-m,'DM Mono',monospace); font-size:11px; letter-spacing:.18em; text-transform:uppercase; color:#7A8076; background:transparent; border:none; cursor:pointer; transition:.2s; border-bottom:2px solid transparent; }
.plan-clp-tab:hover { color:#2C4A3E; }
.plan-clp-tab.active { color:#2C4A3E; background:var(--white,#FEFCF8); border-bottom-color:#C8A96E; font-weight:500; }
.plan-clp-tab .clp-count { display:inline-block; min-width:18px; padding:1px 6px; margin-left:6px; background:#2C4A3E; color:#fff; border-radius:10px; font-size:9px; letter-spacing:.06em; }
.plan-clp-body { padding:24px 28px; min-height:200px; }
.plan-clp-empty { text-align:center; padding:48px 20px; color:#7A8076; font-style:italic; }
.plan-clp-empty button { display:inline-block; margin-top:14px; padding:10px 22px; background:#2C4A3E; color:#fff; border:none; border-radius:999px; font-family:var(--ff-b,sans-serif); font-size:.92rem; font-weight:500; cursor:pointer; letter-spacing:.02em; }
.plan-clp-empty button:hover { background:#1F3A30; }

/* Checklist filters */
.clp-filter-row { display:flex; gap:8px; margin-bottom:18px; flex-wrap:wrap; align-items:center; padding-bottom:14px; border-bottom:1px solid rgba(44,74,62,.08); }
.clp-filter-label { font-family:var(--ff-m,'DM Mono',monospace); font-size:10px; letter-spacing:.15em; text-transform:uppercase; color:#7A8076; margin-right:4px; }
.clp-filter-btn { padding:5px 13px; font-family:var(--ff-b,sans-serif); font-size:11.5px; border:1px solid rgba(44,74,62,.18); border-radius:999px; background:var(--white,#FEFCF8); color:#4A4A4A; cursor:pointer; transition:.2s; }
.clp-filter-btn:hover { border-color:#2C4A3E; }
.clp-filter-btn.active { background:#2C4A3E; color:#fff; border-color:#2C4A3E; }

/* Checklist list */
.clp-cat-group { margin-bottom:24px; }
.clp-cat-header { display:flex; justify-content:space-between; align-items:center; padding:10px 4px; border-bottom:1px solid rgba(44,74,62,.10); margin-bottom:8px; cursor:pointer; user-select:none; transition:background .15s; border-radius:6px; }
.clp-cat-header:hover { background:rgba(232,237,229,.4); }
.clp-cat-name { font-family:var(--ff-d,Cormorant Garamond,serif); font-size:1.15rem; font-weight:500; color:#2C4A3E; display:flex; align-items:center; gap:8px; }
.clp-cat-caret { display:inline-block; width:0; height:0; border-left:5px solid transparent; border-right:5px solid transparent; border-top:6px solid #7A8076; transition:transform .2s; flex-shrink:0; }
.clp-cat-group.is-expanded .clp-cat-caret { transform:rotate(-180deg); }
.clp-cat-progress { font-family:var(--ff-m,monospace); font-size:10px; letter-spacing:.1em; color:#7A8076; display:flex; align-items:center; gap:10px; }
.clp-cat-progress .clp-cat-open-pill { background:#2C4A3E; color:#fff; padding:2px 8px; border-radius:10px; font-size:9px; letter-spacing:.06em; }
.clp-cat-progress .clp-cat-open-pill.is-zero { background:#E8EDE5; color:#5A6B50; }
.clp-cat-tasks { display:none; padding-top:4px; }
.clp-cat-group.is-expanded .clp-cat-tasks { display:block; }
.clp-cat-expand-all { background:transparent; border:1px solid rgba(44,74,62,.18); border-radius:999px; padding:4px 12px; font-family:var(--ff-b,sans-serif); font-size:11px; color:#4A4A4A; cursor:pointer; margin-left:auto; }
.clp-cat-expand-all:hover { border-color:#2C4A3E; color:#2C4A3E; }
.clp-task { display:flex; align-items:flex-start; gap:10px; padding:8px 0; border-bottom:1px dashed rgba(44,74,62,.06); cursor:pointer; transition:.15s; }
.clp-task:last-child { border-bottom:none; }
.clp-task:hover { background:rgba(232,237,229,.3); padding-left:6px; }
.clp-task-checkbox { width:18px; height:18px; border:1.5px solid #C8A96E; border-radius:5px; flex-shrink:0; margin-top:1px; display:flex; align-items:center; justify-content:center; background:var(--white); transition:.2s; }
.clp-task.is-complete .clp-task-checkbox { background:#7A8B6F; border-color:#7A8B6F; }
.clp-task.is-complete .clp-task-checkbox::after { content:'✓'; color:#fff; font-size:12px; font-weight:bold; }
.clp-task-body { flex:1; min-width:0; }
.clp-task-name { font-size:14px; line-height:1.4; color:#1c1c1c; }
.clp-task.is-complete .clp-task-name { color:#9A9A9A; text-decoration:line-through; }
.clp-task-meta { display:flex; gap:10px; margin-top:3px; font-size:11px; color:#7A8076; }
.clp-task-due { font-family:var(--ff-m,monospace); letter-spacing:.04em; }
.clp-task-due.is-overdue { color:var(--amber-risk,#C97B3A); font-weight:500; }
.clp-task-important { color:#C8923A; font-weight:500; }
.clp-task-linked { font-style:italic; }

/* Ledger */
.clp-ledger-summary { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:20px; padding:18px; background:rgba(232,237,229,.4); border-radius:12px; }
.clp-ledger-stat { text-align:center; }
.clp-ledger-stat-val { font-family:var(--ff-d,Cormorant Garamond,serif); font-size:1.6rem; font-weight:500; color:#2C4A3E; line-height:1; }
.clp-ledger-stat-lbl { font-family:var(--ff-m,monospace); font-size:9px; letter-spacing:.12em; text-transform:uppercase; color:#7A8076; margin-top:4px; }
.clp-ledger-table { width:100%; border-collapse:collapse; font-size:13px; }
.clp-ledger-table thead th { padding:8px 6px; font-family:var(--ff-m,monospace); font-size:9.5px; letter-spacing:.12em; text-transform:uppercase; color:#7A8076; border-bottom:1.5px solid rgba(44,74,62,.18); text-align:left; }
.clp-ledger-table thead th.num { text-align:right; }
.clp-ledger-table tbody td { padding:10px 6px; border-bottom:1px solid rgba(44,74,62,.06); }
.clp-ledger-table tbody td.num { text-align:right; font-family:var(--ff-m,monospace); }
.clp-ledger-table tbody tr:hover { background:rgba(232,237,229,.3); }
.clp-status-chip { display:inline-block; padding:2px 9px; border-radius:10px; font-size:10px; letter-spacing:.08em; text-transform:uppercase; font-weight:500; }
.clp-status-chip.scheduled { background:#E8EDE5; color:#5A6B50; }
.clp-status-chip.pending { background:#FFF8EC; color:#B8923E; }
.clp-status-chip.complete { background:#EDF5EA; color:#6B8F5E; }
.clp-status-chip.late { background:#FCEAEA; color:#B54A4A; }
.clp-ledger-add { margin-top:18px; padding-top:18px; border-top:1px solid rgba(44,74,62,.10); }
.clp-ledger-add-toggle { background:none; border:1px dashed rgba(44,74,62,.3); color:#2C4A3E; padding:8px 18px; border-radius:8px; cursor:pointer; font-family:var(--ff-b,sans-serif); font-size:12.5px; }
.clp-ledger-add-toggle:hover { background:rgba(232,237,229,.4); }

/* Calendar */
.clp-cal-card { padding:24px; background:linear-gradient(135deg, rgba(200,169,110,.10) 0%, rgba(122,139,111,.08) 100%); border:1px solid rgba(200,169,110,.30); border-radius:14px; }
.clp-cal-h { font-family:var(--ff-d,Cormorant Garamond,serif); font-size:1.3rem; font-weight:500; color:#2C4A3E; margin-bottom:8px; }
.clp-cal-sub { font-size:13.5px; line-height:1.55; color:#4A4A4A; margin-bottom:16px; max-width:560px; }
.clp-cal-actions { display:flex; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
.clp-cal-btn { display:inline-flex; align-items:center; gap:6px; padding:10px 20px; background:#2C4A3E; color:#fff; border:none; border-radius:999px; font-family:var(--ff-b,sans-serif); font-size:.92rem; font-weight:500; cursor:pointer; text-decoration:none; }
.clp-cal-btn:hover { background:#1F3A30; }
.clp-cal-btn.secondary { background:transparent; color:#2C4A3E; border:1px solid #2C4A3E; }
.clp-cal-btn.secondary:hover { background:rgba(44,74,62,.06); }
.clp-cal-url { display:block; margin-top:10px; padding:10px 14px; background:rgba(255,255,255,.7); border:1px solid rgba(44,74,62,.12); border-radius:8px; font-family:var(--ff-m,monospace); font-size:11.5px; color:#4A4A4A; word-break:break-all; cursor:text; user-select:all; }
.clp-cal-tip { margin-top:14px; padding:12px 16px; background:rgba(255,255,255,.6); border-left:3px solid #C8A96E; border-radius:0 8px 8px 0; font-size:12.5px; color:#4A4A4A; line-height:1.55; }
.clp-cal-tip strong { color:#2C4A3E; }


/* Phase C seating chart */
.clp-seat-table { background:#fff; border:2px solid rgba(44,74,62,.20); border-radius:14px; padding:12px 14px; cursor:pointer; transition:.18s; position:relative; }
.clp-seat-table:hover { border-color:#C8A96E; transform:translateY(-2px); box-shadow:0 6px 18px rgba(28,28,28,.06); }
.clp-seat-table.is-expanded { grid-column:span 2; border-color:#2C4A3E; }
.clp-seat-table.is-head { background:rgba(200,169,110,.10); border-color:#C8A96E; }
.clp-seat-table.is-over { border-color:#9B4040; background:rgba(155,64,64,.06); }
.clp-seat-table.is-ok { border-color:#7A8B6F; }
.clp-seat-table.drop-target { border-color:#2C4A3E; background:rgba(122,139,111,.15); border-style:dashed; }
.clp-seat-head-row { display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px; }
.clp-seat-name { font-family:var(--ff-d,Cormorant Garamond,serif); font-size:1.1rem; color:#2C4A3E; font-weight:500; }
.clp-seat-cap { font-family:var(--ff-m,monospace); font-size:10.5px; letter-spacing:.06em; color:#7A8076; }
.clp-seat-cap.is-over { color:#9B4040; font-weight:600; }
.clp-seat-cap.is-ok { color:#5A7B4F; font-weight:600; }
.clp-seat-bar { height:5px; background:rgba(44,74,62,.10); border-radius:3px; overflow:hidden; margin:4px 0 8px; }
.clp-seat-bar-fill { height:100%; background:#7A8B6F; border-radius:3px; transition:.4s; }
.clp-seat-bar-fill.is-over { background:#9B4040; }
.clp-seat-bar-fill.is-empty { background:rgba(44,74,62,.15); }
.clp-seat-guests { display:none; padding-top:8px; border-top:1px dashed rgba(44,74,62,.10); margin-top:6px; }
.clp-seat-table.is-expanded .clp-seat-guests { display:block; }
.clp-seat-guest { display:flex; justify-content:space-between; align-items:center; padding:4px 0; font-size:12.5px; color:#1c1c1c; }
.clp-seat-guest .gg-x { cursor:pointer; color:#9B4040; opacity:.5; font-size:14px; padding:0 4px; }
.clp-seat-guest .gg-x:hover { opacity:1; }
.clp-seat-actions { display:none; margin-top:8px; padding-top:8px; border-top:1px dashed rgba(44,74,62,.10); gap:6px; flex-wrap:wrap; }
.clp-seat-table.is-expanded .clp-seat-actions { display:flex; }
.clp-seat-actions button { padding:4px 10px; font-size:10.5px; border:1px solid rgba(44,74,62,.18); border-radius:6px; background:#fff; cursor:pointer; font-family:var(--ff-b,sans-serif); }
.clp-seat-actions button:hover { border-color:#2C4A3E; }
.clp-seat-actions button.danger { border-color:rgba(155,64,64,.30); color:#9B4040; }
.clp-orph-pill { display:flex; justify-content:space-between; align-items:center; padding:7px 10px; background:#fff; border:1px solid rgba(44,74,62,.10); border-radius:8px; cursor:grab; font-size:12.5px; transition:.12s; }
.clp-orph-pill:hover { border-color:#C8A96E; background:rgba(200,169,110,.06); }
.clp-orph-pill.is-selected { border-color:#2C4A3E; background:rgba(122,139,111,.10); }
.clp-orph-pill:active { cursor:grabbing; }
.clp-orph-pill .gp-meta { font-size:10.5px; color:#7A8076; }
@media (max-width: 900px) {
  #clpSeatingMain { grid-template-columns:1fr !important; }
  #clpSeatingMain aside { position:static !important; max-height:300px; }
}


.clp-lbl { display:block; font-family:var(--ff-m,'DM Mono',monospace); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:#7A8076; margin-bottom:6px; font-weight:500; }
.clp-input { width:100%; padding:8px 11px; border:1px solid rgba(44,74,62,.18); border-radius:7px; font-family:var(--ff-b,sans-serif); font-size:13.5px; color:#1c1c1c; background:#fff; outline:none; transition:.15s; }
.clp-input:focus { border-color:#7A8B6F; box-shadow:0 0 0 3px rgba(122,139,111,.10); }
.clp-mini-btn { padding:7px 14px; font-family:var(--ff-b,sans-serif); font-size:12px; border:1px solid rgba(44,74,62,.20); border-radius:7px; background:#fff; color:#4A4A4A; cursor:pointer; transition:.15s; }
.clp-mini-btn:hover { border-color:#2C4A3E; color:#2C4A3E; }
.clp-mini-btn.primary { background:#2C4A3E; color:#fff; border-color:#2C4A3E; }
.clp-mini-btn.primary:hover { background:#1F3A30; }
.clp-guest-row { display:grid; grid-template-columns:24px 2fr 1.5fr 1fr 90px 90px 80px; gap:10px; align-items:center; padding:9px 6px; border-bottom:1px solid rgba(44,74,62,.06); font-size:13px; }
.clp-guest-row:hover { background:rgba(232,237,229,.30); }
.clp-guest-row .gr-status { display:inline-block; padding:2px 8px; border-radius:10px; font-size:10px; letter-spacing:.06em; text-transform:uppercase; font-weight:500; }
.clp-guest-row .gr-status.attending { background:#EDF5EA; color:#5A7B4F; }
.clp-guest-row .gr-status.declined { background:#FCEAEA; color:#9B4040; }
.clp-guest-row .gr-status.maybe { background:#FFF8EC; color:#A07840; }
.clp-guest-row .gr-status.pending { background:#F0EFED; color:#7A8076; }
.clp-guest-row .gr-code { font-family:var(--ff-m,monospace); font-size:11px; letter-spacing:.05em; color:#7A8076; padding:2px 8px; background:rgba(232,237,229,.5); border-radius:5px; }
.clp-guest-row .gr-name { font-weight:500; color:#1c1c1c; }
.clp-guest-row .gr-household { color:#7A8076; font-size:12px; }
.clp-guest-row .gr-party { font-size:11px; color:#7A8076; text-transform:uppercase; letter-spacing:.06em; }
.clp-guest-row .gr-actions { display:flex; gap:4px; justify-content:flex-end; }
.clp-guest-edit { padding:14px 16px; background:rgba(232,237,229,.30); border:1px solid rgba(44,74,62,.10); border-radius:10px; margin:6px 0 14px; }
.clp-edit-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr)); gap:8px; }
.clp-edit-grid .clp-input { font-size:13px; padding:7px 10px; }
@media (max-width: 700px) { .clp-edit-grid { grid-template-columns:1fr; } }
.clp-guest-row .gr-icon-btn { background:none; border:none; cursor:pointer; padding:3px 6px; color:#7A8076; font-size:12px; border-radius:4px; }
.clp-guest-row .gr-icon-btn:hover { background:rgba(44,74,62,.08); color:#2C4A3E; }
.clp-registry-row { display:flex; gap:8px; align-items:center; }
.clp-registry-row input { flex:1; }
.clp-registry-row button { padding:4px 10px; font-size:11px; border:1px solid rgba(44,74,62,.20); border-radius:6px; background:#fff; cursor:pointer; color:#9B4040; }
.clp-export-opt { display:block; width:100%; padding:10px 14px; text-align:left; background:transparent; border:none; border-bottom:1px solid rgba(44,74,62,.06); cursor:pointer; font-family:var(--ff-b,sans-serif); font-size:13px; transition:.12s; }
.clp-export-opt:last-child { border-bottom:none; }
.clp-export-opt:hover { background:rgba(232,237,229,.40); }
.clp-stationery-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:12px; }
.clp-stationery-card { display:block; padding:18px; background:#fff; border:1px solid rgba(44,74,62,.12); border-radius:12px; text-decoration:none; color:#1c1c1c; transition:.2s; }
.clp-stationery-card:hover { border-color:#C8A96E; transform:translateY(-2px); box-shadow:0 8px 24px rgba(28,28,28,.06); }
.clp-stat-name { font-family:var(--ff-d,Cormorant Garamond,serif); font-size:1.2rem; color:#2C4A3E; margin-bottom:4px; }
.clp-stat-tag { font-family:var(--ff-m,monospace); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:#A07840; margin-bottom:8px; }
.clp-stat-desc { font-size:12.5px; color:#4A4A4A; line-height:1.5; margin-bottom:10px; }
.clp-stat-cta { font-family:var(--ff-b,'DM Sans',sans-serif); font-size:.8rem; letter-spacing:normal; color:#2C4A3E; }
@media (max-width: 700px) {
  .clp-guest-row { grid-template-columns:24px 1fr 80px; }
  .clp-guest-row .gr-household, .clp-guest-row .gr-party, .clp-guest-row .gr-code { display:none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   2026-05-21 — Vera Help slide-out panel (Size M)
   Right-edge persistent tab + slide-out 380px panel for Try-yourself +
   subscriber modes. Hidden when concierge workflow is active. Module is
   /js/vera-help-panel.js; HTML markup lives just before </body>.
   ═══════════════════════════════════════════════════════════════════════ */
.vx-help-tab {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  background: var(--gold-deep,#A07840);
  color: white;
  padding: 14px 9px;
  border: none;
  border-radius: 8px 0 0 8px;
  cursor: pointer;
  z-index: 4500;
  font-family: var(--ff-d, 'Cormorant Garamond', serif);
  font-style: italic;
  font-size: 13px;
  letter-spacing: 0.08em;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  box-shadow: -2px 0 10px rgba(0,0,0,0.10);
  transition: transform 0.32s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.2s;
  user-select: none;
}
.vx-help-tab:hover {
  transform: translateY(-50%) translateX(-3px);
  box-shadow: -3px 0 14px rgba(0,0,0,0.14);
}
.vx-help-tab-spark {
  font-size: 14px;
  font-style: normal;
}
.vx-help-tab-label {
  writing-mode: vertical-rl;
  text-orientation: mixed;
}
.vx-help-tab.is-stowed {
  transform: translateY(-50%) translateX(110%);
  opacity: 0;
  pointer-events: none;
}
.vx-help-tab.vx-help-hidden-by-workflow {
  display: none !important;
}

.vx-help-panel {
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  width: 380px;
  max-width: 92vw;
  background: var(--cream, #faf7f2);
  border-left: 1px solid rgba(0,0,0,0.08);
  box-shadow: -10px 0 30px rgba(0,0,0,0.08);
  z-index: 4600;
  transform: translateX(101%);
  transition: transform 0.34s cubic-bezier(0.22, 0.61, 0.36, 1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.vx-help-panel.is-open {
  transform: translateX(0);
}

.vx-help-panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 24px 24px 16px;
  border-bottom: 1px solid rgba(0,0,0,0.06);
  background: linear-gradient(to bottom, rgba(200,169,110,0.04), transparent);
}
.vx-help-panel-eyebrow {
  font-family: var(--ff-m, 'DM Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-deep,#A07840);
  margin-bottom: 6px;
  font-weight: 500;
}
.vx-help-panel-title {
  font-family: var(--ff-d, 'Cormorant Garamond', serif);
  font-size: 1.5rem;
  color: var(--charcoal, #2A2A2A);
  margin: 0;
  line-height: 1.15;
  font-weight: 500;
}
.vx-help-panel-close {
  background: transparent;
  border: none;
  font-size: 1.7rem;
  color: var(--charcoal-soft, #5A5249);
  cursor: pointer;
  padding: 2px 8px;
  line-height: 1;
  border-radius: 4px;
  margin-top: -2px;
  transition: background 0.15s;
}
.vx-help-panel-close:hover {
  background: rgba(0,0,0,0.04);
}
.vx-help-panel-body {
  padding: 20px 24px 28px;
  overflow-y: auto;
  flex: 1;
}
.vx-help-panel-body p {
  margin: 0 0 14px;
  font-size: 0.93rem;
  line-height: 1.6;
  color: var(--charcoal, #2A2A2A);
}
.vx-help-panel-body p:last-of-type {
  margin-bottom: 0;
}
.vx-help-panel-tip {
  background: rgba(200,169,110,0.10);
  border-left: 3px solid var(--gold-deep,#A07840);
  padding: 12px 16px;
  border-radius: 0 6px 6px 0;
  margin: 16px 0 0;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--charcoal-soft, #5A5249);
}
.vx-help-panel-tip strong {
  color: var(--charcoal, #2A2A2A);
  font-weight: 600;
}
/* 2026-08-04 (Stephen) — "Ask Vera for it": the registry-driven prompt list
   appended to every Help-card surface by js/vera-help-panel.js. The prompts
   are monospaced and quoted so they read as something you TYPE rather than
   marketing copy — focus-group users mirror what they see verbatim, and the
   type should tell them it is literal. Rendered only when the surface has
   live capabilities, so this block can be absent entirely. */
.vx-help-ask { margin: 20px 0 0; padding-top: 16px; border-top: 1px solid rgba(44,74,62,.12); }
.vx-help-ask-head {
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-size: 1.05rem; font-weight: 500; color: var(--green, #2C4A3E); margin: 0 0 3px;
}
.vx-help-ask-sub { margin: 0 0 11px; font-size: .8rem; line-height: 1.5; color: var(--charcoal-soft, #5A5249); }
.vx-help-ask-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.vx-help-ask-row { display: flex; flex-direction: column; gap: 2px; }
.vx-help-ask-prompt {
  font-family: var(--ff-m, 'DM Mono', ui-monospace, monospace);
  font-size: .78rem; line-height: 1.45; color: var(--green, #2C4A3E);
}
.vx-help-ask-prompt::before { content: '“'; }
.vx-help-ask-prompt::after  { content: '”'; }
.vx-help-ask-why { font-size: .76rem; line-height: 1.45; color: var(--text-muted, #88928d); }
/* 2026-05-24 — Inside-Verdeaux link in the account/Wedding Details
   help panel. Editorial register (italic Cormorant), gold underline,
   sits below the tip with a quiet ornament line above so it reads as
   a thoughtful invitation rather than a marketing CTA. */
.vx-help-panel-inside-link {
  display: block;
  margin: 22px 0 0;
  padding-top: 18px;
  border-top: 1px solid rgba(200,169,110,.22);
  font-family: var(--ff-d, 'Cormorant Garamond','Cormorant Fallback',Georgia, serif);
  font-size: 1.02rem;
  font-style: italic;
  color: var(--green, #2C4A3E);
  text-decoration: none;
  border-bottom: 0;
  letter-spacing: .005em;
}
.vx-help-panel-inside-link::after {
  content: '';
  display: block;
  width: fit-content;
  height: 1px;
  background: var(--gold, #C8A96E);
  margin-top: 2px;
  max-width: 100%;
}
.vx-help-panel-inside-link:hover {
  color: #1e3329;
}
.vx-help-panel-list {
  margin: 0 0 14px;
  padding-left: 22px;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--charcoal, #2A2A2A);
}
.vx-help-panel-list li {
  margin-bottom: 4px;
}

/* Mobile — convert side panel to bottom sheet */
@media (max-width: 768px) {
  /* 2026-05-22 v2 — Centering via inset-inline + margin instead of
     transform. Stephen's screenshot showed the v1 (left:50% + translateX)
     rendering off-center on iOS — almost certainly a `right` declaration
     elsewhere in the cascade was beating my reset. Using inset-inline:0
     + margin-inline:auto is rock-solid because it doesn't depend on
     transform and works with whatever else the cascade throws at it. */
  .vx-help-tab {
    top: auto !important;
    /* 2026-07-08 — respect the iPhone home-indicator zone. In the bundled
       app the WebView extends into the bottom safe area, so a bare 24px
       left the pill half off-screen (Stephen's device pass). env() is 0
       on non-notched devices/browsers, so this is a no-op there. */
    bottom: calc(24px + env(safe-area-inset-bottom, 0px)) !important;
    inset-inline: 0;
    left: 0;
    right: 0;
    margin-inline: auto;
    transform: none !important;
    width: max-content;
    max-width: 92vw;
    border-radius: 18px;
    padding: 9px 18px;
    flex-direction: row;
    gap: 6px;
    font-size: 12.5px;
  }
  .vx-help-tab:hover { transform: none !important; }
  .vx-help-tab-label { writing-mode: horizontal-tb; }
  .vx-help-tab.is-stowed { transform: translateY(140%) !important; }
  /* 2026-07-08 (Stephen) — when the in-section back bar is showing, the
     pill docks into that same row (right side, same baseline as "< Home")
     instead of floating above it. Bar padding is 10px + safe-area; 8px
     centers the taller pill against the 31px Home button. */
  #mh-back-bar.is-visible ~ .vx-help-tab {
    inset-inline: auto;
    left: auto;
    right: 12px;
    margin-inline: 0;
    /* Rides with the bar it docks into — see the note on #mh-back-bar. */
    bottom: calc(8px + env(safe-area-inset-bottom, 0px) + var(--vx-envbar-h,0px)) !important;
  }
  .vx-help-panel {
    top: auto;
    bottom: 0;
    right: 0;
    left: 0;
    width: 100%;
    max-width: 100%;
    max-height: 82vh;
    border-radius: 18px 18px 0 0;
    transform: translateY(101%);
    border-left: none;
    border-top: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 -10px 30px rgba(0,0,0,0.10);
    /* Bottom sheet content clears the home indicator (same rationale as
       .vx-help-tab above). */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .vx-help-panel.is-open { transform: translateY(0); }
}
