// Room layout canvas - Phase B.2.8b. const ROOM_LAYOUT_EMBEDDED_APP_SHELL = new URLSearchParams(window.location.search).get("embed") === "shell"; const ROOM_DND = { furnitureKind: "application/x-scrubstack-furniture-kind", furnitureId: "application/x-scrubstack-furniture-id", furnitureOffset: "application/x-scrubstack-furniture-offset", itemId: "application/x-scrubstack-item-id", }; const ROOM_FURNITURE = { anesthesia_station: { label: "Anesthesia", icon: "A", w: 0.28, h: 0.13, bg: "#E3E8DE", bd: "#8DA18D", fg: "#3F523F", fixedLabel: "Default widget" }, nurses_workstation: { label: "Nurses Station", icon: "NS", w: 0.28, h: 0.13, bg: "#E3E8DE", bd: "#7A8E7B", fg: "#3F523F", fixedLabel: "Default widget" }, or_bed: { label: "OR bed", icon: "BED", w: 0.30, h: 0.14, bg: "#E8EBEA", bd: "#6E6962", fg: "#3A3833", paletteNote: "Optional; record removal reason" }, boom: { label: "Boom", icon: "BM", w: 0.16, h: 0.16, bg: "#E7EFE9", bd: "#789B86", fg: "#3F523F", paletteNote: "Optional equipment target" }, back_table: { label: "Back table", icon: "BT", glyph: "table_wheels", w: 0.24, h: 0.11, bg: "#FAF7F2", bd: "#C7765A", fg: "#7A3F2A" }, mayo_stand: { label: "Mayo", icon: "M", glyph: "mayo_stand", w: 0.10, h: 0.10, bg: "#F1DDD2", bd: "#C7765A", fg: "#7A3F2A" }, equipment_cart: { label: "Equip cart", icon: "EC", glyph: "equipment_cart", w: 0.14, h: 0.11, bg: "#DCE2E6", bd: "#6B7A85", fg: "#3A4651", paletteNote: "Optional equipment target" }, bovie_tower: { label: "Bovie", icon: "B", glyph: "bovie_pencil", w: 0.10, h: 0.13, bg: "#F4E6CC", bd: "#D9A14A", fg: "#7A5615" }, suction_tower: { label: "Suction", icon: "S", glyph: "suction_canister", w: 0.10, h: 0.13, bg: "#EEE7DA", bd: "#9A8C66", fg: "#5F563F" }, c_arm: { label: "C-arm", icon: "C", glyph: "xray", w: 0.18, h: 0.16, bg: "#E2E2DA", bd: "#6E6962", fg: "#3A3833" }, prep_station: { label: "Prep", icon: "P", glyph: "prep_stick", w: 0.16, h: 0.11, bg: "#F1DDD2", bd: "#A05F47", fg: "#7A3F2A" }, custom: { label: "Custom", icon: "+", w: 0.13, h: 0.10, bg: "#FAF7F2", bd: "#ABA59C", fg: "#3A3833", paletteNote: "GUDID lookup" }, }; const ROOM_PALETTE = [ "or_bed", "boom", "back_table", "mayo_stand", "equipment_cart", "bovie_tower", "suction_tower", "c_arm", "prep_station", "custom", ]; const ROOM_DEFAULT_RULES = [ { id: "esu", label: "ESU", defaultLabel: "ESU assumed in room", reasonLabel: "Bovie pencil/tip listed", accessoryPattern: /\b(bovie|cautery|electrosurgical)\b.*\b(pencil|tip|cord|pad|blade)\b|\b(pencil|tip)\b.*\b(bovie|cautery|electrosurgical)\b/i, equipmentPattern: /\b(esu|electrosurgical unit|cautery generator|bovie generator|valleylab|force triad)\b/i, targetKinds: ["boom", "equipment_cart", "bovie_tower"], }, { id: "suction", label: "Suction", defaultLabel: "Suction assumed in room", reasonLabel: "Suction accessory listed", accessoryPattern: /\b(yankauer|poole|suction tubing|suction tip|suction canister|suction liner)\b/i, equipmentPattern: /\b(suction machine|suction pump|suction tower|suction regulator|wall suction)\b/i, targetKinds: ["boom", "equipment_cart", "suction_tower"], }, ]; const ROOM_STORAGE_PREFIX = "scrubstack-room-layout"; const ROOM_SEED = [ { furniture_kind: "anesthesia_station", zone_label: "anesthesia", position_x: 0.15, position_y: 0.30, rotation: 0, is_fixed: true, width_pct: 0.28, height_pct: 0.13, item_count: 0 }, { furniture_kind: "nurses_workstation", zone_label: "nurses-station", position_x: 0.85, position_y: 0.30, rotation: 0, is_fixed: true, width_pct: 0.28, height_pct: 0.13, item_count: 0 }, ]; function RoomLayoutView({ mobile = false, viewTabs = null }) { const cardId = window.PREFCARD_CONFIG?.cardId || 3; const compact = useRoomCompactLayout(mobile); const [cardSnapshot] = React.useState(window.PREFCARD); const [furniture, setFurniture] = React.useState(ROOM_SEED); const [items, setItems] = React.useState([]); const [assignments, setAssignments] = React.useState({}); const [selectedZone, setSelectedZone] = React.useState(null); const [loadState, setLoadState] = React.useState({ phase: "loading", message: "" }); const [saveState, setSaveState] = React.useState({ phase: "idle", message: "" }); const [toast, setToast] = React.useState(""); const [layoutSide, setLayoutSide] = React.useState(() => readRoomSetting(cardId, "side", "right") || "right"); const [layoutNotes, setLayoutNotes] = React.useState(() => readRoomSetting(cardId, "notes", { bedRemovalReason: "" }) || { bedRemovalReason: "" }); React.useEffect(() => { let alive = true; fetch(window.prefcardApiPath(`/api/cards/${cardId}/room-layout`), { credentials: "same-origin", headers: { "Accept": "application/json" }, }) .then((response) => { if (!response.ok) throw new Error(`HTTP ${response.status}`); return response.json(); }) .then((payload) => { if (!alive) return; applyRoomPayload(payload, setFurniture, setItems, setAssignments); setLoadState({ phase: "done", message: "" }); }) .catch((err) => { if (!alive) return; setItems(fallbackItems()); setLoadState({ phase: "error", message: err.message || "Room layout unavailable" }); }); return () => { alive = false; }; }, [cardId]); const selectedFurniture = React.useMemo( () => furniture.find((row) => row.zone_label === selectedZone) || null, [furniture, selectedZone] ); const itemCounts = React.useMemo(() => countAssignments(assignments), [assignments]); const assignedItems = selectedFurniture ? itemsForZone(items, assignments, selectedFurniture.zone_label) : []; const unassignedItems = React.useMemo( () => items.filter((item) => !assignments[String(item.id)]), [items, assignments] ); const detailOpen = Boolean(selectedFurniture); const bedPlaced = furniture.some((row) => row.furniture_kind === "or_bed"); const boomPlaced = furniture.some((row) => row.furniture_kind === "boom"); const cartPlaced = furniture.some((row) => row.furniture_kind === "equipment_cart"); const roomDefaults = React.useMemo(() => inferredRoomDefaults(items), [items]); const highlightItemId = new URLSearchParams(window.location.search).get("highlight_item"); React.useEffect(() => { writeRoomSetting(cardId, "side", layoutSide); }, [cardId, layoutSide]); React.useEffect(() => { writeRoomSetting(cardId, "notes", layoutNotes); }, [cardId, layoutNotes]); function addFurniture(kind, position) { const meta = ROOM_FURNITURE[kind]; const zoneLabel = nextZoneLabel(furniture, kind); const row = { furniture_kind: kind, zone_label: zoneLabel, position_x: position.x, position_y: position.y, rotation: 0, is_fixed: false, width_pct: meta.w, height_pct: meta.h, item_count: 0, }; setFurniture((prev) => [...prev, row]); setSelectedZone(zoneLabel); setSaveState({ phase: "idle", message: "" }); } function moveFurniture(zoneLabel, position) { setFurniture((prev) => prev.map((row) => row.zone_label === zoneLabel ? { ...row, position_x: position.x, position_y: position.y, } : row)); setSaveState({ phase: "idle", message: "" }); } function rotateFurniture(zoneLabel, delta) { setFurniture((prev) => prev.map((row) => row.zone_label === zoneLabel ? { ...row, rotation: (Number(row.rotation || 0) + delta + 360) % 360, } : row)); } function deleteFurniture(zoneLabel) { const row = furniture.find((candidate) => candidate.zone_label === zoneLabel); if (!row || row.is_fixed) return; setFurniture((prev) => prev.filter((candidate) => candidate.zone_label !== zoneLabel)); setAssignments((prev) => clearZone(prev, zoneLabel)); setSelectedZone(null); } function setBedRemovalReason(reason) { setLayoutNotes((prev) => ({ ...prev, bedRemovalReason: reason })); } function assignItem(itemId, zoneLabel) { setAssignments((prev) => ({ ...prev, [String(itemId)]: zoneLabel })); setSelectedZone(zoneLabel); setSaveState({ phase: "idle", message: "" }); } function removeItem(itemId) { setAssignments((prev) => ({ ...prev, [String(itemId)]: null })); setSaveState({ phase: "idle", message: "" }); } async function saveLayout() { setSaveState({ phase: "saving", message: "" }); try { const response = await fetch(window.prefcardApiPath(`/api/cards/${cardId}/room-layout`), { method: "PUT", credentials: "same-origin", headers: { "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify({ furniture: furniture.map((row) => ({ zone_label: row.zone_label, furniture_kind: row.furniture_kind, position_x: Number(row.position_x), position_y: Number(row.position_y), rotation: Number(row.rotation || 0), is_fixed: Boolean(row.is_fixed), width_pct: Number(row.width_pct), height_pct: Number(row.height_pct), })), item_zone_assignments: items.map((item) => ({ item_id: numericItemId(item.id), zone_label: assignments[String(item.id)] || null, })).filter((row) => Number.isFinite(row.item_id)), }), }); const payload = await response.json(); if (!response.ok) throw new Error(payload.detail || `HTTP ${response.status}`); applyRoomPayload(payload, setFurniture, setItems, setAssignments); setSaveState({ phase: "done", message: "" }); setToast("Layout saved"); setTimeout(() => setToast(""), 1400); } catch (err) { setSaveState({ phase: "error", message: err.message || "Save failed" }); } } return (
{!ROOM_LAYOUT_EMBEDDED_APP_SHELL && (mobile ? : )} {viewTabs} {saveState.phase === "error" && } {loadState.phase === "error" && }
{!mobile && ( )} setSelectedZone(null)} onRotate={rotateFurniture} onDelete={deleteFurniture} onRemoveItem={removeItem} onBedRemovalReasonChange={setBedRemovalReason} />
{toast &&
{toast}
}
); } function useRoomCompactLayout(mobile) { const [compact, setCompact] = React.useState(() => !mobile && window.innerWidth <= 980); React.useEffect(() => { if (mobile) { setCompact(false); return undefined; } const media = window.matchMedia("(max-width: 980px)"); const update = () => setCompact(media.matches); update(); media.addEventListener?.("change", update); window.addEventListener("resize", update); return () => { media.removeEventListener?.("change", update); window.removeEventListener("resize", update); }; }, [mobile]); return compact; } function RoomPageHeader({ card, mobile, loadState, saveState, onSave, side, onSideChange }) { return (
Room layout

{card.fullName || card.name || "Preference Card"}

{card.maintainer && (
{card.maintainer}
)}
{loadState.phase === "loading" ? "loading" : "live"} {!mobile && ( )}
Side {["left", "right"].map((value) => { const active = side === value; return ( ); })}
{mobile && view only}
); } function FurniturePalette({ bedPlaced, boomPlaced, cartPlaced, roomDefaults, highlightItemId, bedRemovalReason, onBedRemovalReasonChange, }) { return ( ); } function RoomOptionalSetup({ bedPlaced, boomPlaced, cartPlaced, roomDefaults, highlightItemId, reason, onReasonChange }) { return (
Optional targets
{!bedPlaced && ( onReasonChange(event.target.value)} placeholder="Reason: stretcher, inpatient bed..." style={roomInputStyle} /> )}
); } function OptionalTargetStatus({ label, placed }) { return (
{label} {placed ? "placed" : "not placed"}
); } function RoomCanvas({ furniture, itemCounts, mobile, selectedZone, onSelect, onAddFurniture, onMoveFurniture, onAssignItem }) { const canvasRef = React.useRef(null); function dropOnCanvas(event) { if (mobile) return; event.preventDefault(); const rect = canvasRef.current.getBoundingClientRect(); const kind = event.dataTransfer.getData(ROOM_DND.furnitureKind); const zoneLabel = event.dataTransfer.getData(ROOM_DND.furnitureId); const offset = parseOffset(event.dataTransfer.getData(ROOM_DND.furnitureOffset)); if (kind) { onAddFurniture(kind, pointFromEvent(event, rect)); return; } if (zoneLabel) { const row = furniture.find((candidate) => candidate.zone_label === zoneLabel); if (!row) return; const x = (event.clientX - rect.left - offset.x + (row.width_pct * rect.width) / 2) / rect.width; const y = (event.clientY - rect.top - offset.y + (row.height_pct * rect.height) / 2) / rect.height; onMoveFurniture(zoneLabel, { x: clamp01(x), y: clamp01(y) }); } } return (
!mobile && event.preventDefault()} onDrop={dropOnCanvas} style={{ position: "relative", width: mobile ? "100vw" : "min(100%, 1100px)", aspectRatio: "4 / 3", margin: mobile ? "0 calc(50% - 50vw)" : "0 auto", border: "1px solid var(--ss-line)", borderRadius: mobile ? 0 : 6, backgroundColor: "var(--ss-cream)", backgroundImage: "linear-gradient(rgba(122,142,123,0.11) 1px, transparent 1px), linear-gradient(90deg, rgba(122,142,123,0.11) 1px, transparent 1px)", backgroundSize: mobile ? "28px 28px" : "34px 34px", boxShadow: "var(--ss-shadow-card)", overflow: "hidden", }} > {furniture.map((row) => ( ))}
); } function FurniturePiece({ row, count, mobile, selected, onSelect, onAssignItem }) { const meta = ROOM_FURNITURE[row.furniture_kind] || ROOM_FURNITURE.custom; const title = furnitureTitle(row, meta); const subtitle = furnitureSubtitle(row, meta); return ( ); } function RoomRightPanel({ mobile, compact, selectedFurniture, assignedItems, unassignedItems, allItems, roomDefaults, highlightItemId, bedRemovalReason, onClose, onRotate, onDelete, onRemoveItem, onBedRemovalReasonChange, }) { const [collapsed, setCollapsed] = React.useState(false); if (selectedFurniture) { const meta = ROOM_FURNITURE[selectedFurniture.furniture_kind] || ROOM_FURNITURE.custom; const title = furnitureTitle(selectedFurniture, meta); const needsBedReason = selectedFurniture.furniture_kind === "or_bed"; const deleteDisabled = selectedFurniture.is_fixed; return ( ); } return ( ); } function RoomDetailControls({ selectedFurniture, meta, roomDefaults, bedRemovalReason, onBedRemovalReasonChange }) { const defaultsForZone = roomDefaultsForFurniture(roomDefaults, selectedFurniture.furniture_kind); if (selectedFurniture.furniture_kind === "boom" || selectedFurniture.furniture_kind === "equipment_cart") { return (
Equipment target
Drag supplies onto this widget to assign equipment here.
); } if (selectedFurniture.furniture_kind === "custom") { return (
GUDID lookup
); } if (selectedFurniture.furniture_kind === "or_bed") { return (
Removal reason
onBedRemovalReasonChange(event.target.value)} placeholder="Stretcher, inpatient bed, positioning access..." style={roomInputStyle} />
); } if (defaultsForZone.length) { return (
Room default
); } return null; } function RoomDefaultsList({ defaults, compact = false, highlightedSourceId = null }) { const rowRefs = React.useRef({}); const [activeHighlight, setActiveHighlight] = React.useState(Boolean(highlightedSourceId)); React.useEffect(() => { if (!highlightedSourceId) return undefined; setActiveHighlight(true); const node = rowRefs.current[String(highlightedSourceId)]; node?.scrollIntoView?.({ block: "center", behavior: "smooth" }); const timer = window.setTimeout(() => setActiveHighlight(false), 2200); return () => window.clearTimeout(timer); }, [highlightedSourceId]); if (!defaults || !defaults.length) return null; return (
{!compact &&
Room defaults
} {defaults.map((entry) => { const highlighted = highlightedSourceId && String(entry.sourceId) === String(highlightedSourceId) && activeHighlight; return (
{ if (entry.sourceId != null) rowRefs.current[String(entry.sourceId)] = node; }} style={{ display: "grid", gap: 2, padding: compact ? "7px 8px" : "8px 9px", borderRadius: 5, border: highlighted ? "2px solid #E1CC9E" : "1px solid #C9D8CC", background: highlighted ? "var(--ss-open-bg)" : "rgba(231,239,233,0.72)", boxShadow: highlighted ? "0 0 0 4px rgba(225,204,158,0.35)" : "none", transition: "box-shadow 180ms ease, background 180ms ease, border-color 180ms ease", }} > {entry.defaultLabel} {entry.reasonLabel}{entry.sourceName ? `: ${entry.sourceName}` : ""}
); })}
); } function SupplyDragRow({ item, mobile, assigned }) { return (
event.dataTransfer.setData(ROOM_DND.itemId, String(item.id))} style={{ padding: "9px 10px", border: "1px solid var(--ss-line-soft)", borderRadius: 6, background: assigned ? "var(--ss-cream)" : "var(--ss-warm-white)", cursor: mobile ? "default" : "grab", }} >
); } function SupplyRow({ item, actionLabel, onAction, mobile }) { return (
{!mobile && }
); } function SupplyText({ item }) { const qty = (item.qty_open ?? item.expected ?? 1) + (item.qty_hold ?? 0); return ( <>
{item.item_name || item.name || "Unnamed item"}
qty {qty} {item.section && {item.section}} {(item.vendor || item.mfg) && {item.vendor || item.mfg}}
); } function RoomMobileHeader({ card }) { const maintainer = card?.maintainer || "Maintainer"; return (
ScrubStack
Prefcards
); } function RoomKindIcon({ meta, small = false }) { return ( {meta.glyph ? : meta.icon} ); } function RoomFurnitureGlyph({ kind, color, small }) { if (kind === "table_wheels") { const stroke = color || "currentColor"; return ( ); } if (kind === "mayo_stand") { const stroke = color || "currentColor"; return ( ); } if (kind === "equipment_cart") { const stroke = color || "currentColor"; return ( ); } if (kind === "bovie_pencil") { const stroke = color || "currentColor"; return ( ); } if (kind === "suction_canister") { const stroke = color || "currentColor"; return ( ); } if (kind === "xray") { const stroke = color || "currentColor"; return ( ); } if (kind === "prep_stick") { const stroke = color || "currentColor"; return ( ); } return null; } function RoomBanner({ tone, message, onRetry }) { const error = tone === "error"; return (
{message} {onRetry && }
); } function EmptyPanel({ text }) { return
{text}
; } function applyRoomPayload(payload, setFurniture, setItems, setAssignments) { const rows = (payload.room_layout || []).map((row) => ({ ...row, is_fixed: Boolean(row.is_fixed), position_x: Number(row.position_x), position_y: Number(row.position_y), rotation: Number(row.rotation || 0), width_pct: Number(row.width_pct || ROOM_FURNITURE[row.furniture_kind]?.w || 0.12), height_pct: Number(row.height_pct || ROOM_FURNITURE[row.furniture_kind]?.h || 0.08), })); const flatItems = []; const nextAssignments = {}; for (const [zone, zoneItems] of Object.entries(payload.items_by_zone || {})) { for (const item of zoneItems || []) { if (!flatItems.some((existing) => String(existing.id) === String(item.id))) flatItems.push(item); if (zone !== "_unassigned") nextAssignments[String(item.id)] = zone; } } setFurniture(rows.length ? rows : ROOM_SEED); setItems(flatItems); setAssignments(nextAssignments); } function fallbackItems() { return (window.PREFCARD?.supplies || []).map((item, index) => ({ id: numericItemId(item.id) || index + 1, item_name: item.name, vendor: item.mfg, qty_open: item.expected || 1, qty_hold: 0, section: item.phase, })); } function countAssignments(assignments) { return Object.values(assignments).reduce((acc, zone) => { if (zone) acc[zone] = (acc[zone] || 0) + 1; return acc; }, {}); } function inferredRoomDefaults(items) { const searchableItems = items.map((item) => ({ id: item.id, name: item.item_name || item.name || item.raw_text || "Card item", text: itemSearchText(item), })); return ROOM_DEFAULT_RULES.flatMap((rule) => { const explicitEquipment = searchableItems.some((item) => rule.equipmentPattern.test(item.text)); if (explicitEquipment) return []; const source = searchableItems.find((item) => rule.accessoryPattern.test(item.text)); if (!source) return []; return [{ id: rule.id, sourceId: source.id, label: rule.label, defaultLabel: rule.defaultLabel, reasonLabel: rule.reasonLabel, sourceName: source.name, targetKinds: rule.targetKinds, }]; }); } function roomDefaultsForFurniture(roomDefaults, kind) { return (roomDefaults || []).filter((entry) => (entry.targetKinds || []).includes(kind)); } function itemSearchText(item) { return [ item.item_name, item.name, item.raw_text, item.vendor, item.mfg, item.section, ].filter(Boolean).join(" "); } function furnitureTitle(row, meta) { return meta.label; } function furnitureSubtitle(row, meta) { if (row.is_fixed && meta.fixedLabel) return meta.fixedLabel; if (row.furniture_kind === "boom") return "ESU / lap equipment"; if (row.furniture_kind === "equipment_cart") return "assigned supplies"; if (row.furniture_kind === "custom") return "GUDID lookup"; return row.zone_label; } function itemsForZone(items, assignments, zoneLabel) { return items.filter((item) => assignments[String(item.id)] === zoneLabel); } function clearZone(assignments, zoneLabel) { const next = { ...assignments }; for (const [id, zone] of Object.entries(next)) if (zone === zoneLabel) next[id] = null; return next; } function nextZoneLabel(furniture, kind) { const base = kind.replaceAll("_", "-"); const used = new Set(furniture.map((row) => row.zone_label)); let n = 1; while (used.has(`${base}-${n}`)) n += 1; return `${base}-${n}`; } function pointFromEvent(event, rect) { return { x: clamp01((event.clientX - rect.left) / rect.width), y: clamp01((event.clientY - rect.top) / rect.height), }; } function parseOffset(raw) { try { return JSON.parse(raw || "{}"); } catch (_) { return { x: 0, y: 0 }; } } function clamp01(value) { if (!Number.isFinite(value)) return 0.5; return Math.max(0, Math.min(1, value)); } function numericItemId(value) { if (typeof value === "number") return value; const match = String(value || "").match(/\d+/); return match ? Number(match[0]) : NaN; } function roomStorageKey(cardId, name) { return `${ROOM_STORAGE_PREFIX}:${cardId}:${name}`; } function readRoomSetting(cardId, name, fallback) { try { const raw = window.localStorage.getItem(roomStorageKey(cardId, name)); return raw ? JSON.parse(raw) : fallback; } catch (_) { return fallback; } } function writeRoomSetting(cardId, name, value) { try { window.localStorage.setItem(roomStorageKey(cardId, name), JSON.stringify(value)); } catch (_) { // Local prototype persistence is best-effort. } } function roomDrawerStyle(mobile) { if (mobile) { return { position: "fixed", left: 12, right: 12, bottom: 12, zIndex: 20, maxHeight: "72vh", overflow: "auto", }; } return { position: "fixed", top: 96, right: 24, zIndex: 20, width: 340, maxHeight: "calc(100vh - 120px)", overflow: "auto", }; } const roomPanelStyle = { background: "var(--ss-warm-white)", border: "1px solid var(--ss-line)", borderRadius: 6, boxShadow: "var(--ss-shadow-card)", padding: 14, }; const roomGhostButton = { padding: "6px 10px", borderRadius: 5, background: "transparent", border: "1px solid var(--ss-line)", color: "var(--ss-gray-900)", fontSize: 12, fontWeight: 500, cursor: "pointer", fontFamily: "var(--ss-sans)", }; const roomPrimaryButton = { padding: "7px 12px", borderRadius: 5, background: "var(--ss-ink)", border: "1px solid var(--ss-ink)", color: "var(--ss-cream)", fontSize: 12.5, fontWeight: 600, cursor: "pointer", fontFamily: "var(--ss-sans)", }; const roomDangerButton = { ...roomGhostButton, border: "1px solid #DAB5AC", color: "var(--ss-match-reject)", }; const roomInputStyle = { width: "100%", minWidth: 0, boxSizing: "border-box", border: "1px solid var(--ss-line)", borderRadius: 5, background: "var(--ss-cream)", color: "var(--ss-ink)", padding: "7px 9px", fontSize: 12.5, fontFamily: "var(--ss-sans)", }; const roomDetailSectionStyle = { marginTop: 14, display: "grid", gap: 8, paddingTop: 14, borderTop: "1px solid var(--ss-line-soft)", }; const roomToastStyle = { position: "fixed", right: 24, bottom: 24, zIndex: 30, padding: "10px 14px", borderRadius: 6, background: "var(--ss-match-verified-bg)", border: "1px solid #B9D0BE", color: "var(--ss-match-verified)", boxShadow: "var(--ss-shadow-pop)", fontSize: 13, fontWeight: 600, }; Object.assign(window, { RoomLayoutView });