@ottotheagent/mcp-card-assets 0.6.0 → 0.8.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
@@ -1,16 +1,16 @@
1
1
  # @ottotheagent/mcp-card-assets
2
2
 
3
- **Created**: 2026-10-02 | **Last Updated**: 2026-10-02
3
+ **Created**: 2026-10-02 | **Last Updated**: 2026-10-05
4
4
 
5
5
  Renderers, logos and photo placeholders for the Otto flight, hotel, room and car cards. Each `render_*` MCP tool returns card data and a snippet. The host's model mounts the card in its own widget sandbox, which loads files only from a few public CDNs, so the assets are served from jsDelivr.
6
6
 
7
7
  ## Contents
8
8
 
9
9
  - `flight-card.js`, `hotel-card.js`, `room-card.js` and `car-card.js` each draw one card and expose `OttoFlightCard`, `OttoHotelCard`, `OttoRoomCard` or `OttoCarCard` with `render(rootElement, card)`. Each carries its own CSS and only the icons it uses inline, so the sandbox loads one script per card. The server's snippet loads jsDelivr's minified copy (`*-card.min.js`).
10
- - Select (Show rooms on the hotel card) sends the pick as the traveler's message through the host's `sendPrompt()`: "Book flight …", "Show rooms at …", "Book room …" or "Book car …". The message carries no id.
10
+ - Select (Show rooms on the hotel card) sends the pick as the traveler's message through the host's `sendPrompt()`: "Book flight …", "Show rooms at …", "Select room …" or "Book car …". The message carries no id.
11
11
  - `*-card.css` holds each card's CSS as a separate file, for reference.
12
12
  - `marks/<IATA>.png` holds airline logos, and `marks/cars/<code>.svg` holds car-company logos.
13
- - `placeholders/hotel.svg`, `room.svg` and `car.svg` fill the photo plate, because host sandboxes block supplier photos.
13
+ - `placeholders/room.svg` and `car.svg` fill the photo plate, because host sandboxes block supplier photos. The hotel card has no photo plate: the host's own map shows the hotels with their photos. `hotel.svg` stays for renderers before 0.8.0.
14
14
 
15
15
  The sources are `src/flight-card.js`, and `src/core.js` plus `src/<kind>-card.js` for the hotel, room and car cards. `scripts/mcp/build_card_assets.py` writes the published files from them, from the card CSS in `server/mcp/apps/static/`, and from the logo tables. The generated files are not committed; `placeholders/` is.
16
16
 
package/hotel-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;}.icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--otto-icon-size);height:var(--otto-icon-size);line-height:1;}.icon svg{width:100%;height:100%;fill:currentColor;}.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);}}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}.btn.chosen:disabled{opacity:1;}#root{min-height:140px;}.opt{padding:0;overflow:hidden;}.body{display:flex;flex-direction:column;padding:var(--otto-space-7);}.photo{position:relative;height:var(--otto-photo-height);overflow:hidden;background:var(--otto-photo-bg);}.photo img{width:100%;height:100%;object-fit:cover;display:block;}.chips{position:absolute;top:var(--otto-space-4);left:var(--otto-space-4);right:var(--otto-space-4);display:flex;flex-wrap:wrap;gap:var(--otto-space-1);}.name{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);line-height:1.3;}.loyalty{display:flex;align-items:center;gap:var(--otto-space-2);margin-top:var(--otto-space-1);font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.loyalty svg{flex-shrink:0;}.stars{color:var(--otto-text-primary);--otto-icon-size:12px;}.fare{display:flex;align-items:center;gap:var(--otto-space-5);margin-top:var(--otto-space-7);}.fare .btn{flex:0 0 45%;}.fare>div{min-width:0;}.amount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.per,.total{font-size:var(--otto-text-md);font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.per{color:inherit;}.total{display:block;}.btn.chosen{background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}
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;}.icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--otto-icon-size);height:var(--otto-icon-size);line-height:1;}.icon svg{width:100%;height:100%;fill:currentColor;}.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);}}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}.btn.chosen:disabled{opacity:1;}#root{min-height:140px;}.opt{padding:0;overflow:hidden;}.body{display:flex;flex-direction:column;padding:var(--otto-space-7);}.chips{display:flex;flex-wrap:wrap;gap:var(--otto-space-1);margin-bottom:var(--otto-space-3);}.name{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);line-height:1.3;}.loyalty{display:flex;align-items:center;gap:var(--otto-space-2);margin-top:var(--otto-space-1);font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.loyalty svg{flex-shrink:0;}.stars{color:var(--otto-text-primary);--otto-icon-size:12px;}.fare{display:flex;align-items:center;gap:var(--otto-space-5);margin-top:var(--otto-space-7);}.fare .btn{flex:0 0 45%;}.fare>div{min-width:0;}.amount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.per,.total{font-size:var(--otto-text-md);font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.per{color:inherit;}.total{display:block;}.btn.chosen{background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}
package/hotel-card.js CHANGED
@@ -9,7 +9,7 @@
9
9
  * spec.message(item) is the text Select sends through the host's sendPrompt().
