@ottotheagent/mcp-card-assets 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@ The Otto flight card renderer and airline logos. The `render_flights` MCP tool r
6
6
 
7
7
  ## Contents
8
8
 
9
- - `flight-card.js` draws the card and exposes `OttoFlightCard.render(rootElement, card)`. It carries its CSS inline, so the sandbox loads one script. Select sends the fare's `select_prompt` through the host's `sendPrompt()`.
9
+ - `flight-card.js` draws the card and exposes `OttoFlightCard.render(rootElement, card)`. It carries its CSS inline, so the sandbox loads one script. Select builds "Book flight … (flight_id …)" from the fare and sends it through the host's `sendPrompt()`.
10
10
  - `flight-card.css` is the same CSS as a separate file, for reference.
11
11
  - `marks/<IATA>.png` holds the airline logos.
12
12
 
package/flight-card.css CHANGED
@@ -1 +1 @@
1
- :root{--otto-card-bg:#ffffff;--otto-card-border:#d4d4d4;--otto-btn-border:#525252;--otto-accent:#08c0cc;--otto-divider:#e5e5e5;--otto-strip-bg:#f5f5f5;--otto-fare-bg:#262624;--otto-on-fare:#ffffff;--otto-chip-bg:#ccfbf1;--otto-chip-text:#0a0a0a;--otto-text-primary:#0a0a0a;--otto-text-body:#0a0a0a;--otto-text-secondary:#737373;--otto-link-hover:#0369a1;--otto-banner-bg:#171717;--otto-on-banner:#ffffff;--otto-caution-bg:#fdf0dd;--otto-caution-text:#96590b;--otto-positive-text:#1c7a3e;--otto-photo-bg:#f5f5f5;--otto-font:Inter,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";--otto-line:1.5;--otto-text-xs:10px;--otto-text-sm:11px;--otto-text-md:12px;--otto-text-base:13px;--otto-text-lg:14px;--otto-text-xl:18px;--otto-text-2xl:19px;--otto-weight-regular:400;--otto-weight-medium:500;--otto-weight-semibold:600;--otto-space-1:2px;--otto-space-2:6px;--otto-space-3:8px;--otto-space-4:10px;--otto-space-5:12px;--otto-space-6:14px;--otto-space-7:16px;--otto-space-8:18px;--otto-radius-card:12px;--otto-radius-fare:10px;--otto-radius-md:8px;--otto-radius-pill:999px;--otto-card-width:304px;--otto-icon-size:14px;--otto-photo-height:170px;--otto-mark-size:24px;--otto-chip-height:24px;--otto-tap-min:44px;}@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}}:root[data-theme="dark"]{--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}html,body{margin:0;background:transparent;font-family:var(--otto-font);line-height:var(--otto-line);color:var(--otto-text-primary);}#root{min-height:120px;padding:0;}button{font:inherit;}.head{margin-bottom:var(--otto-space-5);}.title{font-size:var(--otto-text-lg);line-height:22px;font-weight:var(--otto-weight-semibold);}.subtitle,.empty{font-size:var(--otto-text-base);color:var(--otto-text-secondary);}.row{display:flex;gap:var(--otto-space-5);overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:var(--otto-space-2);}.opt{flex:0 0 var(--otto-card-width);width:var(--otto-card-width);min-width:0;overflow-wrap:anywhere;box-sizing:border-box;scroll-snap-align:start;display:flex;flex-direction:column;padding:var(--otto-space-7);background:var(--otto-card-bg);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);}.opt.chosen{border-color:var(--otto-accent);}@media (hover:hover){.opt:hover{border-color:var(--otto-accent);}}.chip{display:inline-flex;align-items:center;height:var(--otto-chip-height);padding:0 var(--otto-space-4);box-sizing:border-box;max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;border-radius:var(--otto-radius-pill);font-size:var(--otto-text-sm);font-weight:var(--otto-weight-semibold);background:var(--otto-chip-bg);color:var(--otto-chip-text);}.chip.caution{background:var(--otto-caution-bg);color:var(--otto-caution-text);}.btn{flex-shrink:0;min-height:41px;padding:9px var(--otto-space-7);box-sizing:border-box;white-space:nowrap;cursor:pointer;border-radius:var(--otto-radius-md);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);display:inline-flex;align-items:center;justify-content:center;gap:var(--otto-space-2);background:transparent;color:var(--otto-text-primary);border:1px solid var(--otto-btn-border);}.btn:disabled{cursor:default;opacity:0.45;}.why{margin-top:var(--otto-space-7);font-size:var(--otto-text-base);color:var(--otto-text-body);}.whyHead{font-weight:var(--otto-weight-semibold);}.whyLine{display:flex;gap:var(--otto-space-3);}.tick{--otto-icon-size:12px;height:19.5px;font-size:var(--otto-text-md);}.tick.note{color:var(--otto-text-secondary);}@media (max-width:480px){.opt{flex-basis:min(var(--otto-card-width),82vw);width:min(var(--otto-card-width),82vw);}.btn{min-height:var(--otto-tap-min);}}.carrier{display:flex;align-items:center;gap:var(--otto-space-3);min-height:var(--otto-chip-height);}.airline{flex:1;min-width:0;display:flex;align-items:center;gap:var(--otto-space-4);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);}.airlineName{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.chips{display:flex;gap:var(--otto-space-1);flex-shrink:0;}.mark{width:var(--otto-mark-size);height:var(--otto-mark-size);border-radius:50%;flex-shrink:0;display:grid;place-items:center;font-size:var(--otto-text-xs);font-weight:var(--otto-weight-semibold);letter-spacing:0.3px;color:#fff;background:#5b6470;}img.mark{object-fit:contain;background:transparent;border:0;padding:0;}.fltline{display:flex;justify-content:space-between;margin-top:var(--otto-space-8);font-size:var(--otto-text-md);color:var(--otto-text-body);}.times,.ports{display:flex;align-items:center;justify-content:space-between;}.times{margin-top:var(--otto-space-2);gap:var(--otto-space-3);}.ports{margin-top:var(--otto-space-1);font-size:var(--otto-text-lg);color:var(--otto-text-body);}.clock{font-size:var(--otto-text-xl);font-weight:var(--otto-weight-semibold);white-space:nowrap;}.plus{font-size:var(--otto-text-sm);vertical-align:super;color:var(--otto-caution-text);}.rule{flex:1;height:1px;background:var(--otto-divider);}.plane{color:var(--otto-text-secondary);}.fareBlock{margin-top:var(--otto-space-6);display:flex;flex-direction:column;}.strip{height:66px;box-sizing:border-box;display:flex;align-items:flex-start;justify-content:space-between;gap:var(--otto-space-3);padding:9px var(--otto-space-5) 0;border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);font-size:var(--otto-text-base);}.strip + .fareRow{margin-top:-27px;}.lowest{min-width:0;font-weight:var(--otto-weight-semibold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lowestName{font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.strip button.link{flex-shrink:0;display:inline-flex;gap:6px;height:auto;min-height:0;margin:0;padding:0;border:0;border-radius:0;box-shadow:none;background:none;appearance:none;cursor:pointer;align-items:center;font-size:var(--otto-text-base);line-height:var(--otto-line);color:var(--otto-text-primary);}@media (hover:hover){.opt.hasFares:hover .link{color:var(--otto-link-hover);}.opt.hasFares:hover .linkText{text-decoration:underline;}}.fareRow{position:relative;height:78px;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-2) var(--otto-space-5) var(--otto-space-2) var(--otto-space-6);border-radius:var(--otto-radius-fare);background:var(--otto-fare-bg);color:var(--otto-on-fare);}.fareText{min-width:0;}.amount{font-size:var(--otto-text-2xl);font-weight:var(--otto-weight-semibold);}.fareName{font-size:var(--otto-text-base);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.fareFacts{font-size:var(--otto-text-md);opacity:0.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.tag{font-size:var(--otto-text-md);}.fareRow .btn.onFare{padding:9px 20px;background:var(--otto-on-fare);color:var(--otto-fare-bg);border-color:var(--otto-on-fare);}.fareRow .btn.onFare.chosen{padding:9px var(--otto-space-7);border-color:var(--otto-accent);}.opt.hasFares{cursor:pointer;}.opt.open{border-color:var(--otto-accent);}.fareList{margin-top:var(--otto-space-7);padding:var(--otto-space-7);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);background:var(--otto-card-bg);display:flex;flex-direction:column;gap:var(--otto-space-3);}.fareListHead{margin-bottom:var(--otto-space-1);font-size:var(--otto-text-md);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderRow{display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-3) var(--otto-space-3) var(--otto-space-3) var(--otto-space-6);border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);}.ladderRow.recommended{border-color:var(--otto-text-primary);}.ladderLabel{min-width:0;}.ladderName{font-size:var(--otto-text-base);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderFacts{font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.ladderRight{flex-shrink:0;display:flex;align-items:center;gap:var(--otto-space-5);}.ladderAmount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.ladderRow .btn{min-height:36px;padding:6px var(--otto-space-6);background:var(--otto-card-bg);border-color:var(--otto-text-primary);}.btn.chosen:not(.onFare){background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}#root.busy .opt.open:not(.chosen){border-color:var(--otto-accent);}#root.busy .opt.hasFares:hover .link{color:var(--otto-text-primary);}#root.busy .opt.hasFares:hover .linkText{text-decoration:none;}.strip button.link:disabled{cursor:default;opacity:0.45;}.btn.chosen:disabled{opacity:1;}
1
+ :root{--otto-card-bg:#ffffff;--otto-card-border:#d4d4d4;--otto-btn-border:#525252;--otto-accent:#08c0cc;--otto-divider:#e5e5e5;--otto-strip-bg:#f5f5f5;--otto-fare-bg:#262624;--otto-on-fare:#ffffff;--otto-chip-bg:#ccfbf1;--otto-chip-text:#0a0a0a;--otto-text-primary:#0a0a0a;--otto-text-body:#0a0a0a;--otto-text-secondary:#737373;--otto-link-hover:#0369a1;--otto-banner-bg:#171717;--otto-on-banner:#ffffff;--otto-caution-bg:#fdf0dd;--otto-caution-text:#96590b;--otto-positive-text:#1c7a3e;--otto-photo-bg:#f5f5f5;--otto-font:Inter,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";--otto-line:1.5;--otto-text-xs:10px;--otto-text-sm:11px;--otto-text-md:12px;--otto-text-base:13px;--otto-text-lg:14px;--otto-text-xl:18px;--otto-text-2xl:19px;--otto-weight-regular:400;--otto-weight-medium:500;--otto-weight-semibold:600;--otto-space-1:2px;--otto-space-2:6px;--otto-space-3:8px;--otto-space-4:10px;--otto-space-5:12px;--otto-space-6:14px;--otto-space-7:16px;--otto-space-8:18px;--otto-radius-card:12px;--otto-radius-fare:10px;--otto-radius-md:8px;--otto-radius-pill:999px;--otto-card-width:304px;--otto-icon-size:14px;--otto-photo-height:170px;--otto-mark-size:24px;--otto-chip-height:24px;--otto-tap-min:44px;}@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}}:root[data-theme="dark"]{--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}html,body{margin:0;background:transparent;font-family:var(--otto-font);line-height:var(--otto-line);color:var(--otto-text-primary);}#root{min-height:120px;padding:0;}button{font:inherit;}.head{margin-bottom:var(--otto-space-5);}.title{font-size:var(--otto-text-lg);line-height:22px;font-weight:var(--otto-weight-semibold);}.subtitle,.empty{font-size:var(--otto-text-base);color:var(--otto-text-secondary);}.row{display:flex;gap:var(--otto-space-5);overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:var(--otto-space-2);}.opt{flex:0 0 var(--otto-card-width);width:var(--otto-card-width);min-width:0;overflow-wrap:anywhere;box-sizing:border-box;scroll-snap-align:start;display:flex;flex-direction:column;padding:var(--otto-space-7);background:var(--otto-card-bg);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);}.opt.chosen{border-color:var(--otto-accent);}@media (hover:hover){.opt:hover{border-color:var(--otto-accent);}}.chip{display:inline-flex;align-items:center;height:var(--otto-chip-height);padding:0 var(--otto-space-4);box-sizing:border-box;max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;border-radius:var(--otto-radius-pill);font-size:var(--otto-text-sm);font-weight:var(--otto-weight-semibold);background:var(--otto-chip-bg);color:var(--otto-chip-text);}.chip.caution{background:var(--otto-caution-bg);color:var(--otto-caution-text);}.btn{flex-shrink:0;min-height:41px;padding:9px var(--otto-space-7);box-sizing:border-box;white-space:nowrap;cursor:pointer;border-radius:var(--otto-radius-md);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);display:inline-flex;align-items:center;justify-content:center;gap:var(--otto-space-2);background:transparent;color:var(--otto-text-primary);border:1px solid var(--otto-btn-border);}.btn:disabled{cursor:default;opacity:0.45;}.why{margin-top:var(--otto-space-7);font-size:var(--otto-text-base);color:var(--otto-text-body);}.whyHead{font-weight:var(--otto-weight-semibold);}.whyLine{display:flex;gap:var(--otto-space-3);}.tick{--otto-icon-size:12px;height:19.5px;font-size:var(--otto-text-md);}.tick.note{color:var(--otto-text-secondary);}@media (max-width:480px){.opt{flex-basis:min(var(--otto-card-width),82vw);width:min(var(--otto-card-width),82vw);}.btn{min-height:var(--otto-tap-min);}}.carrier{display:flex;align-items:center;gap:var(--otto-space-3);min-height:var(--otto-chip-height);}.airline{flex:1;min-width:0;display:flex;align-items:center;gap:var(--otto-space-4);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);}.airlineName{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.chips{display:flex;gap:var(--otto-space-1);flex-shrink:0;}.mark{width:var(--otto-mark-size);height:var(--otto-mark-size);border-radius:50%;flex-shrink:0;display:grid;place-items:center;font-size:var(--otto-text-xs);font-weight:var(--otto-weight-semibold);letter-spacing:0.3px;color:#fff;background:#5b6470;}img.mark{object-fit:contain;background:transparent;border:0;padding:0;}.fltline{display:flex;justify-content:space-between;margin-top:var(--otto-space-8);font-size:var(--otto-text-md);color:var(--otto-text-body);}.times,.ports{display:flex;align-items:center;justify-content:space-between;}.times{margin-top:var(--otto-space-2);gap:var(--otto-space-3);}.ports{margin-top:var(--otto-space-1);font-size:var(--otto-text-lg);color:var(--otto-text-body);}.clock{font-size:var(--otto-text-xl);font-weight:var(--otto-weight-semibold);white-space:nowrap;}.plus{font-size:var(--otto-text-sm);vertical-align:super;color:var(--otto-caution-text);}.rule{flex:1;height:1px;background:var(--otto-divider);}.plane{color:var(--otto-text-secondary);}.fareBlock{margin-top:var(--otto-space-6);display:flex;flex-direction:column;}.strip{height:66px;box-sizing:border-box;display:flex;align-items:flex-start;justify-content:space-between;gap:var(--otto-space-3);padding:9px var(--otto-space-5) 0;border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);font-size:var(--otto-text-base);}.strip + .fareRow{margin-top:-27px;}.lowest{min-width:0;font-weight:var(--otto-weight-semibold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lowestName{font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.strip button.link{flex-shrink:0;display:inline-flex;gap:6px;height:auto;min-height:0;margin:0;padding:0;border:0;border-radius:0;box-shadow:none;background:none;appearance:none;cursor:pointer;align-items:center;font-size:var(--otto-text-base);line-height:var(--otto-line);color:var(--otto-text-primary);}@media (hover:hover){.opt.hasFares:hover .link{color:var(--otto-link-hover);}.opt.hasFares:hover .linkText{text-decoration:underline;}}.fareRow{position:relative;height:78px;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-2) var(--otto-space-5) var(--otto-space-2) var(--otto-space-6);border-radius:var(--otto-radius-fare);background:var(--otto-fare-bg);color:var(--otto-on-fare);}.fareText{min-width:0;}.amount{font-size:var(--otto-text-2xl);font-weight:var(--otto-weight-semibold);}.fareName{font-size:var(--otto-text-base);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.fareFacts{font-size:var(--otto-text-md);opacity:0.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.tag{font-size:var(--otto-text-md);}.fareRow .btn.onFare{padding:9px 20px;background:var(--otto-on-fare);color:var(--otto-fare-bg);border-color:var(--otto-on-fare);}.fareRow .btn.onFare.chosen{padding:9px var(--otto-space-7);border-color:var(--otto-accent);}.opt.hasFares{cursor:pointer;}.opt.open{border-color:var(--otto-accent);}.fareList{margin-top:var(--otto-space-7);padding:var(--otto-space-7);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);background:var(--otto-card-bg);display:flex;flex-direction:column;gap:var(--otto-space-3);}.fareListHead{margin-bottom:var(--otto-space-1);font-size:var(--otto-text-md);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderRow{display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-3) var(--otto-space-3) var(--otto-space-3) var(--otto-space-6);border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);}.ladderRow.recommended{border-color:var(--otto-text-primary);}@media (hover:hover){.ladderRow:hover{border-color:var(--otto-accent);}}.ladderLabel{min-width:0;}.ladderName{font-size:var(--otto-text-base);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderFacts{font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.ladderRight{flex-shrink:0;display:flex;align-items:center;gap:var(--otto-space-5);}.ladderAmount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.ladderRow .btn{min-height:36px;padding:6px var(--otto-space-6);background:var(--otto-card-bg);border-color:var(--otto-text-primary);}.btn.chosen:not(.onFare){background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}#root.busy .opt.open:not(.chosen){border-color:var(--otto-accent);}#root.busy .opt.hasFares:hover .link{color:var(--otto-text-primary);}#root.busy .opt.hasFares:hover .linkText{text-decoration:none;}#root.busy .ladderRow:hover{border-color:var(--otto-divider);}#root.busy .ladderRow.recommended:hover{border-color:var(--otto-text-primary);}.strip button.link:disabled{cursor:default;opacity:0.45;}.btn.chosen:disabled{opacity:1;}
package/flight-card.js CHANGED
@@ -4,13 +4,13 @@
4
4
  * <div id="root"></div><script src=".../flight-card.js"></script>
5
5
  * <script>OttoFlightCard.render(document.getElementById("root"), CARD)</script>
6
6
  * The CSS is inlined at build time (scripts/mcp/build_card_assets.py), so the
7
- * sandbox only has to allow this one script. Select sends the fare's
8
- * `select_prompt` through the host's global sendPrompt().
7
+ * sandbox only has to allow this one script. Select sends "Book flight …
8
+ * (flight_id …)" through the host's global sendPrompt().
9
9
  */
10
10
  (function () {
11
11
  "use strict";
12
12
 
13
- const CSS = ":root{--otto-card-bg:#ffffff;--otto-card-border:#d4d4d4;--otto-btn-border:#525252;--otto-accent:#08c0cc;--otto-divider:#e5e5e5;--otto-strip-bg:#f5f5f5;--otto-fare-bg:#262624;--otto-on-fare:#ffffff;--otto-chip-bg:#ccfbf1;--otto-chip-text:#0a0a0a;--otto-text-primary:#0a0a0a;--otto-text-body:#0a0a0a;--otto-text-secondary:#737373;--otto-link-hover:#0369a1;--otto-banner-bg:#171717;--otto-on-banner:#ffffff;--otto-caution-bg:#fdf0dd;--otto-caution-text:#96590b;--otto-positive-text:#1c7a3e;--otto-photo-bg:#f5f5f5;--otto-font:Inter,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";--otto-line:1.5;--otto-text-xs:10px;--otto-text-sm:11px;--otto-text-md:12px;--otto-text-base:13px;--otto-text-lg:14px;--otto-text-xl:18px;--otto-text-2xl:19px;--otto-weight-regular:400;--otto-weight-medium:500;--otto-weight-semibold:600;--otto-space-1:2px;--otto-space-2:6px;--otto-space-3:8px;--otto-space-4:10px;--otto-space-5:12px;--otto-space-6:14px;--otto-space-7:16px;--otto-space-8:18px;--otto-radius-card:12px;--otto-radius-fare:10px;--otto-radius-md:8px;--otto-radius-pill:999px;--otto-card-width:304px;--otto-icon-size:14px;--otto-photo-height:170px;--otto-mark-size:24px;--otto-chip-height:24px;--otto-tap-min:44px;}@media (prefers-color-scheme:dark){:root:not([data-theme=\"light\"]){--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}}:root[data-theme=\"dark\"]{--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}html,body{margin:0;background:transparent;font-family:var(--otto-font);line-height:var(--otto-line);color:var(--otto-text-primary);}#root{min-height:120px;padding:0;}button{font:inherit;}.head{margin-bottom:var(--otto-space-5);}.title{font-size:var(--otto-text-lg);line-height:22px;font-weight:var(--otto-weight-semibold);}.subtitle,.empty{font-size:var(--otto-text-base);color:var(--otto-text-secondary);}.row{display:flex;gap:var(--otto-space-5);overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:var(--otto-space-2);}.opt{flex:0 0 var(--otto-card-width);width:var(--otto-card-width);min-width:0;overflow-wrap:anywhere;box-sizing:border-box;scroll-snap-align:start;display:flex;flex-direction:column;padding:var(--otto-space-7);background:var(--otto-card-bg);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);}.opt.chosen{border-color:var(--otto-accent);}@media (hover:hover){.opt:hover{border-color:var(--otto-accent);}}.chip{display:inline-flex;align-items:center;height:var(--otto-chip-height);padding:0 var(--otto-space-4);box-sizing:border-box;max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;border-radius:var(--otto-radius-pill);font-size:var(--otto-text-sm);font-weight:var(--otto-weight-semibold);background:var(--otto-chip-bg);color:var(--otto-chip-text);}.chip.caution{background:var(--otto-caution-bg);color:var(--otto-caution-text);}.btn{flex-shrink:0;min-height:41px;padding:9px var(--otto-space-7);box-sizing:border-box;white-space:nowrap;cursor:pointer;border-radius:var(--otto-radius-md);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);display:inline-flex;align-items:center;justify-content:center;gap:var(--otto-space-2);background:transparent;color:var(--otto-text-primary);border:1px solid var(--otto-btn-border);}.btn:disabled{cursor:default;opacity:0.45;}.why{margin-top:var(--otto-space-7);font-size:var(--otto-text-base);color:var(--otto-text-body);}.whyHead{font-weight:var(--otto-weight-semibold);}.whyLine{display:flex;gap:var(--otto-space-3);}.tick{--otto-icon-size:12px;height:19.5px;font-size:var(--otto-text-md);}.tick.note{color:var(--otto-text-secondary);}@media (max-width:480px){.opt{flex-basis:min(var(--otto-card-width),82vw);width:min(var(--otto-card-width),82vw);}.btn{min-height:var(--otto-tap-min);}}.carrier{display:flex;align-items:center;gap:var(--otto-space-3);min-height:var(--otto-chip-height);}.airline{flex:1;min-width:0;display:flex;align-items:center;gap:var(--otto-space-4);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);}.airlineName{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.chips{display:flex;gap:var(--otto-space-1);flex-shrink:0;}.mark{width:var(--otto-mark-size);height:var(--otto-mark-size);border-radius:50%;flex-shrink:0;display:grid;place-items:center;font-size:var(--otto-text-xs);font-weight:var(--otto-weight-semibold);letter-spacing:0.3px;color:#fff;background:#5b6470;}img.mark{object-fit:contain;background:transparent;border:0;padding:0;}.fltline{display:flex;justify-content:space-between;margin-top:var(--otto-space-8);font-size:var(--otto-text-md);color:var(--otto-text-body);}.times,.ports{display:flex;align-items:center;justify-content:space-between;}.times{margin-top:var(--otto-space-2);gap:var(--otto-space-3);}.ports{margin-top:var(--otto-space-1);font-size:var(--otto-text-lg);color:var(--otto-text-body);}.clock{font-size:var(--otto-text-xl);font-weight:var(--otto-weight-semibold);white-space:nowrap;}.plus{font-size:var(--otto-text-sm);vertical-align:super;color:var(--otto-caution-text);}.rule{flex:1;height:1px;background:var(--otto-divider);}.plane{color:var(--otto-text-secondary);}.fareBlock{margin-top:var(--otto-space-6);display:flex;flex-direction:column;}.strip{height:66px;box-sizing:border-box;display:flex;align-items:flex-start;justify-content:space-between;gap:var(--otto-space-3);padding:9px var(--otto-space-5) 0;border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);font-size:var(--otto-text-base);}.strip + .fareRow{margin-top:-27px;}.lowest{min-width:0;font-weight:var(--otto-weight-semibold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lowestName{font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.strip button.link{flex-shrink:0;display:inline-flex;gap:6px;height:auto;min-height:0;margin:0;padding:0;border:0;border-radius:0;box-shadow:none;background:none;appearance:none;cursor:pointer;align-items:center;font-size:var(--otto-text-base);line-height:var(--otto-line);color:var(--otto-text-primary);}@media (hover:hover){.opt.hasFares:hover .link{color:var(--otto-link-hover);}.opt.hasFares:hover .linkText{text-decoration:underline;}}.fareRow{position:relative;height:78px;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-2) var(--otto-space-5) var(--otto-space-2) var(--otto-space-6);border-radius:var(--otto-radius-fare);background:var(--otto-fare-bg);color:var(--otto-on-fare);}.fareText{min-width:0;}.amount{font-size:var(--otto-text-2xl);font-weight:var(--otto-weight-semibold);}.fareName{font-size:var(--otto-text-base);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.fareFacts{font-size:var(--otto-text-md);opacity:0.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.tag{font-size:var(--otto-text-md);}.fareRow .btn.onFare{padding:9px 20px;background:var(--otto-on-fare);color:var(--otto-fare-bg);border-color:var(--otto-on-fare);}.fareRow .btn.onFare.chosen{padding:9px var(--otto-space-7);border-color:var(--otto-accent);}.opt.hasFares{cursor:pointer;}.opt.open{border-color:var(--otto-accent);}.fareList{margin-top:var(--otto-space-7);padding:var(--otto-space-7);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);background:var(--otto-card-bg);display:flex;flex-direction:column;gap:var(--otto-space-3);}.fareListHead{margin-bottom:var(--otto-space-1);font-size:var(--otto-text-md);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderRow{display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-3) var(--otto-space-3) var(--otto-space-3) var(--otto-space-6);border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);}.ladderRow.recommended{border-color:var(--otto-text-primary);}.ladderLabel{min-width:0;}.ladderName{font-size:var(--otto-text-base);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderFacts{font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.ladderRight{flex-shrink:0;display:flex;align-items:center;gap:var(--otto-space-5);}.ladderAmount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.ladderRow .btn{min-height:36px;padding:6px var(--otto-space-6);background:var(--otto-card-bg);border-color:var(--otto-text-primary);}.btn.chosen:not(.onFare){background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}#root.busy .opt.open:not(.chosen){border-color:var(--otto-accent);}#root.busy .opt.hasFares:hover .link{color:var(--otto-text-primary);}#root.busy .opt.hasFares:hover .linkText{text-decoration:none;}.strip button.link:disabled{cursor:default;opacity:0.45;}.btn.chosen:disabled{opacity:1;}";
13
+ const CSS = ":root{--otto-card-bg:#ffffff;--otto-card-border:#d4d4d4;--otto-btn-border:#525252;--otto-accent:#08c0cc;--otto-divider:#e5e5e5;--otto-strip-bg:#f5f5f5;--otto-fare-bg:#262624;--otto-on-fare:#ffffff;--otto-chip-bg:#ccfbf1;--otto-chip-text:#0a0a0a;--otto-text-primary:#0a0a0a;--otto-text-body:#0a0a0a;--otto-text-secondary:#737373;--otto-link-hover:#0369a1;--otto-banner-bg:#171717;--otto-on-banner:#ffffff;--otto-caution-bg:#fdf0dd;--otto-caution-text:#96590b;--otto-positive-text:#1c7a3e;--otto-photo-bg:#f5f5f5;--otto-font:Inter,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";--otto-line:1.5;--otto-text-xs:10px;--otto-text-sm:11px;--otto-text-md:12px;--otto-text-base:13px;--otto-text-lg:14px;--otto-text-xl:18px;--otto-text-2xl:19px;--otto-weight-regular:400;--otto-weight-medium:500;--otto-weight-semibold:600;--otto-space-1:2px;--otto-space-2:6px;--otto-space-3:8px;--otto-space-4:10px;--otto-space-5:12px;--otto-space-6:14px;--otto-space-7:16px;--otto-space-8:18px;--otto-radius-card:12px;--otto-radius-fare:10px;--otto-radius-md:8px;--otto-radius-pill:999px;--otto-card-width:304px;--otto-icon-size:14px;--otto-photo-height:170px;--otto-mark-size:24px;--otto-chip-height:24px;--otto-tap-min:44px;}@media (prefers-color-scheme:dark){:root:not([data-theme=\"light\"]){--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}}:root[data-theme=\"dark\"]{--otto-card-bg:#262624;--otto-card-border:#3d3d3a;--otto-btn-border:#a3a3a3;--otto-divider:#3d3d3a;--otto-strip-bg:#1c1c1b;--otto-fare-bg:#3d3d3a;--otto-text-primary:#ffffff;--otto-text-body:#f5f5f5;--otto-text-secondary:#a3a3a3;--otto-link-hover:#38bdf8;--otto-banner-bg:#3d3d3a;--otto-chip-bg:#0d3d3a;--otto-chip-text:#ccfbf1;--otto-caution-bg:#3b2a12;--otto-caution-text:#f5b65b;--otto-positive-text:#5fd08a;--otto-photo-bg:#1c1c1b;}html,body{margin:0;background:transparent;font-family:var(--otto-font);line-height:var(--otto-line);color:var(--otto-text-primary);}#root{min-height:120px;padding:0;}button{font:inherit;}.head{margin-bottom:var(--otto-space-5);}.title{font-size:var(--otto-text-lg);line-height:22px;font-weight:var(--otto-weight-semibold);}.subtitle,.empty{font-size:var(--otto-text-base);color:var(--otto-text-secondary);}.row{display:flex;gap:var(--otto-space-5);overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:var(--otto-space-2);}.opt{flex:0 0 var(--otto-card-width);width:var(--otto-card-width);min-width:0;overflow-wrap:anywhere;box-sizing:border-box;scroll-snap-align:start;display:flex;flex-direction:column;padding:var(--otto-space-7);background:var(--otto-card-bg);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);}.opt.chosen{border-color:var(--otto-accent);}@media (hover:hover){.opt:hover{border-color:var(--otto-accent);}}.chip{display:inline-flex;align-items:center;height:var(--otto-chip-height);padding:0 var(--otto-space-4);box-sizing:border-box;max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;border-radius:var(--otto-radius-pill);font-size:var(--otto-text-sm);font-weight:var(--otto-weight-semibold);background:var(--otto-chip-bg);color:var(--otto-chip-text);}.chip.caution{background:var(--otto-caution-bg);color:var(--otto-caution-text);}.btn{flex-shrink:0;min-height:41px;padding:9px var(--otto-space-7);box-sizing:border-box;white-space:nowrap;cursor:pointer;border-radius:var(--otto-radius-md);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);display:inline-flex;align-items:center;justify-content:center;gap:var(--otto-space-2);background:transparent;color:var(--otto-text-primary);border:1px solid var(--otto-btn-border);}.btn:disabled{cursor:default;opacity:0.45;}.why{margin-top:var(--otto-space-7);font-size:var(--otto-text-base);color:var(--otto-text-body);}.whyHead{font-weight:var(--otto-weight-semibold);}.whyLine{display:flex;gap:var(--otto-space-3);}.tick{--otto-icon-size:12px;height:19.5px;font-size:var(--otto-text-md);}.tick.note{color:var(--otto-text-secondary);}@media (max-width:480px){.opt{flex-basis:min(var(--otto-card-width),82vw);width:min(var(--otto-card-width),82vw);}.btn{min-height:var(--otto-tap-min);}}.carrier{display:flex;align-items:center;gap:var(--otto-space-3);min-height:var(--otto-chip-height);}.airline{flex:1;min-width:0;display:flex;align-items:center;gap:var(--otto-space-4);font-size:var(--otto-text-lg);font-weight:var(--otto-weight-medium);}.airlineName{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.chips{display:flex;gap:var(--otto-space-1);flex-shrink:0;}.mark{width:var(--otto-mark-size);height:var(--otto-mark-size);border-radius:50%;flex-shrink:0;display:grid;place-items:center;font-size:var(--otto-text-xs);font-weight:var(--otto-weight-semibold);letter-spacing:0.3px;color:#fff;background:#5b6470;}img.mark{object-fit:contain;background:transparent;border:0;padding:0;}.fltline{display:flex;justify-content:space-between;margin-top:var(--otto-space-8);font-size:var(--otto-text-md);color:var(--otto-text-body);}.times,.ports{display:flex;align-items:center;justify-content:space-between;}.times{margin-top:var(--otto-space-2);gap:var(--otto-space-3);}.ports{margin-top:var(--otto-space-1);font-size:var(--otto-text-lg);color:var(--otto-text-body);}.clock{font-size:var(--otto-text-xl);font-weight:var(--otto-weight-semibold);white-space:nowrap;}.plus{font-size:var(--otto-text-sm);vertical-align:super;color:var(--otto-caution-text);}.rule{flex:1;height:1px;background:var(--otto-divider);}.plane{color:var(--otto-text-secondary);}.fareBlock{margin-top:var(--otto-space-6);display:flex;flex-direction:column;}.strip{height:66px;box-sizing:border-box;display:flex;align-items:flex-start;justify-content:space-between;gap:var(--otto-space-3);padding:9px var(--otto-space-5) 0;border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);font-size:var(--otto-text-base);}.strip + .fareRow{margin-top:-27px;}.lowest{min-width:0;font-weight:var(--otto-weight-semibold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lowestName{font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.strip button.link{flex-shrink:0;display:inline-flex;gap:6px;height:auto;min-height:0;margin:0;padding:0;border:0;border-radius:0;box-shadow:none;background:none;appearance:none;cursor:pointer;align-items:center;font-size:var(--otto-text-base);line-height:var(--otto-line);color:var(--otto-text-primary);}@media (hover:hover){.opt.hasFares:hover .link{color:var(--otto-link-hover);}.opt.hasFares:hover .linkText{text-decoration:underline;}}.fareRow{position:relative;height:78px;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-2) var(--otto-space-5) var(--otto-space-2) var(--otto-space-6);border-radius:var(--otto-radius-fare);background:var(--otto-fare-bg);color:var(--otto-on-fare);}.fareText{min-width:0;}.amount{font-size:var(--otto-text-2xl);font-weight:var(--otto-weight-semibold);}.fareName{font-size:var(--otto-text-base);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.fareFacts{font-size:var(--otto-text-md);opacity:0.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.tag{font-size:var(--otto-text-md);}.fareRow .btn.onFare{padding:9px 20px;background:var(--otto-on-fare);color:var(--otto-fare-bg);border-color:var(--otto-on-fare);}.fareRow .btn.onFare.chosen{padding:9px var(--otto-space-7);border-color:var(--otto-accent);}.opt.hasFares{cursor:pointer;}.opt.open{border-color:var(--otto-accent);}.fareList{margin-top:var(--otto-space-7);padding:var(--otto-space-7);border:1px solid var(--otto-card-border);border-radius:var(--otto-radius-card);background:var(--otto-card-bg);display:flex;flex-direction:column;gap:var(--otto-space-3);}.fareListHead{margin-bottom:var(--otto-space-1);font-size:var(--otto-text-md);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderRow{display:flex;align-items:center;justify-content:space-between;gap:var(--otto-space-4);padding:var(--otto-space-3) var(--otto-space-3) var(--otto-space-3) var(--otto-space-6);border:1px solid var(--otto-divider);border-radius:var(--otto-radius-md);background:var(--otto-strip-bg);}.ladderRow.recommended{border-color:var(--otto-text-primary);}@media (hover:hover){.ladderRow:hover{border-color:var(--otto-accent);}}.ladderLabel{min-width:0;}.ladderName{font-size:var(--otto-text-base);font-weight:var(--otto-weight-semibold);color:var(--otto-text-primary);}.ladderFacts{font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.ladderRight{flex-shrink:0;display:flex;align-items:center;gap:var(--otto-space-5);}.ladderAmount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.ladderRow .btn{min-height:36px;padding:6px var(--otto-space-6);background:var(--otto-card-bg);border-color:var(--otto-text-primary);}.btn.chosen:not(.onFare){background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}#root.busy .opt.open:not(.chosen){border-color:var(--otto-accent);}#root.busy .opt.hasFares:hover .link{color:var(--otto-text-primary);}#root.busy .opt.hasFares:hover .linkText{text-decoration:none;}#root.busy .ladderRow:hover{border-color:var(--otto-divider);}#root.busy .ladderRow.recommended:hover{border-color:var(--otto-text-primary);}.strip button.link:disabled{cursor:default;opacity:0.45;}.btn.chosen:disabled{opacity:1;}";
14
14
  const SYMBOLS = { USD: "$", EUR: "€", GBP: "£", JPY: "¥", CNY: "¥", AUD: "A$", CAD: "C$" };
15
15
  // The widget cannot see when the host's reply ends, so the lock lifts on a timer.
16
16
  const BUSY_MS = 60000;
@@ -45,6 +45,30 @@
45
45
  const stops = (s) => (!s ? "" : s === 1 ? "1 stop" : `${s} stops`);
46
46
  const recommended = (option) => option.fares.find((f) => f.recommended) || option.fares[0];
47
47
  const allFares = () => card.items.flatMap((o) => o.fares || []);
48
+ const optionOf = (fare) => card.items.find((o) => (o.fares || []).includes(fare));
49
+
50
+ // Supplier text flattened to one short line, quotes out, before it becomes the traveler's message.
51
+ const oneLine = (value, max = 60) =>
52
+ String(value ?? "")
53
+ .replace(/["“”‘’`]/g, "'")
54
+ .replace(/[\s\u0000-\u001f]+/g, " ")
55
+ .trim()
56
+ .slice(0, max);
57
+
58
+ // The pick in words, then the id the model books with.
59
+ function bookMessage(option, fare) {
60
+ const carrier = [option.airline_name, option.flight_number].filter(Boolean).join(" ");
61
+ const route = option.origin && option.destination ? `${oneLine(option.origin, 5)}→${oneLine(option.destination, 5)}` : "";
62
+ const parts = [
63
+ oneLine(carrier),
64
+ route,
65
+ option.depart ? `departing ${oneLine(option.depart, 12)}` : "",
66
+ oneLine(fare.name),
67
+ oneLine(fare.refundable),
68
+ money(fare.price),
69
+ ].filter(Boolean);
70
+ return `Book flight ${parts.join(", ")} (flight_id ${fare.id})`;
71
+ }
48
72
 
49
73
  // Logo from the CDN; the code circle in the airline's color when it does not load.
50
74
  function mark(option) {
@@ -191,7 +215,7 @@
191
215
  draw();
192
216
  timer = setTimeout(unlock, BUSY_MS);
193
217
  try {
194
- const sent = window.sendPrompt(fare.select_prompt);
218
+ const sent = window.sendPrompt(bookMessage(optionOf(fare), fare));
195
219
  if (sent && typeof sent.catch === "function") sent.catch(unlock);
196
220
  } catch (error) {
197
221
  unlock();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottotheagent/mcp-card-assets",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Renderer, styles and airline logos for the Otto flight card that Claude draws in its widget sandbox.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [