/* ⛑ THE TRANSPORTATION WIZARD’S STYLESHEET — extracted 2026-09-16.
   Stephen: "Make the full swap so we are not maintaining two environments - the wizard is
   superior." The wizard is becoming the app’s transportation surface, and ~900 lines of its
   styling lived inline in weekend-plan-prototype.html — where the app cannot reach them, so
   mounted inside Verdeaux it would have rendered unstyled.

   ⚑ EXTRACTED AS ONE CONTIGUOUS RANGE, and linked exactly where it used to sit — between the
   page’s own <style> and its header-E block. Document order is therefore unchanged, which is
   the whole reason this is safe: split it in two and rules that used to come after would come
   before, and the cascade would silently shift.

   WHAT STAYED INLINE, deliberately: the metric-matched font fallbacks, html/body, .top, the
   body::before camera strip and the wordmark rules (safe-area-validate and header-e-validate
   contract those TO THE PAGE), plus the header-E block, which must stay last in the head.

   The shared compare block travels here with its BEGIN/END markers intact — planner-compare
   still diffs it byte-identically against the app’s own copy, now reading this file. */
/* The thread: one line near the top saying what is being assembled and what
   it buys her with an operator. Quiet by design — it is orientation, not a
   headline, and it must never compete with the question being asked. */
/* ⛑ AND IT SHARES THE PAGE'S GUTTER — seen on a real iPhone, 2026-09-13.
   .top and main pad 18px; .thread padded nothing, so it ran edge to edge while
   every other line on the screen started 18px in. It looked like a rendering
   fault rather than a sentence. */