10
10
  * spec.empty is the line shown when the card has no items.
11
11
  */
12
- 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;}.icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--otto-icon-size);height:var(--otto-icon-size);line-height:1;}.icon svg{width:100%;height:100%;fill:currentColor;}.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);}}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}.btn.chosen:disabled{opacity:1;}#root{min-height:140px;}.opt{padding:0;overflow:hidden;}.body{display:flex;flex-direction:column;padding:var(--otto-space-7);}.photo{position:relative;height:var(--otto-photo-height);overflow:hidden;background:var(--otto-photo-bg);}.photo img{width:100%;height:100%;object-fit:cover;display:block;}.chips{position:absolute;top:var(--otto-space-4);left:var(--otto-space-4);right:var(--otto-space-4);display:flex;flex-wrap:wrap;gap:var(--otto-space-1);}.name{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);line-height:1.3;}.loyalty{display:flex;align-items:center;gap:var(--otto-space-2);margin-top:var(--otto-space-1);font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.loyalty svg{flex-shrink:0;}.stars{color:var(--otto-text-primary);--otto-icon-size:12px;}.fare{display:flex;align-items:center;gap:var(--otto-space-5);margin-top:var(--otto-space-7);}.fare .btn{flex:0 0 45%;}.fare>div{min-width:0;}.amount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.per,.total{font-size:var(--otto-text-md);font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.per{color:inherit;}.total{display:block;}.btn.chosen{background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}";
12
+ 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;}.icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--otto-icon-size);height:var(--otto-icon-size);line-height:1;}.icon svg{width:100%;height:100%;fill:currentColor;}.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);}}#root.busy .opt{cursor:default;}#root.busy .opt:not(.chosen):hover{border-color:var(--otto-card-border);}.btn.chosen:disabled{opacity:1;}#root{min-height:140px;}.opt{padding:0;overflow:hidden;}.body{display:flex;flex-direction:column;padding:var(--otto-space-7);}.chips{display:flex;flex-wrap:wrap;gap:var(--otto-space-1);margin-bottom:var(--otto-space-3);}.name{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);line-height:1.3;}.loyalty{display:flex;align-items:center;gap:var(--otto-space-2);margin-top:var(--otto-space-1);font-size:var(--otto-text-md);color:var(--otto-text-secondary);}.loyalty svg{flex-shrink:0;}.stars{color:var(--otto-text-primary);--otto-icon-size:12px;}.fare{display:flex;align-items:center;gap:var(--otto-space-5);margin-top:var(--otto-space-7);}.fare .btn{flex:0 0 45%;}.fare>div{min-width:0;}.amount{font-size:var(--otto-text-lg);font-weight:var(--otto-weight-semibold);}.per,.total{font-size:var(--otto-text-md);font-weight:var(--otto-weight-regular);color:var(--otto-text-secondary);}.per{color:inherit;}.total{display:block;}.btn.chosen{background:var(--otto-text-primary);color:var(--otto-card-bg);border-color:var(--otto-text-primary);}";
13
13
  const ICONS = {"hotels/check-regular-full":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 640\"><path d=\"M534 132.5C544.8 140.2 547.2 155.2 539.5 166L275.5 534C271.4 539.7 265 543.4 258 543.9C251 544.4 244 542 239 537L103 401C93.6 391.6 93.6 376.4 103 367.1C112.4 357.8 127.6 357.7 136.9 367.1L253 483L500.5 138C508.2 127.2 523.2 124.8 534 132.5z\"/></svg>","hotels/circle-info-regular-full":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 640\"><path d=\"M320 112C434.9 112 528 205.1 528 320C528 434.9 434.9 528 320 528C205.1 528 112 434.9 112 320C112 205.1 205.1 112 320 112zM320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM280 400C266.7 400 256 410.7 256 424C256 437.3 266.7 448 280 448L360 448C373.3 448 384 437.3 384 424C384 410.7 373.3 400 360 400L352 400L352 312C352 298.7 341.3 288 328 288L280 288C266.7 288 256 298.7 256 312C256 325.3 266.7 336 280 336L304 336L304 400L280 400zM320 256C337.7 256 352 241.7 352 224C352 206.3 337.7 192 320 192C302.3 192 288 206.3 288 224C288 241.7 302.3 256 320 256z\"/></svg>","hotels/coin-light-full":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 640\"><path d=\"M192 396.7C225.3 407.5 263.4 414.3 304 415.7L304 479.7C262.3 478.3 224.1 471.6 192 461.4L192 396.7zM96 341.7C112.2 358.2 134.1 372.6 160 384.3L160 449C157.7 447.9 155.5 446.9 153.3 445.8C110.4 424.3 96 400.6 96 383.9L96 341.7zM320 128C178.6 128 64 192.5 64 272L64 384C64 454.7 178.6 512 320 512C461.4 512 576 454.7 576 384L576 272C576 192.5 461.4 128 320 128zM480 384.4C505.9 372.7 527.8 358.2 544 341.8L544 384C544 400.7 529.6 424.4 486.7 445.9C484.5 447 482.3 448.1 480 449.1L480 384.4zM336 415.7C376.6 414.3 414.7 407.5 448 396.7L448 461.4C415.9 471.7 377.7 478.3 336 479.7L336 415.7zM96 272C96 210.1 196.3 160 320 160C443.7 160 544 210.1 544 272C544 333.9 443.7 384 320 384C196.3 384 96 333.9 96 272zM320 352C417.2 352 496 316.2 496 272C496 227.8 417.2 192 320 192C222.8 192 144 227.8 144 272C144 316.2 222.8 352 320 352zM184 272C184 245.5 244.9 224 320 224C395.1 224 456 245.5 456 272C456 298.5 395.1 320 320 320C244.9 320 184 298.5 184 272z\"/></svg>","hotels/star-solid-full":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 640\"><path d=\"M341.5 45.1C337.4 37.1 329.1 32 320.1 32C311.1 32 302.8 37.1 298.7 45.1L225.1 189.3L65.2 214.7C56.3 216.1 48.9 222.4 46.1 231C43.3 239.6 45.6 249 51.9 255.4L166.3 369.9L141.1 529.8C139.7 538.7 143.4 547.7 150.7 553C158 558.3 167.6 559.1 175.7 555L320.1 481.6L464.4 555C472.4 559.1 482.1 558.3 489.4 553C496.7 547.7 500.4 538.8 499 529.8L473.7 369.9L588.1 255.4C594.5 249 596.7 239.6 593.9 231C591.1 222.4 583.8 216.1 574.8 214.7L415 189.3L341.5 45.1z\"/></svg>"};
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.
@@ -165,7 +165,8 @@ function mount(root, card, spec) {
165
165
  }
