diff options
Diffstat (limited to 'public')
-rw-r--r-- | public/common/client.js | 375 | ||||
-rw-r--r-- | public/common/grid.css | 302 | ||||
-rw-r--r-- | public/images/chat-bubble.svg | 1 | ||||
-rw-r--r-- | public/images/cog.svg | 1 | ||||
-rw-r--r-- | public/images/earth-africa-europe.svg | 1 | ||||
-rw-r--r-- | public/images/earth-america.svg | 1 | ||||
-rw-r--r-- | public/images/earth-asia-oceania.svg | 1 | ||||
-rw-r--r-- | public/images/scroll-quill.svg | 1 |
8 files changed, 683 insertions, 0 deletions
diff --git a/public/common/client.js b/public/common/client.js new file mode 100644 index 0000000..ea1c12b --- /dev/null +++ b/public/common/client.js @@ -0,0 +1,375 @@ +let socket = null; +let chat_is_visible = false; +let chat_text = null; +let chat_key = null; +let chat_last_day = null; +let chat_log = null; + +function scroll_with_middle_mouse(panel_sel, multiplier) { + let panel = document.querySelector(panel_sel); + let down_x, down_y, scroll_x, scroll_y; + if (!multiplier) + multiplier = 1; + function md(e) { + if (e.button === 1) { + down_x = e.clientX; + down_y = e.clientY; + scroll_x = panel.scrollLeft; + scroll_y = panel.scrollTop; + window.addEventListener('mousemove', mm); + window.addEventListener('mouseup', mu); + e.preventDefault(); + } + } + function mm(e) { + let dx = down_x - e.clientX; + let dy = down_y - e.clientY; + panel.scrollLeft = scroll_x + dx * multiplier; + panel.scrollTop = scroll_y + dy * multiplier; + e.preventDefault(); + } + function mu(e) { + if (e.button === 1) { + window.removeEventListener('mousemove', mm); + window.removeEventListener('mouseup', mu); + e.preventDefault(); + } + } + panel.addEventListener('mousedown', md); +} + +function drag_element_with_mouse(element_sel, grabber_sel) { + let element = document.querySelector(element_sel); + let grabber = document.querySelector(grabber_sel) || element; + let save_x, save_y; + function md(e) { + if (e.button === 0) { + save_x = e.clientX; + save_y = e.clientY; + window.addEventListener('mousemove', mm); + window.addEventListener('mouseup', mu); + e.preventDefault(); + } + } + function mm(e) { + let dx = save_x - e.clientX; + let dy = save_y - e.clientY; + save_x = e.clientX; + save_y = e.clientY; + element.style.left = (element.offsetLeft - dx) + "px"; + element.style.top = (element.offsetTop - dy) + "px"; + e.preventDefault(); + } + function mu(e) { + if (e.button === 0) { + window.removeEventListener('mousemove', mm); + window.removeEventListener('mouseup', mu); + e.preventDefault(); + } + } + grabber.addEventListener('mousedown', md); +} + +function add_chat_lines(log) { + function format_time(date) { + let mm = date.getMinutes(); + let hh = date.getHours(); + if (mm < 10) mm = "0" + mm; + if (hh < 10) hh = "0" + hh; + return hh + ":" + mm; + } + function add_date_line(date) { + let line = document.createElement("div"); + line.className = "date"; + line.textContent = "~ " + date + " ~"; + chat_text.appendChild(line); + } + function add_chat_line(time, user, message) { + let line = document.createElement("div"); + line.textContent = "[" + time + "] " + user + " \xbb " + message; + chat_text.appendChild(line); + chat_text.scrollTop = chat_text.scrollHeight; + } + for (let entry of log) { + chat_log.push(entry); + let [date, user, message] = entry; + date = new Date(date); + let day = date.toDateString(); + if (day != chat_last_day) { + add_date_line(day); + chat_last_day = day; + } + add_chat_line(format_time(date), user, message); + } +} + +function load_chat(game) { + chat_key = "chat/" + game; + chat_text = document.querySelector(".chat_text"); + chat_last_day = null; + chat_log = []; + let save = JSON.parse(window.localStorage.getItem(chat_key)); + if (save) { + if (Date.now() < save.expires) + add_chat_lines(save.chat); + else + window.localStorage.removeItem(chat_key); + } + return chat_log.length; +} + +function save_chat() { + const DAY = 86400000; + let save = { expires: Date.now() + 7 * DAY, chat: chat_log }; + window.localStorage.setItem(chat_key, JSON.stringify(save)); +} + +function update_chat(log_start, log) { + if (log_start == 0) { + chat_last_day = null; + chat_log = []; + while (chat_text.firstChild) + chat_text.removeChild(chat_text.firstChild); + } + add_chat_lines(log); +} + +function init_client(roles) { + let params = new URLSearchParams(window.location.search); + let title = window.location.pathname.split("/")[1]; + let game = params.get("game"); + let role = params.get("role"); + let player = null; + + const ROLE_SEL = [ + ".role.one", + ".role.two", + ".role.three", + ".role.four", + ".role.five", + ".role.six", + ".role.seven", + ]; + + const USER_SEL = [ + ".role.one .role_user", + ".role.two .role_user", + ".role.three .role_user", + ".role.four .role_user", + ".role.five .role_user", + ".role.six .role_user", + ".role.seven .role_user", + ]; + + load_chat(game); + + console.log("JOINING game", game, "role", role); + + socket = io({ + transports: ['websocket'], + query: { title: title, game: game, role: role }, + }); + + socket.on('connect', () => { + console.log("CONNECTED"); + document.querySelector(".grid_top").classList.remove('disconnected'); + socket.emit('getchat', chat_log.length); // only send new messages when we reconnect! + }); + + socket.on('disconnect', () => { + console.log("DISCONNECTED"); + document.getElementById("prompt").textContent = "Disconnected from server!"; + document.querySelector(".grid_top").classList.add('disconnected'); + }); + + socket.on('roles', (me, players) => { + console.log("ROLES", me, JSON.stringify(players)); + player = me; + if (player == "Observer") + document.querySelector(".chat_button").style.display = "none"; + document.querySelector(".grid_top").classList.add(player); + for (let i = 0; i < roles.length; ++i) { + let p = players.find(p => p.role == roles[i]); + document.querySelector(USER_SEL[i]).textContent = p ? p.name : "NONE"; + } + }); + + socket.on('presence', (presence) => { + console.log("PRESENCE", presence); + for (let i = 0; i < roles.length; ++i) { + let elt = document.querySelector(ROLE_SEL[i]); + if (roles[i] in presence) + elt.classList.add('present'); + else + elt.classList.remove('present'); + } + }); + + socket.on('state', (state) => { + console.log("STATE"); + on_update_log(state); + on_update_bar(state, player); + on_update(state, player); + }); + + socket.on('save', (msg) => { + console.log("SAVE"); + window.localStorage[title + '/save'] = msg; + }); + + socket.on('error', (msg) => { + console.log("ERROR", msg); + document.getElementById("prompt").textContent = msg; + }); + + socket.on('chat', function (log_start, log) { + console.log("CHAT UPDATE", log_start, log.length); + update_chat(log_start, log); + let button = document.querySelector(".chat_button"); + if (!chat_is_visible) + button.classList.add("new"); + else + save_chat(); + }); + + document.querySelector(".chat_form").addEventListener("submit", e => { + let input = document.querySelector("#chat_input"); + e.preventDefault(); + if (input.value) { + socket.emit('chat', input.value); + input.value = ''; + } else { + hide_chat(); + } + }); + + document.querySelector("body").addEventListener("keydown", e => { + if (player && player != "Observer") { + if (e.key == "Escape") { + if (chat_is_visible) { + e.preventDefault(); + hide_chat(); + } + } + if (e.key == "Enter") { + let input = document.querySelector("#chat_input"); + if (document.activeElement != input) { + e.preventDefault(); + show_chat(); + } + } + } + }); + + drag_element_with_mouse(".chat_window", ".chat_header"); +} + +function on_update_bar(state, player) { + document.getElementById("prompt").textContent = state.prompt; + if (state.actions) + document.querySelector(".grid_top").classList.add("your_turn"); + else + document.querySelector(".grid_top").classList.remove("your_turn"); +} + +function on_update_log(state) { + let parent = document.getElementById("log"); + let to_delete = parent.children.length - state.log_start; + while (to_delete > 0) { + parent.removeChild(parent.firstChild); + --to_delete; + } + for (let entry of state.log) { + let p = document.createElement("div"); + p.textContent = entry; + parent.prepend(p); + } +} + +function toggle_fullscreen() { + if (document.fullscreen) + document.exitFullscreen(); + else + document.documentElement.requestFullscreen(); +} + +function show_chat() { + if (!chat_is_visible) { + document.querySelector(".chat_button").classList.remove("new"); + document.querySelector(".chat_window").classList.add("show"); + document.querySelector("#chat_input").focus(); + chat_is_visible = true; + save_chat(); + } +} + +function hide_chat() { + if (chat_is_visible) { + document.querySelector(".chat_window").classList.remove("show"); + document.querySelector("#chat_input").blur(); + chat_is_visible = false; + } +} + +function toggle_chat() { + if (chat_is_visible) + hide_chat(); + else + show_chat(); +} + +function toggle_log() { + document.querySelector(".grid_window").classList.toggle("hide_log"); +} + +function show_action_button(sel, action, use_label = false) { + let button = document.querySelector(sel); + if (game.actions && action in game.actions) { + button.classList.remove("hide"); + if (game.actions[action]) { + if (use_label) + button.textContent = game.actions[action]; + button.disabled = false; + } else { + button.disabled = true; + } + } else { + button.classList.add("hide"); + } +} + +function confirm_resign() { + if (window.confirm("Are you sure that you want to resign?")) + socket.emit('resign'); +} + +function send_action(verb, noun) { + // Reset action list here so we don't send more than one action per server prompt! + if (noun) { + if (game.actions && game.actions[verb] && game.actions[verb].includes(noun)) { + game.actions = null; + console.log("SEND ACTION", verb, noun); + socket.emit('action', verb, noun); + } + } else { + if (game.actions && game.actions[verb]) { + game.actions = null; + console.log("SEND ACTION", verb, noun); + socket.emit('action', verb); + } + } +} + +function send_save() { + socket.emit('save'); +} + +function send_restore() { + let title = window.location.pathname.split("/")[1]; + let save = window.localStorage[title + '/save']; + socket.emit('restore', window.localStorage[title + '/save']); +} + +function send_restart(scenario) { + socket.emit('restart', scenario); +} diff --git a/public/common/grid.css b/public/common/grid.css new file mode 100644 index 0000000..95a2ee4 --- /dev/null +++ b/public/common/grid.css @@ -0,0 +1,302 @@ +/* COMMON GRID LAYOUT */ + +html, button, input, select { + font-family: "Source Sans", "Circled Numbers", "Dingbats", "Noto Emoji", "Verdana", sans-serif; + font-size: 16px; +} + +.chat_text, #chat_input { + font-family: "Source Serif", "Circled Numbers", "Dingbats", "Noto Emoji", "Georgia", serif; +} + +.log { + font-family: "Source Serif SmText", "Circled Numbers", "Dingbats", "Noto Emoji", "Georgia", serif; +} + +html, body, div { + margin: 0; + padding: 0; +} + +.status { + position:absolute; + z-index: 100; + left: 0; + bottom: 0; + background-color: white; + padding: 0 1ex; +} + +.grid_window { + display: grid; + grid-template-columns: 1fr min-content; + grid-template-rows: min-content min-content 1fr; + gap: 0px; + width: 100vw; + height: 100vh; +} + +.grid_window.hide_log .grid_role { + display: none; +} +.grid_window.hide_log .grid_log { + display: none; +} + +.grid_center { + grid-column: 1; + grid-row: 2/4; + overflow: auto; + scrollbar-width: none; +} + +.grid_role { + grid-column: 2; + grid-row: 2; + border-left: 1px solid black; + overflow-y: clip; + width: 209px; +} + +.role_vp { + padding-top: 3px; + padding-right: 5px; + padding-left: 3px; + float: right; +} + +.role_name { + padding-top: 3px; + padding-bottom: 3px; + padding-left: 25px; + text-indent: -20px; + border-bottom: 1px solid black; +} + +.role .role_name::before { content: "\25cb "; opacity: 0.6; } +.role.present .role_name::before { content: "\25cf "; opacity: 0.6; } + +.role_info { + border-bottom: 1px solid black; +} + +.grid_log { + grid-column: 2; + grid-row: 3; + border-left: 1px solid black; + overflow-y: scroll; + scrollbar-width: thin; +} + +.log { + padding-left: 20px; + padding-top: 8px; + padding-right: 8px; + text-indent: -12px; + font-size: 12px; + line-height: 18px; + white-space: pre-wrap; +} + +.log > * { + min-height: 9px; +} + +.grid_top { + grid-column: 1/3; + grid-row: 1; + display: flex; + align-items: center; + border-bottom: 1px solid black; +} + +.grid_top.disconnected { + background-color: red; +} + +.menu { + user-select: none; +} +.menu_title img { + display: block; + height: 35px; + padding: 5px; +} +.menu:hover .menu_title { + background-color: black; + color: white; +} +.menu:hover .menu_title img { + filter: invert(100%); +} +.menu_popup { + display: none; + position: absolute; + min-width: 20ex; + white-space: nowrap; + border: 1px solid black; + background-color: white; + z-index: 100; +} +.menu:hover .menu_popup { + display: block; +} +.menu_separator { + border-top: 1px solid black; +} +.menu_item { + padding: 5px 10px; +} +.menu_item:hover { + background-color: black; + color: white; +} + +.image_button { + user-select: none; +} +.image_button img { + display: block; + height: 35px; + padding: 5px; +} +.image_button:hover { + background-color: black; + color: white; +} +.image_button:hover img { + filter: invert(100%); +} + +.grid_top button { + margin: 0 10px; +} +.grid_top button.hide { + display: none; +} + +.prompt { + margin: 0 50px; + font-size: large; + flex-grow: 1; +} + +.hand { + margin: 15px; + display: flex; + flex-wrap: wrap; + justify-content: center; + min-height: 370px; +} + +.card { + margin: 10px; + background-size: cover; + background-repeat: no-repeat; + transition: 100ms; + box-shadow: 1px 1px 5px rgba(0,0,0,0.5); + display: none; +} +.card.show { + display: block; +} +.card.enabled { + cursor: pointer; +} +.card.enabled:hover { + transform: scale(1.1); +} +.card.disabled { + filter: grayscale(100%); +} + +.small_card { + margin: 15px; + background-size: cover; + background-repeat: no-repeat; + transition: 100ms; + box-shadow: 1px 1px 5px rgba(0,0,0,0.5); +} +.one .small_card:hover { + transform: scale(2.0) translate(0,35px); +} +.two .small_card:hover { + transform: scale(2.0) translate(0,-35px); +} + +.map { + margin: 0 auto; + box-shadow: 0px 1px 10px rgba(0,0,0,0.5); +} + +button { + font-size: 1rem; + margin: 0; + padding: 1px 12px; + background-color: gainsboro; +} +button:disabled { + color: gray; + border: 2px solid gainsboro; + outline: 1px solid gray; +} +button:enabled { + border: 2px outset white; + outline: 1px solid black; +} +button:enabled:active:hover { + border: 2px inset white; + padding: 2px 11px 0px 13px; +} + +/* CHAT WINDOW */ + +.chat_button.new { + filter: invert(100%); +} +.chat_window { + position: absolute; + left: 10px; + top: 55px; + width: 40rem; + z-index: 60; + border: 1px solid black; + background-color: white; + box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.5); + visibility: hidden; + display: grid; + grid-template-rows: min-content 1fr min-content; +} +.chat_window.show { + visibility: visible; +} +.chat_header { + cursor: move; + background-color: gainsboro; + border-bottom: 1px solid black; + padding: 5px 10px; +} +.chat_text { + font-size: 16px; + line-height: 24px; + height: 216px; + padding: 0px 5px; + overflow-y: scroll; +} +.chat_text .date { + font-weight: bold; +} +.chat_form { + display: block; + margin: 0; + padding: 0; + border-top: 1px solid black; +} +#chat_input { + box-sizing: border-box; + width: 100%; + outline: none; + border: none; + padding: 5px; + font-size: 1rem; +} diff --git a/public/images/chat-bubble.svg b/public/images/chat-bubble.svg new file mode 100644 index 0000000..1aa4ae9 --- /dev/null +++ b/public/images/chat-bubble.svg @@ -0,0 +1 @@ +<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M229.7 22.66A155.2 235.6 80.24 0 0 23.81 215.6 155.2 235.6 80.24 0 0 236.7 333.4c23.8 55.6-17.1 109.3-83.6 161.1 86.2-28.3 176.2-94.4 179.7-178.7a155.2 235.6 80.24 0 0 155.4-180.1A155.2 235.6 80.24 0 0 229.7 22.66z" fill="#000" fill-opacity="1"></path></g></svg>
\ No newline at end of file diff --git a/public/images/cog.svg b/public/images/cog.svg new file mode 100644 index 0000000..6e44bd2 --- /dev/null +++ b/public/images/cog.svg @@ -0,0 +1 @@ +<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M234.875 18.78c-26.087 2.367-51.557 8.56-74.875 18.782 15.37 32.763 14.222 66.706-6.72 82.407-20.835 15.617-54.055 7.965-81.124-15.69-16.246 19.452-29.336 41.36-38.875 65.626 33.83 12.333 56.635 37.665 52.94 63.5-3.698 25.835-32.697 43.74-68.626 46.094 2.338 25.796 8.91 50.778 18.937 73.875 17.81-8.182 35.793-11.09 51.095-8.938 13.032 1.87 23.927 7.015 31.156 16.657 15.817 21.097 7.603 54.713-16.78 81.97 19.516 16.35 42.216 29.444 66.594 39.03 12.33-33.828 37.655-56.634 63.5-52.938 25.844 3.697 43.74 32.696 46.094 68.625 26.087-2.365 51.557-8.555 74.875-18.78-15.766-32.997-14.26-67.588 6.843-83.406 9.64-7.23 22.568-9.022 35.594-7.125 15.112 2.16 31.19 10.25 45.563 22.78 16.088-19.345 29.4-41.51 38.875-65.594-33.83-12.332-56.635-37.653-52.938-63.5 3.697-25.846 32.665-43.772 68.594-46.125-2.36-25.944-8.774-50.663-18.906-73.874-32.612 15.117-66.66 13.145-82.282-7.687-15.696-20.944-7.252-53.86 16.688-81-19.52-16.352-42.248-29.447-66.625-39.032-12.332 33.828-37.657 56.66-63.5 52.968-25.846-3.693-43.744-32.696-46.095-68.625zm21.656 95.126c79.626 0 144.376 64.752 144.376 144.375 0 79.626-64.75 144.376-144.375 144.376-79.624 0-144.374-64.75-144.374-144.375 0-79.624 64.75-144.374 144.375-144.374zm0 18.688c-69.524 0-125.686 56.162-125.686 125.687 0 69.526 56.162 125.69 125.687 125.69 69.526 0 125.69-56.164 125.69-125.69 0-69.522-56.164-125.686-125.69-125.686zm.033 15.125c61.094 0 110.625 49.53 110.625 110.624 0 61.095-49.53 110.625-110.625 110.625s-110.625-49.53-110.625-110.626c0-61.095 49.53-110.625 110.625-110.625z" fill="#000" fill-opacity="1"></path></g></svg>
\ No newline at end of file diff --git a/public/images/earth-africa-europe.svg b/public/images/earth-africa-europe.svg new file mode 100644 index 0000000..39a4868 --- /dev/null +++ b/public/images/earth-africa-europe.svg @@ -0,0 +1 @@ +<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M256 32A224 224 0 0 0 32 256a224 224 0 0 0 224 224 224 224 0 0 0 223.672-217.45c-15.468 4.148-.306.22-16.467 4.51-9.1-2.965-28.42 10.264-29.197 10.264-1.756 0-14.65-49.66-14.65-49.66L381.08 208H368l-1.316 6.32 30.2 28.444-47.76 20.718-35.466-49.162-5.24 2.328 11.21 36.3 42.84 23.177-42.84 50.568 1.403 35.82-31.276 67.182-52.168-6.716-16-88.843-3.094-33.43-71.517-3.838-9.258-60.77 32.314-35.827 54.782-6.32 40.034 21.772 36.93-9.72c-1.112-18.374.05-12.54-1.112-18.374l-19.666-.7-1.053-10.184-5.97-2.107-2.81 12.64-9.48-.526-11.94-26.514-8.43 2.81 10.185 22.475-9.13 3.16-13.694-20.718-8.428-1.406-21.773 2.81-18.26 23.177-18.613 1.406-1.405-34.064 24.23-1.757 2.108-10.184-5.795-5.618-.174-3.69 16.182-7.94 11.56-2.944 19.665-6.848 6.32-7.375 3.512 7.375 22.474 2.81 8.78-9.13 5.97-24.582-6.673-2.81-11.238 16.857-8.43-9.834-11.586 14.75-14.4 2.458-.7-10.184 11.236-23.88 31.606-13.694 43.894-3.16 3.864 13.344s-4.916 13.344-5.97 13.695c-.138.045.428 1.754 1.464 4.565h31.195l14.047-11.59 29.484-9.138A224 224 0 0 0 256 32zM145.098 69.465l6.144 1.053s1.756 8.076.352 10.007c-1.405 1.932-10.885 7.903-10.885 7.903l-6.148-12.115 10.536-6.848zm41.086 11.588l8.252 19.49 3.337 16.68s-11.588 5.793-12.466 6.496c-.878.7-6.147-8.077-6.147-8.077l-1.93-17.91 2.81-15.1 6.144-1.58zm-12.116 22.474v16.155l-10.007 3.86-2.107-7.724 12.115-12.29zm189.104 238.618l-7.365 61.798-16.164 3.166s4.868-50.492 7.326-53.3l16.202-11.665z" fill="#000" fill-opacity="1"></path></g></svg>
\ No newline at end of file diff --git a/public/images/earth-america.svg b/public/images/earth-america.svg new file mode 100644 index 0000000..56b30dc --- /dev/null +++ b/public/images/earth-america.svg @@ -0,0 +1 @@ +<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M256 32c-37.764.086-74.894 9.72-107.938 28.002l27.52 19.36 40.033-13.694 24.582 5.62 8.78 49.864 15.1-11.588 41.087-14.046 18.26 27.742-35.82 18.963-22.473 16.152-2.458 22.475-24.932 21.07-7.023 34.064-14.047 1.053 7.023-38.63-53.027-2.807-12.64 18.61-.1-.01v26.644l25.824 1.986 23.838 16.885-1.986 25.328 33.77 5.96-.36.76 53.004-30.558 90.88 59.098-20.51 48.548-32.685 20.156-61.143 77.965-13.498-3.845L262.216 365l-42.213-42.213 7.853-13.86-25.732-9.482-25.326-30.79-21.853-4.967L116.422 208H112l-5.117 26.746-3.64-39.146 5.267-29.147-.7-23.178L97.247 98.2C55.516 140.12 32.06 196.847 32 256c0 123.712 100.288 224 224 224 82.413-.028 158.155-45.308 197.195-117.887L442.82 298.14l-5.62-36.17-34.06-27.392 6.67-37.926 15.803-20.367 37.555-5.05C428.766 87.086 346.913 32.072 256 32zm89.047 48H368v48l-32 16v-23.836zm-122.76 166.518l29.85 4.918-4.213 6.32-24.23-4.916z" fill="#000" fill-opacity="1"></path></g></svg>
\ No newline at end of file diff --git a/public/images/earth-asia-oceania.svg b/public/images/earth-asia-oceania.svg new file mode 100644 index 0000000..dd9e6fb --- /dev/null +++ b/public/images/earth-asia-oceania.svg @@ -0,0 +1 @@ +<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M256 32A224 224 0 0 0 99.596 95.68l11.12-2.66 38.24-13.41 44.198-8.44 17.383 17.38 27.81-15.892 32.778.498 5.96 7.946 48.17-10.43 73.005 22.35-33.77 13.904 8.442 34.763-16.885 10.925-10.43-52.144-22.844 1.987-3.476 25.824-23.838 9.933 2.48 33.77-14.897 2.484-10.926-19.37-5.463 15.397 12.416 22.844-39.73 40.725-3.973 12.414 6.457 17.878s-15.892 23.343-18.375 22.846c-2.484-.495-44.698-37.743-44.698-37.743l-26.32 15.395-20.86-31.288-18.375 1.49-24.83 69.032-17.88 4.967-38.454-52.088A224 224 0 0 0 256 480a224 224 0 0 0 224-224A224 224 0 0 0 256 32zm75.217 112.67l9.93 15.394-14.897 22.348-2.484 15.893-7.946-4.967h1.49l4.47-42.213 9.437-6.455zm-18.873 56.117l11.422 1.49-.993 11.422-29.796 5.462-.995-7.945 20.362-10.43zm-39.233 26.818l14.9 4.47-2.483 21.355-17.382-12.416 4.966-13.41zm-9.434 45.69l2.482 18.87H245.3l-.993-13.407 19.37-5.463zm39.728 3.476l33.772 8.94 16.885 20.858-45.193-11.918-11.918 4.965-19.866-21.85 26.32-.994zM198.12 289.685l27.316 8.443 33.77 17.38s-20.86 4.47-23.84 3.477c-2.98-.993-43.702-19.37-43.702-19.37l6.457-9.93zm116.21 10.43l10.43 24.83 22.347 13.906-4.966 34.763-25.326 23.342-26.322-21.355-27.314 8.94-19.367 13.903L230.9 369.64s8.442-26.82 10.428-27.812l19.37-5.96 8.443-19.366 7.448 12.912 25.326-6.457 12.416-22.844zm86.91 49.66l4.965 2.484-10.926 15.396-3.475-8.94 9.435-8.94zm-11.422 19.867s6.456 4.47 4.47 5.96c-1.987 1.49-27.81 19.367-27.81 19.367l-10.927-5.463 23.343-17.38 10.925-2.483zm-82.44 32.28l12.415.498-10.428 9.932-1.988-10.43z" fill="#000" fill-opacity="1"></path></g></svg>
\ No newline at end of file diff --git a/public/images/scroll-quill.svg b/public/images/scroll-quill.svg new file mode 100644 index 0000000..19891eb --- /dev/null +++ b/public/images/scroll-quill.svg @@ -0,0 +1 @@ +<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M311.9 47.95c-17.6 0-34.6.7-50.7 2.43L244.6 93.5l-4.9-40.04c-2.5.46-5 .94-7.5 1.47-9.1 1.94-15.1 7.22-20.3 14.87-5.2 7.65-8.9 17.5-12.1 26.6C191 121.5 184 148 178.4 175c6 5.1 12 10.3 17.9 15.4l30.7-17.6 33.8 26.1 51.9-19.7 61 24.5-6.8 16.7-54.4-21.8-54.7 20.7-32.2-24.9-14.9 8.5c19.6 17.3 38.6 34.4 56.5 51.2l14-6.4 33.9 16.1 31.2-13.1 24.2 23.3-12.4 13-15.8-15.1-27.6 11.7-33-15.8c6.9 6.7 13.6 13.2 20.1 19.7l1.7 1.8 19.5 76.3-7.8-5.7-53 .4-38.1-17.8-42.4 14.6-5.8-17 49.2-17 41.1 19.2 24.7-.2-70.7-51.7c-19.7 4.6-39.4 2.8-58.1-3.7-4.2 44.4-5.9 85.7-7 118.7-.4 10.7 2.7 23 7.5 32.5 4.9 9.5 11.7 15.4 15 16.1 5.2 1.2 19 3.2 37.7 5.1l12.4-39 19.1 41.7c16.7 1.2 35 2 53.5 2.2 28.2.3 57.1-.9 82-4.7 15.8-2.3 29.6-6 40.7-10.4-11.8-5.1-21.6-10.6-29.1-16.6-11.1-8.9-18.2-19.3-17.3-30.9v.2c5.4-96.4 10.8-188.8 30.3-286l.1-.4.1-.4c5.3-17.9 17.9-39.86 36.1-55.83-13.9-2.06-28.6-4-43.7-5.66l-22.3 25.3-2.2-27.7c-19-1.64-38.4-2.71-57.4-2.92h-5.7zm148.5 20.44c-4.7 3.69-9.2 8.03-13.3 12.73 12.1 8.18 21.4 23.38 21.8 36.98.3 7.8-1.9 14.9-7.7 21.4-5.8 6.4-15.6 12.4-31.6 15.8l3.8 17.6c18.6-4 32.3-11.5 41.2-21.4 9-9.9 12.7-22.2 12.3-34-.6-19.3-11.1-37.59-26.5-49.11zM25.44 71.91c-.24 1.61-.38 3.43-.38 5.62.1 7.69 2.03 18.17 5.83 30.17 3.41 10.7 8.27 22.5 14.35 34.8 10.63-5.3 20.59-11 28.41-18.1-4.42 12.5-10.15 24.7-18.6 36.5 4.14 7.2 8.63 14.4 13.45 21.5 10.64-5.3 20.72-13 29.52-26.1-3.3 16-8.47 30.6-18.27 41.8 6.53 8.5 13.5 16.8 20.75 24.5 8.7-9.3 15.6-21 20.7-34.9 3.8 18.5 2.6 35.3-5.7 49.4 8 7.2 16.3 13.7 24.8 19.1 6.1-14 8.9-30.6 8.5-49.7 9.2 23.7 11.3 42.9 9.6 59.5 20.2 9.2 40.8 12 61.3 6.1l4.2-1.3 69.3 50.6-5.9-22.8c-73-72.8-175.4-156.7-261.86-226.69zM312.8 123.9l33.2 13.8 31.3-9.9 5.4 17.2-37.5 11.9-33.6-14-28.8 8.1-4.8-17.4zm107.3 236.2c-.7 0-1.3.1-2 .1-3.5.1-7.2.5-11.1 1.3l3.4 17.6c12.2-2.3 20-.4 24.5 2.5 4.4 2.9 6.3 6.8 6.4 12.5.1 9.3-7 23-23.3 32.5 5.4 2.9 11.9 5.9 19.3 8.7 14.4-11.6 22.1-26.8 22-41.4-.1-10.7-5.2-21.2-14.6-27.4-6.7-4.3-15-6.5-24.6-6.4z" fill="#000" fill-opacity="1"></path></g></svg>
\ No newline at end of file |