.thread{margin:8px 0 0;padding:0 18px;font-size:13px;line-height:1.5;
  color:var(--muted,#5b665f);opacity:.92}
main{flex:1;padding:22px 18px 0;display:flex;flex-direction:column}
.eyebrow{font-family:var(--ff-m);font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--gold-deep);margin:0 0 8px}
.q{font-family:var(--ff-s);font-size:32px;line-height:1.12;margin:0 0 8px;font-weight:600}
.q em{color:var(--gold);font-style:italic}
.sub{font-size:14px;color:var(--charcoal);margin:0 0 18px;line-height:1.55}

/* ⛑ "WHY I ASK" — the reason this pattern is worth more to us than to Sleep
   Number: every answer has a MECHANICAL consequence we can state. Theirs are
   marketing; ours are the arithmetic that produces the estimate. */
.why{display:flex;gap:11px;border-radius:12px;padding:12px 13px;margin:18px 0 0;
  background:#fff;border:1px solid var(--line)}
.why .mk{flex:0 0 24px;height:24px;border-radius:50%;background:var(--gold);color:var(--green);
  display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;
  font-family:var(--ff-s)}
.why b{display:block;font-size:11.5px;margin-bottom:3px}
.why p{margin:0;font-size:12.5px;line-height:1.55;color:var(--charcoal)}


/* ⛑ AND THE SAME AFFORDANCE FOR THE STOPS — Stephen 2026-09-13, with Apple
   Maps open: "we need to nest stops and only show the 'leave by' and 'arrive
   by' and an expand on demand." Maps lists a multi-stop route as three one-line
   rows and a + Add Stop; we were printing five clock fields PER STOP, so a
   three-stop trip asked fifteen questions to answer two. */
button.expand{display:flex;align-items:center;gap:7px;width:100%;margin:12px 0 0;
  padding:9px 0 0;border:0;border-top:1px solid var(--line);background:transparent;
  color:var(--green);font:600 12.5px/1.3 var(--ff-b);cursor:pointer;text-align:left}
button.expand::before{content:'+';font:700 15px/1 var(--ff-s);opacity:.75}
button.expand[aria-expanded="true"]::before{content:'\2212'}
.expandp{margin-top:12px}

label.fl{display:block;font-family:var(--ff-m);font-size:9.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--charcoal);margin:0 0 5px}
input,select,textarea{width:100%;min-height:var(--fieldh);font-family:var(--ff-b);font-size:16px;
  padding:9px 12px;border:1px solid var(--line);border-radius:10px;background:#fff;color:var(--ink)}
textarea{min-height:0;resize:vertical;line-height:1.45}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:10px}

/* ⛑ PASSENGERS IS A TYPED NUMBER, LIKE TRANSFEERO — a band cannot tell 55 from
   100 and an Operator quotes from the manifest. It sits in half a row beside
   the date now, where a −/+ stepper did not fit; the spin buttons go so the
   field reads as a value, not a control. */
#tg{-moz-appearance:textfield}
#tg::-webkit-outer-spin-button,#tg::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* ── ⛑ THE FOUR CLOCKS, TWO BY TWO — Stephen's mock, 2026-08-27 ──────────
   Leave by | Boarding, Arrive by | Drop-off, inside an opened leg. */
.mtimes{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:0 0 10px}
.mtcell{position:relative;display:flex;flex-direction:column;gap:5px;min-width:0}
.mtcell > span{font-family:var(--ff-m);font-size:9px;letter-spacing:.05em;text-transform:uppercase;
  color:var(--muted);white-space:nowrap}
/* green outline = "you can set this" — his rule, on the typed pair only */
.mtcell input{border-color:var(--green);box-shadow:inset 0 0 0 1px var(--green);
  min-height:var(--fieldh)}
/* VALUES, NOT FIELDS — same box so the block reads as one object, grey because
   green is the sheet's mark for "you can set this" */
.mtcell .val{display:flex;align-items:center;min-height:var(--fieldh);padding:0 12px;
  border:1px solid var(--line);border-radius:10px;font-size:15px;color:var(--muted)}
.mtcell .clockclear{position:absolute;right:2px;bottom:0;height:var(--fieldh)}
/* ⛑ THE PROJECTED CLOCK, DRAWN OVER AN EMPTY TIME FIELD. WebKit does not paint a
   placeholder on input[type=time], so on an iPhone the projection was invisible.
   pointer-events:none so the tap still lands on the input; Chrome's own "--:--"
   is hidden while empty so the two do not print on top of each other. */
.clw{position:relative;min-width:0}
.clw .projv{position:absolute;left:13px;top:50%;transform:translateY(-50%);
  pointer-events:none;font-weight:400;font-size:15px;color:var(--muted);white-space:nowrap}
.clw.empty input::-webkit-datetime-edit{color:transparent}
.clw.empty input:focus::-webkit-datetime-edit{color:inherit}
.clw.empty input:focus + .projv{display:none}
/* ⛑ ADDRESS SUGGESTIONS. A tapped suggestion BLURS the input and iOS closes the
   keyboard with it — so the pick itself commits, and nothing waits for Enter. */
.addrwrap{position:relative}
.addrsug{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:20;background:#fff;
  border:1px solid var(--line);border-radius:10px;overflow:hidden;
  box-shadow:0 6px 20px rgba(35,51,44,.12)}
.addropt{padding:11px 12px;font-size:14px;line-height:1.35;cursor:pointer;
  border-bottom:1px solid var(--line)}
.addropt:last-child{border-bottom:0}
.addropt:active,.addropt:hover{background:var(--cream-2)}
/* Removal is offered only once there is something to remove: two stops is a
   trip, one is a place. */
.rmstop{border:0;background:transparent;color:var(--charcoal);font-size:20px;
  line-height:1;cursor:pointer;padding:0 2px;opacity:.5}
.rmstop:hover{opacity:1;color:#8a4b1f}
/* ⛑ WAIT IS NAMED, NOT ABSORBED. A vehicle held at the church through a
   ceremony is billed time the couple is paying for; hiding it inside a drive
   figure is how an estimate stops being checkable. */
.held{margin:0 0 10px;padding:8px 10px;border-radius:8px;background:var(--cream-2);
  font-size:12px;line-height:1.45;color:var(--charcoal)}
.held b{color:var(--ink)}
.cardhd{font-family:var(--ff-m);font-size:9.5px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--gold-deep);margin:0 0 10px}
/* the route reads as a list of places, with a line down the side like a journey */
.routerow{position:relative;padding:0 0 12px 0;margin:0 0 2px}
.routerow:last-child{padding-bottom:0}
.hints{margin:0;padding:0 0 0 18px;font-size:13.5px;line-height:1.65;color:var(--charcoal)}
.hints li{margin-bottom:3px}
.stopacts{display:flex;gap:2px;align-items:center}
/* touch-action:none is what lets a drag start on iOS without the page scrolling
   out from under the finger. */
.grip{border:0;background:transparent;color:var(--charcoal);font-size:17px;line-height:1;
  cursor:grab;padding:0 4px;opacity:.5;touch-action:none}
.grip:hover{opacity:1}
[data-stopcard].is-dragging{opacity:.75;box-shadow:0 8px 22px rgba(35,51,44,.16);
  transform:scale(1.01)}
.rowacts{display:flex;gap:4px;align-items:flex-start;flex:0 0 auto}
.rowacts button{border:1px solid var(--line);background:#fff;border-radius:999px;
  font-family:var(--ff-b);font-size:11.5px;font-weight:600;color:var(--green);
  padding:4px 11px;cursor:pointer}
.rowacts button[data-deltrip]{color:var(--charcoal);padding:4px 9px;font-size:15px;line-height:1}
.rowacts button:hover{border-color:var(--green)}

.card{background:#fff;border:1px solid var(--line);border-radius:14px;padding:14px;margin:0 0 12px}
/* ⛑ THE TRIP SCREEN, TIGHT LIKE TRANSFEERO — 2026-09-14. Stephen: "we need to be
   tighter on the layout (like Transfeero) for our input screen scrolls multiple
   folds". No rail or narrative above it, and less air between the fields. */
body.tripscreen main{padding-top:12px}
body.tripscreen .eyebrow{margin-bottom:8px}
body.tripscreen .card{padding:12px;margin:0 0 10px}
body.tripscreen label.fl{margin-bottom:4px}
body.tripscreen .cardhd{margin-bottom:8px}
.chevg{display:inline-block;transition:transform .15s ease}
@media (prefers-reduced-motion:reduce){.chevg{transition:none}}
/* ⛑ THREE INPUTS, THEN THE ANSWER — 2026-09-14. Stephen: "Pinterest users
   leave after 10 seconds". One line of headline on the first trip, From / To /
   Passengers, and the answer in a green card the moment the three are in. */
.qhero{font-size:26px;margin:0 0 14px}
.mapsgroup > .addstop{display:block;width:100%;text-align:left;border-left:0;border-right:0;
  border-bottom:0;background:transparent;color:var(--green);font:600 14px/1.2 var(--ff-b);
  padding:14px;cursor:pointer}
.sumcard{background:#eef5ec;border:1px solid #cfe3c8;border-radius:14px;padding:14px;margin:0 0 10px}
.sumhd{font:700 17px/1.3 var(--ff-b);color:var(--green)}
.sumrt{font-size:14px;line-height:1.4;color:var(--ink);margin-top:4px}
.summt{font-size:13px;line-height:1.45;color:var(--charcoal);margin-top:2px}
.anymore{font:600 16px/1.3 var(--ff-b);color:var(--ink);margin:14px 0 4px}
.moretoggle{display:flex;justify-content:space-between;align-items:center;gap:10px;width:100%;
  margin:0 0 10px;padding:12px 14px;border:1px solid var(--line);border-radius:14px;background:#fff;
  font:600 14px/1.25 var(--ff-b);color:var(--ink);cursor:pointer;text-align:left}
.moretoggle small{display:block;font-weight:400;font-size:12px;color:var(--muted);margin-top:3px}
.moretoggle .chevg{font-size:24px;line-height:1;color:var(--green)}
.moretoggle[aria-expanded="true"] .chevg{transform:rotate(90deg)}
/* ⛑ WHEN, AND THE PLAN AS AN AGENDA — 2026-09-14. Stephen: "the user is really
   creating a calendar event that has movements for groups". The day and time sit
   under the answer with an Arrive by / Leave at switch, and the plan lists the
   weekend by day, then time, the way a calendar does. */
.whenrow .seg{display:flex;border-top:1px solid var(--line)}
.seg button{flex:1;min-height:44px;border:0;background:transparent;font:600 14px/1 var(--ff-b);
  color:var(--muted);cursor:pointer}
.seg button + button{border-left:1px solid var(--line)}
.seg button[aria-pressed="true"]{color:var(--green);background:#eef5ec}
.clw:not(.empty) .projv{display:none}
.forgot{font-size:12.5px;line-height:1.5;color:var(--muted);margin:2px 0 8px}
.agday{font:600 11px/1 var(--ff-m);letter-spacing:.08em;text-transform:uppercase;
  color:var(--gold-deep);margin:18px 0 8px}
.agcard{padding:2px 14px;margin-bottom:6px}
.agwhen{font-size:14px;font-weight:600;color:var(--green);margin-top:2px}
.editedby{margin:-8px 0 12px}
/* ── ⛑ LEGS, THE AUGUST WAY — 2026-09-14 ─────────────────────────────────
   Stephen: "independent legs, port the app component". One row per leg — its
   name, both clocks with the pipe on one column (ink is hers, grey is ours), a ›
   and a grip. Opened: From, To, the four clocks, Group. */
.leglist{padding:2px 14px}
.legrow{border-top:1px solid var(--line)}
.legrow:first-child{border-top:0}
.legface{display:flex;align-items:center;gap:2px}
.leghead{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:13px 0;border:0;
  background:transparent;text-align:left;cursor:pointer;font-family:var(--ff-b);color:var(--ink)}
/* wraps rather than truncating: with two clocks beside it, "Basilica to Blake's"
   cut to "Basilic…" on a phone, and the place is the thing the row is for */
.legname{flex:1;min-width:0;font-size:15px;font-weight:600;line-height:1.3;overflow-wrap:anywhere}
.legsub{display:block;font-size:12px;font-weight:400;color:var(--muted);margin-top:2px}
.cpair{flex:0 0 auto;display:flex;gap:5px;font-size:13.5px;font-variant-numeric:tabular-nums;color:var(--muted)}
.cpair .typed{color:var(--ink);font-weight:700}
.cpair .pipe{color:var(--line)}
.leghead .chevg{font-size:22px;line-height:1;color:var(--green)}
.leghead[aria-expanded="true"] .chevg{transform:rotate(90deg)}
.leghead[aria-expanded="true"] .legname{color:var(--green)}
.legbody{padding:0 0 12px}
.legbody .card{margin:0 0 10px}
.mlab{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:12px;margin:0}
.mlab > span{font-size:13px;font-weight:600;color:var(--charcoal)}
.legacts{display:flex;justify-content:space-between;gap:10px;margin-top:10px}
.legacts .legrm{color:var(--charcoal)}
.leglist > .addstop{display:block;width:100%;text-align:left;border:0;border-top:1px solid var(--line);
  background:transparent;color:var(--green);font:600 14px/1.2 var(--ff-b);padding:13px 0;cursor:pointer}
/* the trip's shape and how long the vehicle is needed, then "How it runs" */
.legmeta{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:12px 14px;
  border-top:1px solid var(--line);font-size:14px;color:var(--charcoal)}
.legmeta b{color:var(--ink);font-variant-numeric:tabular-nums}
.howrow{display:grid;grid-template-columns:auto 1fr;align-items:center;border-top:1px solid var(--line);padding-left:14px}
.howrow > span{font-size:14px;color:var(--charcoal);white-space:nowrap}
.howrow select{min-width:0;text-align:right;text-align-last:right}
.mapsgroup > .addrrow + .addrrow{border-top:1px solid var(--line)}
.addclock{display:inline-block;margin:0 8px 6px 0;padding:8px 12px;border-radius:999px;
  border:1px solid var(--line);background:#fff;color:var(--green);font:600 13px/1 var(--ff-b);cursor:pointer}
.clockline{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:10px;margin:0 0 8px}
.clocklab{font-size:13px;font-weight:600;color:var(--charcoal)}
.clockclear{border:0;background:transparent;color:var(--charcoal);font-size:20px;line-height:1;cursor:pointer;padding:0 4px}
/* ⛑ AND [hidden] MUST WIN. Seen on an iPhone the day this shipped: .clockline
   (display:grid) and .addclock (display:inline-block) beat the browser's own
   [hidden] rule, so a closed time showed its empty field AND its "+" button at
   once — the same trap that kept the progress ribbon on screen. */
.clockline[hidden],.addclock[hidden],.legbody[hidden],.legsub[hidden],.clockclear[hidden]{display:none}
/* ⛑ APPLE MAPS INPUT — 2026-09-14. Stephen: "removing the field outlines and
   headers on the input fields to look like an Apple Maps input - we do not need
   the extra headings". The card is the one rounded shape; fields inside it are
   borderless rows divided by hairlines, and each says what it is in its own
   placeholder. Scoped to .mapsgroup so the on-demand clocks keep their outlines
   and labels, where four blank time boxes would otherwise mean nothing. */
.mapsgroup{padding:0;overflow:visible}
.mapsgroup input,.mapsgroup select,.mapsgroup textarea{border:0;border-radius:0;
  background:transparent;box-shadow:none;min-height:48px;padding:12px 14px}
.mapsgroup > input,.mapsgroup > .row2,.mapsgroup > textarea,.mapsgroup > .routerow,.mapsgroup > .addstop{
  border-top:1px solid var(--line)}
.mapsgroup > :first-child{border-top:0}
.mapsgroup .row2{gap:0}
.mapsgroup .row2 > div + div{border-left:1px solid var(--line)}
.mapsgroup .routerow{padding:0;margin:0}
.mapsgroup .addrrow{margin:0}
.mapsgroup .addrsug{left:8px;right:8px}
/* a visible focus without an outline: the row fills faintly */
.mapsgroup input:focus,.mapsgroup select:focus,.mapsgroup textarea:focus{
  outline:none;background:var(--cream-2)}
.mapsgroup input:focus-visible,.mapsgroup select:focus-visible,.mapsgroup textarea:focus-visible{
  box-shadow:inset 3px 0 0 var(--green)}
/* reorder and remove at the right end of an address row */
.routerow.hasacts{position:relative}
.routerow.hasacts input{padding-right:70px}
.routerow .stopacts{position:absolute;right:8px;top:0;height:48px;display:flex;align-items:center;gap:2px;z-index:2}
.mapsgroup .clw .projv{left:14px}
.derived{margin:14px 0 0;padding:13px 14px;border-radius:12px;background:#eef5ec;
  border:1px solid #cfe3c8;font-size:13.5px;line-height:1.6}
.derived b{color:var(--green)}
.derived.warn{background:#fdf0e8;border-color:#f0cdb4}
.derived.warn b{color:#8a4b1f}
.note{font-size:11.5px;color:var(--muted);margin:12px 0 0;line-height:1.55}
.pills{display:flex;flex-wrap:wrap;gap:7px}
.pill{font-family:var(--ff-b);font-size:13.5px;padding:9px 15px;border:1px solid var(--line);
  border-radius:999px;background:#fff;color:var(--ink);cursor:pointer}
.pill[aria-pressed=true]{background:var(--green);color:#fff;border-color:var(--green)}
.triprow{display:flex;gap:10px;align-items:flex-start;padding:11px 0;border-top:1px solid var(--line)}
.triprow:first-child{border-top:0}
.triprow .n{flex:0 0 22px;height:22px;border-radius:50%;background:var(--green);color:#fff;
  font-size:11px;display:flex;align-items:center;justify-content:center;font-weight:700}
.triprow .nm{font-size:14px;font-weight:500;line-height:1.35}
.triprow .mt{font-size:11.5px;color:var(--charcoal);line-height:1.5;margin-top:2px}

footer{position:sticky;bottom:0;padding:14px 18px calc(14px + env(safe-area-inset-bottom));
  display:flex;gap:10px;margin-top:auto;
  background:linear-gradient(to top,var(--cream) 74%,rgba(250,247,242,0))}
.back{flex:0 0 46px;height:46px;border-radius:50%;border:1px solid var(--line);background:#fff;
  font-size:19px;color:var(--charcoal);cursor:pointer}
.next{flex:1;height:46px;border-radius:999px;border:0;background:var(--green);color:#fff;
  font-family:var(--ff-b);font-size:15px;font-weight:700;cursor:pointer}
.next[disabled]{background:#d8d4cc;color:#8f8b83;cursor:default}
.alt{flex:1;height:46px;border-radius:999px;background:#fff;color:var(--green);
  border:1px solid var(--green);font-family:var(--ff-b);font-size:15px;font-weight:700;cursor:pointer}
/* + Trip sits between + Stop and View plan; it saves a trip, so it greys out
   exactly when View plan does. */
/* ⚑ 2026-09-17 — EMPHASIS MOVES BETWEEN THE TWO STYLES THAT ALREADY EXIST.
   Stephen asked for a grey button that turns green when there is a reason to
   re-search. Grey was the one thing to avoid: `.next[disabled]` above is
   already grey, so a grey-but-live button would read as broken on exactly the
   screen where we want it pressed. `.next` and `.alt` are the same pill in two
   weights, so the fill just swaps — no third state, no new colour, and the
   disabled grey keeps meaning disabled.
   These mirror `.next` and `.alt` exactly; change one pair, change both. */
.next.is-quiet{background:#fff;color:var(--green);border:1px solid var(--green)}
/* The Interview button. Same pill as .alt — it is a peer of Refresh, not a
   lesser thing — so it takes the emphasis modifiers in exactly the same way. */
/* The Map button — a peer of Interview and Refresh, same pill. */
.map{flex:1;height:46px;border-radius:999px;background:#fff;color:var(--green);
  border:1px solid var(--green);font-family:var(--ff-b);font-size:15px;font-weight:700;cursor:pointer}
/* ⚑ THREE BUTTONS ON A PHONE. At 15px/700 "Interview" and "Refresh" fit a third
   of a 320px screen; the shrink is on the type, not on the tap target, which
   stays 46px tall. */
@media (max-width:400px){
  .map,.journal,#foot .next{font-size:13.5px}
}
/* The map sheet — the stop sheet's own scrim and card, so there is one dialog
   look in the guide rather than two. Only the body differs. */
.vxp-mapsheet{display:flex;flex-direction:column;gap:10px}
.vxp-map-img{display:block;width:100%;height:auto;border-radius:12px;
  border:1px solid rgba(44,74,62,.12)}
/* ⚑ THE SHEET IS A GLANCE, NOT A SCREEN. Capped so the table it opened over is
   still visible behind the scrim — a full-height dialog would be the same
   "everything else is gone" the inline version had, with a scrim on top. */
.vxp-mapsheet{max-height:min(78dvh,620px)}

.journal{flex:1;height:46px;border-radius:999px;background:#fff;color:var(--green);
  border:1px solid var(--green);font-family:var(--ff-b);font-size:15px;font-weight:700;cursor:pointer}
.journal.is-loud{background:var(--green);color:#fff;border:0}
/* The journal is a scroll target now, so it must not draw a browser focus ring
   around the whole block when we send focus there for keyboard users. */
.oplog-wrap:focus{outline:none}
.oplog-wrap:focus-visible{outline:2px solid var(--green);outline-offset:4px}
.alt.is-loud{background:var(--green);color:#fff;border:0}
/* The reason the button is lit, in Vera's voice. Never a warning colour — this
   is an observation with an action, not an alarm. */
.vxp-refresh{margin:0 0 12px}
/* Vera's refresh question. Same card, one step louder, because it is waiting on
   an answer rather than reporting a fact — and still not a warning colour. */
.vxp-ask{display:flex;flex-direction:column;gap:6px}
.vxp-ask b{font-weight:600}
.vxp-ask span{display:block}
/* Wraps on a phone rather than squeezing two pills onto one line: the labels
   are sentences, not verbs, and a clipped choice is a choice nobody makes. */
.vxp-askrow{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.vxp-askrow .next,.vxp-askrow .alt{flex:1 1 200px;height:40px;font-size:14px}

.trip{flex:1;height:46px;border-radius:999px;background:#fff;color:var(--green);
  border:1px solid var(--green);font-family:var(--ff-b);font-size:15px;font-weight:700;cursor:pointer}
.trip[disabled]{color:#8f8b83;border-color:#d8d4cc;cursor:default}
/* ⛑ FOUR LAYOUT BUGS FOUND BY A REAL TESTER — 2026-09-13 ─────────────────
   1. THE OVAL. `.alt` carries flex:1 for the footer, and `main` is a COLUMN
      flex container — so an .alt button placed in the body GREW VERTICALLY to
      fill the screen, and a 999px radius on a 380px-tall box is an oval. A
      button in the flow sizes to its content.
   2. WHITE ON WHITE. `.triprow .nm` set no colour, so on the quiz screens it
      inherited body.quiz's white and disappeared against the white card. `.mt`
      set --charcoal explicitly, which is why only the TIME was visible and the
      appointment looked nameless.
   3. GRID BLOWOUT. Grid and flex items default to min-width:auto, and iOS gives
      input[type=time] a large intrinsic width it will not shrink below — so
      "Leave by" overlapped "Boarding" and the AT field ran off the screen.
      min-width:0 is what lets a track actually constrain its child.
   4. And a native time input must be allowed to shrink to its column. */
/* An inline "Try again" inside a note: a real button, but it reads as part of
   the sentence it ends, because it is the only thing to do about that sentence. */
.linkbtn{background:none;border:0;padding:0;font:inherit;color:var(--green);
  font-weight:700;text-decoration:underline;cursor:pointer}
/* The call script. A question and the reason it matters, so the reason is not
   an afterthought in smaller grey type — it is why she is asking at all. */
.askrow{padding:10px 0;border-top:1px solid rgba(44,74,62,.10)}
.askrow:first-of-type{border-top:0;padding-top:2px}
.askq{font-weight:700;line-height:1.45}
.askw{margin-top:4px;color:#5b665f;font-size:13.5px;line-height:1.5}
.triprow .nm{color:var(--ink)}
.row2 > *{min-width:0}
.clocks > *{min-width:0}
.mtcell input,.mtcell .val,.row2 input,.row2 select{min-width:0;max-width:100%}
/* ⛑ THE ONE CHROMIUM CANNOT SHOW YOU — 2026-09-13. On iOS, input[type=date]
   and input[type=time] are NATIVE controls that size themselves and ignore the
   width they are given, so in a two-column grid the first ran full width and
   the second overlapped it and spilled off-screen. Chromium reported clean
   columns (18–196, 206–384) for the same markup, which is exactly why a layout
   bug on this project has to be seen in WebKit — 85% of visitors are on an
   iPhone and the desktop browser will happily tell you it is fine.
   `appearance:none` is what turns them back into ordinary boxes that obey a
   width; everything else here is the box we then have to draw ourselves. */
input[type=time],input[type=date]{
  -webkit-appearance:none;appearance:none;
  min-width:0;max-width:100%;width:100%;display:block;
  font-family:var(--ff-b);text-align:left;
  /* iOS also shrinks a native date control's own text; 16px is the floor that
     stops the page zooming when it takes focus. */
  font-size:16px;line-height:1.2}
/* the native clear/step affordances go with the appearance */
input[type=time]::-webkit-date-and-time-value,
input[type=date]::-webkit-date-and-time-value{text-align:left;margin:0}
input[type=time]::-webkit-calendar-picker-indicator,
input[type=date]::-webkit-calendar-picker-indicator{margin:0;opacity:.55}
/* ⛑ FOUR ACTIONS ON THE REVIEW SCREEN, so they wrap rather than squeeze. Print
   and Keep are quieter than the two that build the plan — they are what you do
   WITH it, not to it. */
footer{flex-wrap:wrap}
/* ⛑ …AND THE WRAP NEVER HAPPENED — Stephen, on his iPhone 2026-09-15, asking which fix
   "will function as the prototype was — that was clean and simple."
   It was: until bd7fc292 the review footer held exactly TWO actions (+ Add a trip · Find
   operators) on one flex row, and `flex:1` splits a row perfectly when there are two of
   them. That commit added Print and Keep AND this flex-wrap in one change — but `flex:1`
   is `flex:1 1 0%`, so .alt and .next shrink toward nothing instead of filling the row and
   pushing the quieter pair over. Print squeezed onto row one and "+ Add a trip" collapsed
   into three colliding lines.
   Giving them a real BASIS restores the two-row layout the comment above already describes:
   row one is the prototype's row exactly, row two is what you do WITH the plan.
   ⚑ SCOPED BY `:has(.print)`, which is true on the review screen and nowhere else — the
   other nine foot() calls carry at most two actions and must keep sharing one row, and the
   base .alt/.next rule is left alone (a body-placed .alt with flex:1 once grew into an
   oval — see the tester-bug note above). */
/* ⛑ 2026-09-16 — the row-one pair is the two that BUILD the plan, and "+ New plan" replaced the
   operators action there when Keep this plan was removed and Find operators took its place below.
   The basis still has to be big enough that the quieter pair cannot squeeze up beside them. */
footer:has(.print) .alt,
footer:has(.print) .newplan{flex:1 1 38%}
/* Find operators keeps its weight — it is the primary action — but takes row two's metrics so it
   sits level with Print rather than standing 4px taller than it. */
footer:has(.print) .next{flex:1 1 46%;height:42px;font-size:14px}
.newplan{flex:1;height:46px;border-radius:999px;background:#fff;color:var(--green);
  border:1px solid var(--green);font-family:var(--ff-b);font-size:15px;font-weight:700;cursor:pointer}
.print,.save{flex:1 1 46%;height:42px;border-radius:999px;background:transparent;
  color:var(--charcoal);border:1px solid var(--line);font-family:var(--ff-b);
  font-size:14px;font-weight:600;cursor:pointer}
.save{color:var(--green);border-color:var(--green)}

/* ⛑ VERA'S INTERVIEW — Stephen 2026-09-14: "Each answer is shown on the screen so
   a user sees their work but we only show the next question after 'enter' and I
   want this to stay on one mobile screen so it is not overwhelming."
   So the answers are a compact list of one-line chips above ONE question. The
   list scrolls inside itself; the question never leaves the thumb. A chip is a
   button: tapping it re-asks that question. */
body.vera main{padding-top:14px;min-height:0}
.vx{display:flex;flex-direction:column;gap:12px;flex:1;min-height:0}
.vxlog{display:flex;flex-direction:column;gap:6px;max-height:34dvh;overflow-y:auto;
  overscroll-behavior:contain;padding:2px 0}
.vxans{display:flex;align-items:baseline;gap:8px;width:100%;text-align:left;border:0;
  background:var(--cream-2);border-radius:10px;padding:7px 11px;font:inherit;color:var(--ink);cursor:pointer}
/* ⛑ ONE EDGE FOR EVERY ANSWER — Stephen: "I like the data fields left aligned and not staggered
   as field titles change." The label is a fixed column, whatever it says. */
.vxans .k{flex:0 0 84px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--ff-m);font-size:9px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
/* ⛑ ONE LINE EACH — "everything should be one line when not expanded." A long
   place name ends in an ellipsis; tapping the row shows the whole answer. */
.vxans .v{flex:1;min-width:0;font-size:13.5px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vxans:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxtrip{font-family:var(--ff-m);font-size:9px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--gold-deep);margin:6px 0 0}
/* ⛑ A LINE OF ROOM ABOVE HER QUESTION, IN THE ANSWERS' OWN FONT — Stephen: "a line space above
   Vera's question but keep the font the same for the current font is hard to read quickly". */
.vxq{display:flex;gap:10px;align-items:flex-start;margin-top:14px}
.vxav{flex:0 0 30px;height:30px;border-radius:50%;background:var(--green);color:var(--gold);
  display:flex;align-items:center;justify-content:center;font-family:var(--ff-s);font-size:17px;font-style:italic}
.vxsay{flex:1;min-width:0;font-family:var(--ff-b);font-size:18px;line-height:1.35;font-weight:600;margin:4px 0 0;color:var(--ink)}
.vxsay.intro{font-family:var(--ff-b);font-size:15.5px;font-weight:400;line-height:1.55;color:var(--ink)}
.vxin{display:flex;flex-direction:column;gap:8px}
.vxin input[type=text],.vxin input[type=number]{width:100%;height:var(--fieldh);border:1px solid var(--line);
  border-radius:12px;padding:0 13px;font:inherit;font-size:16px;background:#fff;color:var(--ink)}
.vxin input[type=date],.vxin input[type=time]{height:var(--fieldh);border:1px solid var(--line);
  border-radius:12px;padding:0 13px;background:#fff;color:var(--ink)}
/* ⛑ A DATE OR TIME SITS IN THE MIDDLE OF ITS FIELD. Seen in the Simulator: with
   appearance:none, iOS draws the value at the top of the box. The value's own
   line is made the field's height, and the box centres what it holds. */
.vxin input[type=date],.vxin input[type=time]{display:flex;align-items:center;padding-top:0;padding-bottom:0;line-height:normal}
.vxin input[type=date]::-webkit-date-and-time-value,.vxin input[type=time]::-webkit-date-and-time-value{line-height:calc(var(--fieldh) - 2px);min-height:calc(var(--fieldh) - 2px)}
.vxin .row2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.vxin label{font-family:var(--ff-m);font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vxin select{width:100%;height:var(--fieldh);border:1px solid var(--line);border-radius:12px;
  padding:0 10px;font:inherit;font-size:16px;background:#fff;color:var(--ink);min-width:0}
.vxopts{display:flex;flex-wrap:wrap;gap:7px}
.vxopt{font-family:var(--ff-b);font-size:14px;padding:10px 15px;border:1px solid var(--line);
  border-radius:999px;background:#fff;color:var(--ink);cursor:pointer}
.vxopt[aria-pressed=true]{background:var(--green);color:#fff;border-color:var(--green)}
.vxsug{border:1px solid var(--line);border-radius:12px;background:#fff;overflow:hidden}
.vxsug button{display:block;width:100%;text-align:left;border:0;border-top:1px solid var(--line);
  background:#fff;padding:10px 13px;font:inherit;font-size:14px;color:var(--ink);cursor:pointer}
.vxsug button:first-child{border-top:0}
.vxhint{font-size:12px;color:var(--charcoal);margin:0;line-height:1.45}
.vxhint.bad{color:#8a4b1f}
/* ⛑ VERA'S CALENDAR — one screen that stays open: turn the month, tap two days. */
.vxcal{border:1px solid var(--line);border-radius:14px;background:#fff;padding:8px 8px 10px}
.vxcal-head{display:grid;grid-template-columns:44px 1fr 44px;align-items:center;gap:4px;margin-bottom:4px}
.vxcal-nav{height:44px;border:0;background:transparent;border-radius:10px;font-size:24px;line-height:1;color:var(--green);cursor:pointer}
.vxcal-nav[disabled]{opacity:.25;cursor:default}
.vxin .vxcal-head select{height:44px;border:0;background:transparent;text-align:center;text-align-last:center;
  font-family:var(--ff-s);font-size:20px;font-weight:600;color:var(--ink);-webkit-appearance:none;appearance:none;padding:0}
.vxcal-dow,.vxcal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px 0}
.vxcal-dow span{font-family:var(--ff-m);font-size:9px;letter-spacing:.06em;color:var(--muted);text-align:center;padding:4px 0}
.vxcal-grid button{height:42px;border:0;border-radius:10px;background:transparent;font:inherit;font-size:15px;color:var(--ink);
  cursor:pointer;font-variant-numeric:tabular-nums;padding:0}
.vxcal-grid button[disabled]{color:var(--muted);opacity:.45;cursor:default}
.vxcal-grid button.in{background:var(--cream-2);border-radius:0}
.vxcal-grid button.on{background:var(--green);color:#fff}
.vxcal-grid button:focus-visible{outline:2px solid var(--gold);outline-offset:1px}
.vxcal-sum{font-size:13px;color:var(--charcoal);margin:8px 4px 0;min-height:1.45em;line-height:1.45}
.vxbusy{font-size:14px;color:var(--charcoal);line-height:1.5}
/* Here's what we captured: one line per ride, the empty drives left to the
   operator brief. */
.capday{font-family:var(--ff-m);font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--gold-deep);margin:14px 0 4px}
.caprow{display:grid;grid-template-columns:58px 1fr;gap:10px;padding:9px 0;border-top:1px solid var(--line)}
.caprow:first-of-type{border-top:0}
.caprow .tm{font-family:var(--ff-m);font-size:12px;color:var(--charcoal);font-variant-numeric:tabular-nums}
.caprow .rt{font-size:14px;font-weight:500;line-height:1.35;overflow-wrap:anywhere}
.caprow .who{font-size:12px;color:var(--charcoal);margin-top:2px}
@media (prefers-reduced-motion:no-preference){.vxq{animation:vxin .18s ease-out}}
.vxfacts{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.vxfacts .vxans{width:auto}
/* ⛑ THE PLACE NAMES GET THE WIDTH. Seen on the live card: beside a 117px clock
   pair, "The Westin Edina Galleria to Spalon Montage" was squeezed into 46px and
   broke a letter or two per line. On the card the name and its chevron take the
   first line and the clocks take a whole line of their own under it. */
.vxcardlist .leghead{flex-wrap:wrap;row-gap:3px}
.vxcardlist .legname{order:0;flex:1 1 0;min-width:0}
.vxcardlist .leghead .chevg{order:1}
.vxcardlist .cpair{order:2;flex:1 1 100%}
.vxempty .leghead{cursor:default}
.vxempty .legname{font-weight:500;color:var(--muted)}
.vxplaces{display:grid;gap:6px;margin:0 0 10px}
.vxplace{display:grid;grid-template-columns:44px minmax(0,1fr) auto;align-items:center;gap:8px;text-align:left;
  border:1px solid var(--line);border-radius:12px;background:#fff;padding:9px 12px;font:inherit;color:var(--ink);cursor:pointer}
.vxplace span{font-family:var(--ff-m);font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vxplace b{font-weight:500;font-size:14px;overflow-wrap:anywhere}
.vxplace i{font-style:normal;font-size:12.5px;color:var(--green);font-weight:600}
.caphd{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:14px 0 4px}
.caphd .capday{margin:0}
.caphd{align-items:center}
.vxedittrip{flex:0 0 auto;border:1px solid var(--line);border-radius:999px;background:#fff;padding:7px 14px;
  font:inherit;font-size:13px;font-weight:600;color:var(--green);cursor:pointer}
.vxedittrip:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.linkbtn[disabled]{color:var(--muted);text-decoration:none;cursor:default}
/* ⛑ THE INVENTORY UNDER VERA'S WELCOME — 2026-09-16. Her greeting and the plan list were two
   screens; on her own page the cards need the air the old screen's <h1>/<p class="sub"> gave
   them, or they butt straight against her portrait block. */
.vxplans{display:block;margin:22px 0 0}
/* ⛑ THE DELETE CONTROL SITS BESIDE THE CARD, NOT INSIDE IT — a <button> within a <button> is
   invalid and gets re-parsed out. The wrapper positions it over the card's top-right, and the
   card keeps room for it so a long plan title never runs underneath. */
.plancard-wrap{position:relative}
.plancard-wrap .plancard{padding-right:46px}
.plancard-rm{position:absolute;top:9px;right:9px;width:32px;height:32px;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:transparent;color:var(--muted);font-size:19px;line-height:1;cursor:pointer;padding:0}
.plancard-rm:hover{background:var(--cream);color:var(--ink)}
.plancard-rm:focus-visible{outline:2px solid var(--gold);outline-offset:2px;color:var(--ink)}
.plancard{display:block;width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer;min-height:0}
.plancard:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.plancard.on{border-color:var(--green)}
.plancard-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.plancard-top b{font-size:16px;line-height:1.3;color:var(--ink)}
.plancard .pill{flex:none;font-family:var(--ff-m);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--green)}
.plancard-meta{display:block;font-size:13px;color:var(--charcoal);margin-top:4px}
.plancard small{display:block;font-size:12px;color:var(--muted);margin-top:4px}
/* ══ ⛑ THE COMPARE TABLE, IN THE GUIDES' OWN FORMAT — 2026-09-15 ══════════════════════════
   Stephen: "I also want the format of the compare table to match the other guides for brand
   consistency." The block between BEGIN and END is copied VERBATIM from verdeaux-local.html,
   and scripts/planner-compare-validate.js fails if the two differ. The app's own custom
   properties are set on the wrapper so its fallbacks never decide the look. */
.vxp-cmpwrap{--radius-lg:20px;--green-mid:#3D6355;--text-mid:#4A4A4A;--text-muted:#7A7A7A;--ink:#1C1C1C;--sage-dark:#2C4A3E;margin:0 0 12px}
/* BEGIN app compare CSS */
.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);
}
/* END app compare CSS */
/* The planner's own additions, scoped to it: up to five operators, so the grid counts the ones it has. */
.vxp-cmp .vx-cmp-head,.vxp-cmp .vx-cmp-row{grid-template-columns:240px repeat(var(--cmp-n,5),1fr)}
@media (max-width:1100px){.vxp-cmp .vx-cmp-head,.vxp-cmp .vx-cmp-row{grid-template-columns:180px repeat(var(--cmp-n,5),1fr)}}
@media (max-width:780px){.vxp-cmp .vx-cmp-head,.vxp-cmp .vx-cmp-row{grid-template-columns:116px repeat(var(--cmp-n,5),1fr);min-width:calc(116px + var(--cmp-n,5) * 160px)}}
.vxp-cmp .vx-cmp-head-vendor-rank{font-family:var(--ff-m,'DM Mono',monospace);font-size:.6rem;letter-spacing:.08em;opacity:.8}
.vxp-cmp .vxp-fit{cursor:default}
.vxp-cmp .vxp-fit[data-fit="yes"]{background:rgba(120,170,130,.32);border-color:rgba(120,170,130,.7);color:#dff0e0}
.vxp-cmp .vxp-fit[data-fit="short"],.vxp-cmp .vxp-fit[data-fit="unknown"]{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.35);color:#fff}
.vxp-cmp a.vx-cmp-why-btn{text-decoration:none;min-height:0}
.vxp-cmp .vxp-needflag{display:block;font-family:var(--ff-m,'DM Mono',monospace);font-size:.56rem;letter-spacing:.06em;text-transform:uppercase;color:var(--green,#2C4A3E);margin-top:3px;font-weight:500}
.vxp-cmp .vx-cmp-row.vxp-need .vx-cmp-row-label{background:rgba(44,74,62,.07)}
.vxp-cmp .vxp-proxy{font-style:italic;color:var(--text-mid,#4A4A4A)}
.vxp-cmp .vx-cmp-cell a.vx-cmp-cell-value{color:var(--green,#2C4A3E);text-decoration:none;font-weight:600}
.vxp-cmpwrap .vx-cmp-rotate-x{min-height:0}
.vxtriprow{align-items:center}
.vxtriprow .chevg{margin-left:auto;color:var(--green);font-size:18px;line-height:1;transition:transform .15s ease}
.vxtriprow[aria-expanded="true"] .chevg{transform:rotate(90deg)}
/* ⛑ A FOLDED ROW IS ITS NAME AND AN ARROW — the name renames in place, the arrow
   (with a thumb-sized target) opens and folds. */
.vxhead-name{flex:1;min-width:0;display:flex;align-items:baseline;gap:8px;border:0;background:transparent;
  padding:0;margin:0;font:inherit;color:inherit;text-align:left;cursor:pointer}
.vxhead-fold{position:relative;flex:0 0 28px;align-self:stretch;border:0;background:transparent;padding:0;margin:0;
  display:flex;align-items:center;justify-content:flex-end;cursor:pointer;color:var(--green)}
.vxhead-fold::after{content:'';position:absolute;inset:0 -10px 0 -14px}
.vxhead-fold .chevg{margin-left:0}
.vxhead-fold[aria-expanded="true"] .chevg{transform:rotate(90deg)}
.vxhead-name:focus-visible,.vxhead-fold:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:6px}
/* ⛑ AN ANSWER CHANGES WHERE IT IS — the row opens into the question's own field. */
.vxans.vxinline{flex-direction:column;align-items:stretch;gap:8px;background:#fff;box-shadow:inset 0 0 0 1px var(--gold);cursor:default}
.vxans.vxinline .k{flex:0 0 auto}
.vxinline-ask{margin:0;font-family:var(--ff-b);font-size:15px;font-weight:600;line-height:1.25;color:var(--ink)}
.vx.editing .vxlog{max-height:none;overflow:visible}
/* A loop's boarding times, as the engine scheduled them. */
.vxboards{margin-top:10px}
.vxboards p{margin:4px 0 0;font-size:14px;line-height:1.7;color:var(--ink);font-variant-numeric:tabular-nums}
/* ⛑ THE TRIP BUILDER — its name, Day | Passengers on one line, a line per stop. */
.vxtb{display:flex;flex-direction:column;gap:12px;margin-top:14px}
.vxtb-eyebrow{margin:0;font-family:var(--ff-m);font-size:10px;letter-spacing:.09em;text-transform:uppercase;color:var(--gold-deep)}
/* ⛑ THE TRIP'S NAME IS A FIELD — empty, it wears the gold edge until it is named. */
.vxtb-name.empty{border-color:var(--gold);box-shadow:0 0 0 1px var(--gold)}
.vxtb-line,.vxtime{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.vxpill{position:relative;display:flex;flex-direction:column;justify-content:center;gap:2px;min-width:0;min-height:56px;
  padding:7px 14px;border:1px solid var(--line);border-radius:14px;background:#fff;cursor:pointer}
.vxpill.wide{grid-column:1 / -1}
.vxpill-k{font-family:var(--ff-m);font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
/* ⛑ THE VALUE SITS IN THE MIDDLE OF THE FIELD — Stephen, on his iPhone 2026-09-15: "the leave by
   and the time data are not aligned to the middle of the field."
   MEASURED in an isolated harness first: .vxpill is already flex/column/justify-content:center
   and comes out at exactly 56px with 9.8px above and 9.8px below — so the pill's own rules were
   never the fault, and on a desktop engine there is nothing to fix. The extra height is the
   CONTROL: iOS applies its own minimum to <select> and <input type="time"> that outranks a
   declared height, so the box grows, the text keeps its own baseline, and the pair rides high.
   min-height:0 removes that floor and line-height pins the text box to the height we asked for. */
.vxpill select,.vxpill input{width:100%;min-width:0;height:24px;min-height:0;line-height:24px;border:0;background:transparent;padding:0;margin:0;
  font:inherit;font-size:16px;font-weight:600;color:var(--ink);-webkit-appearance:none;appearance:none}
/* ⛑ …AND A DATE IN A PILL NEEDS THE SAME TREATMENT AS ONE IN A FIELD. With appearance:none
   iOS draws a date's value at the TOP of its box (the reason .vxin has the rule below), so the
   trip card's Day would ride high above Passengers beside it — the exact misalignment Stephen
   reported for Leave by. The value's own line is pinned to the 24px the pill gives it. */
.vxpill input[type=date]::-webkit-date-and-time-value{line-height:24px;min-height:24px}
.vxpill input::placeholder{color:var(--muted);font-weight:500}
.vxpill select:focus,.vxpill input:focus{outline:none}
.vxpill:focus-within{border-color:var(--gold);box-shadow:0 0 0 1px var(--gold)}
.vxpill.static{cursor:default}
.vxpill-v{font-size:16px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vxstops{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.vxstop{display:grid;grid-template-columns:24px minmax(0,1fr) auto 12px;align-items:center;gap:10px;width:100%;min-height:54px;
  padding:8px 12px;border:1px solid var(--line);border-radius:14px;background:#fff;font:inherit;text-align:left;color:var(--ink);cursor:pointer}
.vxstop:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxstop-n{width:24px;height:24px;border-radius:50%;background:var(--green);color:#fff;font-size:12px;font-weight:600;
  display:flex;align-items:center;justify-content:center;font-variant-numeric:tabular-nums}
.vxstop-route{min-width:0;font-size:14.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vxstop-when{font-size:12.5px;color:var(--charcoal);white-space:nowrap;font-variant-numeric:tabular-nums}
.vxstop-when.warn{color:#8a4b1f;font-weight:600}
.vxstop .chevg{color:var(--green);font-size:18px;line-height:1}
/* ⛑ THE TRIP READS AS ITS PLACES — one row per place, joined by a line, the last one the
   bookend. */
.vxstops{gap:0;border:1px solid var(--line);border-radius:14px;background:#fff;padding:4px 0}
.vxpt{position:relative}
.vxpt:not(:first-child)::before,.vxpt:not(:last-child)::after{content:'';position:absolute;left:22px;width:2px;background:rgba(35,51,44,.18)}
.vxpt:not(:first-child)::before{top:0;height:50%}
.vxpt:not(:last-child)::after{top:50%;height:50%}
.vxpt .vxstop{position:relative;z-index:1;grid-template-columns:18px minmax(0,1fr) auto 12px;min-height:48px;padding:6px 12px 6px 14px;
  border:0;border-radius:0;background:transparent}
.vxpt .vxstop-route{white-space:normal;line-height:1.3}
.vxpt-dot{width:11px;height:11px;border-radius:50%;background:var(--green);justify-self:center;box-shadow:0 0 0 3px #fff}
.vxpt.pickup .vxpt-dot{background:#fff;border:2px solid var(--green);width:9px;height:9px}
.vxpt.end .vxpt-dot{background:var(--gold);width:13px;height:13px}
.vxpt.end .vxstop-route{font-weight:700}
.vxstop-add{align-self:flex-start;border:0;background:transparent;padding:6px 2px;font:inherit;font-size:14.5px;font-weight:600;color:var(--green);cursor:pointer}
.vxstop-add.first{align-self:stretch;min-height:56px;border:1px dashed var(--gold);border-radius:14px;background:#fff}
.vxrt{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border:1px solid var(--line);border-radius:14px;background:#fff;cursor:pointer}
.vxrt b{display:block;font-size:14.5px;color:var(--ink)}
.vxrt small{display:block;font-size:12px;color:var(--charcoal)}
.vxtb .vxrt input[type=checkbox]{-webkit-appearance:none;appearance:none;flex:0 0 auto;width:46px;height:28px;min-height:0;max-height:28px;padding:0;border:0;margin:0;border-radius:999px;
  background:rgba(35,51,44,.18);position:relative;cursor:pointer;transition:background .15s ease}
.vxtb .vxrt input[type=checkbox]::after{content:'';position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:50%;background:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.22);transition:transform .15s ease}
.vxtb .vxrt input[type=checkbox]:checked{background:var(--green)}
.vxtb .vxrt input[type=checkbox]:checked::after{transform:translateX(18px)}
.vxtb .vxrt input[type=checkbox]:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
/* ⛑ THE STOP SHEET — fixed in one place, the same for every stop; it grows to the
   whole screen only while a place is searched, so the keyboard never covers it. */
body.vxsheet-open{overflow:hidden}
.vxsheet-scrim{position:fixed;inset:0;z-index:80;background:rgba(20,28,24,.38)}
.vxsheet{position:fixed;left:0;right:0;bottom:0;z-index:81;max-width:560px;margin:0 auto;max-height:92dvh;overflow-y:auto;
  display:flex;flex-direction:column;gap:12px;padding:8px 18px calc(18px + env(safe-area-inset-bottom));
  background:var(--cream);border-radius:22px 22px 0 0;box-shadow:0 -12px 36px rgba(20,28,24,.18);animation:vxsheetin .22s ease}
/* ⛑ SCROLL, NEVER SQUEEZE — Stephen, on his iPhone 2026-09-15: "In-line editing worked great
   but the field spacing got compressed." Capped above the keyboard, the sheet is a flex
   column, and flex items shrink before a box scrolls: the To row and Recently used were cut
   in half. Every block keeps its own height; the sheet scrolls inside what is left. */
.vxsheet > *{flex-shrink:0}
@keyframes vxsheetin{from{transform:translateY(28px);opacity:.5}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.vxsheet{animation:none}}
.vxsheet-grab{width:38px;height:5px;border-radius:3px;background:rgba(35,51,44,.2);margin:2px auto 0}
.vxsheet-head{display:flex;align-items:center;gap:10px}
.vxsheet-head h2{flex:1;min-width:0;margin:0;font-family:var(--ff-s);font-size:25px;font-weight:600;line-height:1.15;color:var(--ink)}
.vxsheet-head h2 small{display:block;font-family:var(--ff-b);font-size:12px;font-weight:500;color:var(--charcoal);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vxsheet-x,.vxsheet-back{flex:0 0 40px;height:40px;border:0;border-radius:50%;background:rgba(35,51,44,.08);color:var(--ink);font-size:17px;line-height:1;cursor:pointer}
.vxsheet-x:focus-visible,.vxsheet-back:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.vxroute{position:relative;border:1px solid var(--line);border-radius:16px;background:#fff;overflow:hidden}
/* ⛑ NO CONNECTOR BETWEEN THE DOTS — Stephen, on his iPhone 2026-09-15: "the dot in the From
   field has a directional line from the bottom of the point… if we clean up these items it
   visually may not look like an overlap". The line ran from under the From dot to the To dot;
   with the focus bar beside it the pair read as one field sitting on top of another. The two
   dots already say which is which (green start, gold end), so the line was decoration that
   cost legibility. */
.vxroute-f{position:relative;display:grid;grid-template-columns:16px 40px minmax(0,1fr);align-items:center;gap:8px;width:100%;min-height:58px;
  padding:8px 14px;border:0;background:transparent;font:inherit;text-align:left;color:var(--ink);cursor:pointer}
.vxroute-f + .vxroute-f{border-top:1px solid var(--line)}
/* ⛑ NO FOCUS TREATMENT ON THE ROW AT ALL — Stephen, 2026-09-15: "We don't need the focus, the
   cursor does that well and the field alignment in the screenshot looks great." It was
   `inset 3px 0 0 gold`, a bar down the left edge of the focused row that read as one field
   overlapping the other; a warm tint replaced it, and the tint was not wanted either. The
   caret is the cue. Nothing here should re-add a focus style to .vxroute-f. */
.vxroute-in{min-width:0;width:100%;height:30px;border:0;background:transparent;padding:0;margin:0;font:inherit;font-size:16px;font-weight:600;
  color:var(--ink);text-overflow:ellipsis;-webkit-appearance:none;appearance:none}
.vxroute-in::placeholder{color:var(--muted);font-weight:500}
.vxroute-in:focus{outline:none}
.vxroute-sug{max-height:38dvh;overflow-y:auto;border:1px solid var(--line);border-radius:14px;background:#fff;padding:0 12px}
.vxroute-sug .vxpick-row:last-child{border-bottom:0}
.vxroute-dot{position:relative;z-index:1;width:11px;height:11px;border-radius:50%;background:var(--green);justify-self:center}
.vxroute-f.to .vxroute-dot{background:var(--gold)}
.vxroute-k{font-family:var(--ff-m);font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vxsheet-actions{display:flex;flex-wrap:wrap;gap:8px}
.vxsheet-actions .alt,.vxsheet-actions .next{flex:1 1 140px}
.vxsheet-actions [aria-disabled="true"]{opacity:.45}
.vxsheet-rm{flex:1 1 100%;border:0;background:transparent;padding:6px;font:inherit;font-size:13.5px;font-weight:600;color:#8a4b1f;cursor:pointer}
.vxpick{display:flex;flex-direction:column}
.vxpick-k{margin:10px 2px 2px;font-family:var(--ff-m);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--gold-deep)}
.vxpick-row{display:grid;grid-template-columns:34px minmax(0,1fr);align-items:center;gap:12px;width:100%;min-height:56px;padding:8px 2px;
  border:0;border-bottom:1px solid var(--line);background:transparent;font:inherit;text-align:left;color:var(--ink);cursor:pointer}
.vxpick-row:focus-visible{outline:2px solid var(--gold);outline-offset:-2px}
.vxpick-ic{width:34px;height:34px;border-radius:50%;background:rgba(35,51,44,.08);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--green)}
.vxpick-t{min-width:0}
.vxpick-t b{display:block;font-size:15px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vxpick-t small{display:block;font-size:12.5px;color:var(--charcoal);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* ⛑ VERA'S WELCOME, AS IN THE APP (verdeaux-local.html .vx-vera-header, its
   mobile size): portrait in a cream halo with a gold hairline, eyebrow, and her
   greeting in Cormorant with her name in gold italic. */
.vxhello{display:grid;grid-template-columns:120px minmax(0,1fr);gap:22px;align-items:center;margin:8px 0 0}
.vxhello-portrait{width:120px;height:120px;border-radius:50%;object-fit:cover;object-position:center;background:var(--cream);
  display:block;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)}
.vxhello-text{min-width:0}
.vxhello-eyebrow{font-family:var(--ff-m);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep);
  margin:0 0 6px;font-weight:500}
.vxhello-headline{font-family:var(--ff-s);font-size:36px;font-weight:400;color:var(--green);line-height:1.08;letter-spacing:-.01em;margin:0}
.vxhello-headline em{color:var(--gold);font-style:italic}
/* Indented from the gutter — Stephen: "indent the welcome paragraph a bit so it
   is not sitting on the left edge." The portrait's halo reaches past the gutter,
   so text flush with it read as pressed against the edge. */
.vxhello-intro{grid-column:1 / -1;font-family:var(--ff-s);font-size:20px;line-height:1.5;color:var(--ink);margin:6px 0 0;padding:0 6px 0 16px;text-wrap:pretty}
.vxav.has-portrait{background:var(--cream);box-shadow:0 0 0 2px rgba(200,169,110,.36);overflow:hidden}
.vxav.has-portrait img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
.why .mk.has-portrait{background:var(--cream);box-shadow:0 0 0 2px rgba(200,169,110,.36);overflow:hidden}
.why .mk.has-portrait img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
/* ⛑ VERA'S MENU IN THE HEADER — her portrait, as on her welcome; the menu holds the
   one account step that matters here. */
.vxmenu-wrap{position:relative}
.vxmenu-btn{appearance:none;border:0;padding:0;background:var(--cream);width:36px;height:36px;border-radius:50%;cursor:pointer;
  display:block;overflow:hidden;box-shadow:0 0 0 2px var(--cream),0 0 0 3px rgba(200,169,110,.55)}
.vxmenu-btn img{width:100%;height:100%;object-fit:cover;display:block}
.vxmenu-btn:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.vxmenu{position:absolute;top:46px;right:0;z-index:50;width:min(280px,82vw);background:#fff;border:1px solid rgba(200,169,110,.35);
  border-radius:12px;box-shadow:0 14px 36px rgba(28,28,28,.16);padding:6px}
.vxmenu-who{padding:10px 10px 12px;border-bottom:1px solid var(--line);margin:0 0 4px}
.vxmenu-who b{display:block;font-size:14px;color:var(--ink)}
.vxmenu-who span{display:block;font-size:12px;line-height:1.45;color:var(--charcoal);margin-top:2px}
.vxmenu-item{display:block;width:100%;text-align:left;border:0;background:transparent;border-radius:8px;padding:10px;
  font:inherit;font-size:14px;font-weight:600;color:var(--green);cursor:pointer;text-decoration:none}
.vxmenu-item small{display:block;font-size:12px;font-weight:400;color:var(--charcoal);margin-top:2px}
.vxmenu-item:hover,.vxmenu-item:focus-visible{background:var(--cream-2);outline:none}
/* ⛑ RELEASE AND SIGN OUT, AS IN THE APP'S MENU. */
.vxmenu-build{display:flex;align-items:baseline;justify-content:space-between;gap:10px;width:100%;margin-top:4px;padding:10px;
  border:0;border-top:1px solid var(--line);background:transparent;cursor:pointer;font:inherit;text-align:left}
.vxmenu-build span{font-family:var(--ff-m);font-size:9px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.vxmenu-build b{font-family:var(--ff-m);font-size:12px;font-weight:500;color:var(--ink)}
.vxmenu-build:focus-visible{outline:2px solid var(--gold);outline-offset:-2px;border-radius:8px}
.vxmenu-confirm{display:flex;gap:8px;padding:4px 6px 8px}
.vxmenu-confirm .alt,.vxmenu-confirm .next{height:40px;flex:1}
.vxmenu-idea{display:block;width:100%;box-sizing:border-box;margin:4px 0 6px;padding:10px;border:1px solid var(--line);border-radius:8px;
  font:inherit;font-size:16px;line-height:1.4;resize:vertical;min-height:88px}
.vxmenu-note{margin:6px 10px 10px;font-size:13px;line-height:1.45;color:var(--charcoal)}
.vxmenu-note.bad{color:#9b3b2e}
.vxtips{position:fixed;inset:0;z-index:80;background:rgba(20,24,22,.62);display:flex;align-items:center;justify-content:center;padding:16px}
.vxtips-card{position:relative;width:min(560px,100%);background:#fff;border-radius:14px;padding:12px;box-shadow:0 12px 40px rgba(0,0,0,.25)}
.vxtips-card video{display:block;width:100%;max-height:70vh;border-radius:10px;background:#000}
.vxtips-t{margin:10px 40px 2px 4px;font-size:14px;color:var(--ink)}
.vxtips-x{position:absolute;top:6px;right:6px;z-index:1;width:36px;height:36px;min-height:0;border:0;border-radius:50%;background:var(--cream-2);
  font-size:22px;line-height:1;cursor:pointer}
/* ⛑ THE PAYWALL AT PRINT AND SEND — two plans, the upgrade note, Early Access, Stripe's card form. */
.cotiers{display:grid;gap:8px;margin:6px 0 8px}
.cotier{display:flex;flex-direction:column;gap:4px;width:100%;text-align:left;border:1px solid var(--line);border-radius:14px;background:#fff;
  padding:12px 14px;font:inherit;color:var(--ink);cursor:pointer}
.cotier.on{border-color:var(--green);box-shadow:0 0 0 1px var(--green)}
.cotier-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.cotier-top b{font-size:15.5px}
.cotier-price{font-family:var(--ff-s);font-size:24px;font-weight:600;color:var(--green)}
.cotier small{font-size:12.5px;line-height:1.45;color:var(--charcoal)}
.cotier:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.coea{margin:10px 0 12px}
.copay{min-height:120px}
@keyframes vxin{from{opacity:.4;transform:translateY(4px)}to{opacity:1;transform:none}}

/* ── The operator journal ────────────────────────────────────────────────
   ⛑ 2026-09-16, Stephen: "there is no link to the journal to make notes and
   update the data from an email response or telephone call." What an operator
   SAID is a different kind of fact from what we looked up, so it sits under the
   compare table rather than inside it — and it survives a re-search, because it
   lives in weekend_briefs.answers rather than in the brief the engine rebuilds. */
.oplog-wrap{margin:26px 0 0}
.oplog-said{color:var(--green,#2C4A3E);font-weight:600}
.oplog{background:#fff;border:1px solid var(--line,rgba(44,74,62,.16));border-radius:14px;
  padding:14px 15px;margin:10px 0 0;box-shadow:0 1px 3px rgba(44,74,62,.05)}
.oplog-name{font-weight:600;font-size:.95rem;color:var(--green,#2C4A3E);margin-bottom:10px}
.oplog-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.oplog-chip{font-family:var(--ff-b,'DM Sans',sans-serif);font-size:12.5px;padding:7px 13px;
  border-radius:999px;border:1px solid var(--line,rgba(44,74,62,.16));background:#fff;
  color:var(--green,#2C4A3E);cursor:pointer}
.oplog-chip[aria-pressed="true"]{background:var(--green,#2C4A3E);border-color:var(--green,#2C4A3E);color:var(--cream,#FAF7F2)}
.oplog-f{display:block;margin:9px 0 0}
.oplog-f > span{display:block;font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--green,#2C4A3E);font-weight:600;margin-bottom:5px}
/* 16px, or iOS Safari zooms the page the moment the field takes focus — the same
   floor the wizard's own fields and the demo save card carry. */
.oplog-f input,.oplog-f textarea{width:100%;box-sizing:border-box;font-size:16px;padding:10px 11px;
  border:1px solid var(--line,rgba(44,74,62,.16));border-radius:10px;background:#fff;
  font-family:var(--ff-b,'DM Sans',sans-serif);color:var(--ink,#1c1c1c);resize:vertical}
.oplog-open{margin-top:4px;width:100%;font-family:var(--ff-b,'DM Sans',sans-serif);font-size:13px;
  font-weight:600;padding:10px 12px;border-radius:10px;border:1px solid var(--line,rgba(44,74,62,.16));
  background:var(--cream,#FAF7F2);color:var(--green,#2C4A3E);cursor:pointer;text-align:left}
.oplog-qs{margin-top:4px;padding-top:4px}
/* ⚑ An answer is not a filing. The compare table greys what a carrier told a regulator; what an
   operator told the couple on the phone is the fact that outranks it, so it reads as a fact. */
.vxp-cmp .vx-cmp-cell-value.vxp-said{color:var(--green,#2C4A3E);font-weight:600}