166
166
 
167
167
  /* Otto hotel card: OttoHotelCard.render(root, card), card from render_hotels.
168
- * Show rooms sends "Show rooms at …" as the traveler's message. */
168
+ * Show rooms sends "Show rooms at …" as the traveler's message. No photo plate: the
169
+ * host's own map shows the hotels with their photos (see the render_elastic_hotels skill). */
169
170
 
170
171
  // Reasons first, then server facts; five lines keep the card short.
171
172
  const MAX_INSIGHTS = 5;
@@ -215,16 +216,13 @@ function render(root, card) {
215
216
 
216
217
  function option(item, ui) {
217
218
  const box = el("div", "opt" + (ui.chosen ? " chosen" : ""));
218
- const photo = el("div", "photo");
219
- photo.append(placeholder("hotel"));
219
+ const body = el("div", "body");
220
220
  const chipLabels = labels.get(item.id) || [];
221
221
  if (chipLabels.length) {
222
222
  const chips = el("div", "chips");
223
223
  for (const label of chipLabels) chips.append(el("span", "chip", label));
224
- photo.append(chips);
224
+ body.append(chips);
225
225
  }
226
-
227
- const body = el("div", "body");
228
226
  body.append(el("div", "name", item.name));
229
227
  if (item.star_rating) {
230
228
  const stars = el("div", "loyalty");
@@ -254,7 +252,7 @@ function render(root, card) {
254
252
  const insights = renderInsights([...(item.reasons || []), ...(item.facts || [])].slice(0, MAX_INSIGHTS));
255
253
  if (insights) body.append(insights);
256
254
 
257
- box.append(photo, body);
255
+ box.append(body);
258
256
  return box;
259
257
  }
260
258
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottotheagent/mcp-card-assets",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Renderers, styles, logos and photo placeholders for the Otto flight, hotel, room and car cards that Claude draws in its widget sandbox.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [
package/room-card.js CHANGED
@@ -165,7 +165,7 @@ function mount(root, card, spec) {
165
165
  }
166
166
 
167
167
  /* Otto room card: OttoRoomCard.render(root, card), card from render_hotel_rooms.
168
- * Select sends "Book room …" as the traveler's message. */
168
+ * Select sends "Select room …" as the traveler's message. */
169
169
 
170
170
  // Fact icon → [icon name, text fallback].
171
171
  const FACT_ICONS = {
@@ -236,7 +236,7 @@ function render(root, card) {
236
236
  mount(root, card, {
237
237
  empty: "No room options to show.",
238
238
  option,
239
- message: (item) => `Book room ${describe(item)}`,
239
+ message: (item) => `Select room ${describe(item)}`,
240
240
  });
241
241
  }
242
242