<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[{{ Ghost-O-Matic }}]]></title><description><![CDATA[{{ Ghost-O-Matic }}]]></description><link>https://ghost-o-matic.com/</link><image><url>https://ghost-o-matic.com/favicon.png</url><title>{{ Ghost-O-Matic }}</title><link>https://ghost-o-matic.com/</link></image><generator>Ghost 5.80</generator><lastBuildDate>Thu, 16 Apr 2026 16:38:22 GMT</lastBuildDate><atom:link href="https://ghost-o-matic.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Littlefoot Footnotes]]></title><description><![CDATA[Create popup footnotes in your Ghost site's posts and pages. This script enables this through the Header and Footer injections in the Ghost admin settings...]]></description><link>https://ghost-o-matic.com/littlefoot-footnotes/</link><guid isPermaLink="false">65eb378455e87ebe7b833a18</guid><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Mon, 19 Jun 2023 02:54:46 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://littlefoot.js.org/?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">littlefoot.js</div><div class="kg-bookmark-description">Footnotes without the footprint.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://t3.gstatic.com/faviconV2?client=SOCIAL&amp;type=FAVICON&amp;fallback_opts=TYPE,SIZE,URL&amp;url=https://js.org/&amp;size=128" alt><span class="kg-bookmark-author">littlefoot</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://badgen.net/npm/v/littlefoot" alt></div></a></figure><!--kg-card-begin: markdown--><p>First Footnote <a href="#fn:1" id="fnref:1">1</a></p>
<p>Second Footnote <a href="#fn:2" id="fnref:2">2</a></p>
<div class="footnotes"><hr><ol>
<li class="footnote" id="fn:1"><p>
</p><p>This is what is in the first inline footnote bubble...</p>
<p></p></li>
<li class="footnote" id="fn:2"><p>
</p><p>This is what is in the second inline footnote bubble...</p>
<p></p></li></ol></div>
<!--kg-card-end: markdown--><p>Below you can see the contents of the HTML Card used in the Post Editor... (you can copy and save this for re-use in the editor as a <a href="https://ghost.org/tutorials/code-snippets-in-ghost/?ref=ghost-o-matic.com">Code Snippet</a>)</p><pre><code class="language-HTML">First Footnote &lt;a href=&quot;#fn:1&quot; id=&quot;fnref:1&quot;&gt;1&lt;/a&gt;

Second Footnote &lt;a href=&quot;#fn:2&quot; id=&quot;fnref:2&quot;&gt;2&lt;/a&gt;

&lt;div class=&quot;footnotes&quot;&gt;&lt;hr&gt;&lt;ol&gt;
    
&lt;li class=&quot;footnote&quot; id=&quot;fn:1&quot;&gt;&lt;p&gt;
              
This is what is in the first inline footnote bubble...
              
&lt;/p&gt;&lt;/li&gt;
    
&lt;li class=&quot;footnote&quot; id=&quot;fn:2&quot;&gt;&lt;p&gt;
    
This is what is in the second inline footnote bubble...
    
&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</code></pre><p>To make this work, put this in your Site Header Code Injection...</p><pre><code class="language-HTML">&lt;link
  rel=&quot;stylesheet&quot;
  href=&quot;https://unpkg.com/littlefoot/dist/littlefoot.css&quot;
/&gt;</code></pre><p>...and put this in your Site Footer Code Injection...</p><pre><code class="language-JAVASCRIPT">&lt;script
  src=&quot;https://unpkg.com/littlefoot/dist/littlefoot.js&quot;
  type=&quot;application/javascript&quot;
&gt;&lt;/script&gt;
&lt;script type=&quot;application/javascript&quot;&gt;
  littlefoot.littlefoot() // Pass any littlefoot settings here.
&lt;/script&gt;</code></pre><p>And for reference, here below is a screenshot of the Site Header and Footer Code injections in your admin settings to enable Littlefoot Footnotes in your posts and pages...</p><figure class="kg-card kg-image-card"><img src="https://ghost-o-matic.com/content/images/2023/06/littlefoot-footnotes-code-injections-1.png" class="kg-image" alt loading="lazy" width="2000" height="1345" srcset="https://ghost-o-matic.com/content/images/size/w600/2023/06/littlefoot-footnotes-code-injections-1.png 600w, https://ghost-o-matic.com/content/images/size/w1000/2023/06/littlefoot-footnotes-code-injections-1.png 1000w, https://ghost-o-matic.com/content/images/size/w1600/2023/06/littlefoot-footnotes-code-injections-1.png 1600w, https://ghost-o-matic.com/content/images/2023/06/littlefoot-footnotes-code-injections-1.png 2060w" sizes="(min-width: 720px) 720px"></figure><p></p><p>There is also this...</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://cathy.sarisky.link/footnotes-with-ease/?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Footnotes with ease</div><div class="kg-bookmark-description">Ghost doesn&#x2019;t have native footnotes. There are some options for using Markdown or HTML cards, but none of them meet my standards. Here&#x2019;s my solution, which uses Littlefoot. How to use in the editor: 1. To mark the footnote notation, type something like [[X]] pretty much anywhere in the post.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cathy.sarisky.link/content/images/size/w256h256/2022/08/Avatars---Default-with-Backdrop-5.png" alt><span class="kg-bookmark-author">Cathy Sarisky</span><span class="kg-bookmark-publisher">Cathy Sarisky</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cathy.sarisky.link/content/images/2023/07/Capture.PNG" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[HTML Dialog Popups]]></title><description><![CDATA[The HTML Dialog Element provides popup Modals built into HTML...]]></description><link>https://ghost-o-matic.com/html-dialog-popups/</link><guid isPermaLink="false">65eb378455e87ebe7b833a17</guid><category><![CDATA[Tips and Tricks]]></category><category><![CDATA[Code Snippets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Sun, 11 Jun 2023 23:25:24 GMT</pubDate><content:encoded><![CDATA[<p>From</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://blog.webdevsimplified.com/2023-04/html-dialog/?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Modals Will Never Be The Same - HTML dialog Element</div><div class="kg-bookmark-description">The new HTML dialog element makes working with accessible modals so much easier. In this article I explain everything you need to know about the new dialog element to use it in your next project.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://blog.webdevsimplified.com/favicon.ico" alt><span class="kg-bookmark-author">HTML dialog Element</span></div></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Hundreds of Free CSS Copy-Paste Clips]]></title><description><![CDATA[A curated collection of copy-and-paste CSS box-shadow examples, buttons and checkboxes examples for use as HTML Cards/Code Snippets...]]></description><link>https://ghost-o-matic.com/93-free-css-box-shadows/</link><guid isPermaLink="false">65eb378455e87ebe7b833a16</guid><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Tue, 04 Apr 2023 21:53:52 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://getcssscan.com/css-box-shadow-examples?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Beautiful CSS box-shadow examples - CSS Scan</div><div class="kg-bookmark-description">&#x1F3A8; Curated collection of 93 free beautiful CSS box-shadow, ready-to-use for your next projects. Click to copy.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://getcssscan.com/apple-touch-icon.png" alt><span class="kg-bookmark-author">CSS Scan</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://getcssscan.com/css-box-shadow-examples/og-image.jpg" alt></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://getcssscan.com/css-buttons-examples?ref=beautifulboxshadow-bottom"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Beautiful CSS buttons examples - CSS Scan</div><div class="kg-bookmark-description">&#x1F3A8; Curated collection of 92 free beautiful CSS buttons, ready-to-use for your next projects. Click to copy.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://getcssscan.com/apple-touch-icon.png" alt><span class="kg-bookmark-author">CSS Scan</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://getcssscan.com/css-buttons-examples/og-image.jpg" alt></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://getcssscan.com/css-checkboxes-examples?ref=beautifulboxshadow-bottom"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Beautiful CSS checkboxes examples - CSS Scan</div><div class="kg-bookmark-description">&#x1F3A8; Curated collection of 65 free beautiful CSS checkboxes, ready-to-use for your next projects. Click to copy.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://getcssscan.com/apple-touch-icon.png" alt><span class="kg-bookmark-author">CSS Scan</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://getcssscan.com/css-checkboxes-examples/og-image.jpg" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[CSS position:sticky Not Working?]]></title><description><![CDATA[Stuck on CSS Sticky Positioning? Here are some troubleshooting tips...]]></description><link>https://ghost-o-matic.com/css-position-sticky-not-working/</link><guid isPermaLink="false">65eb378455e87ebe7b833a15</guid><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Tue, 04 Apr 2023 03:04:33 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://michaelmovsesov.com/articles/fix-css-position-sticky-not-working?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">CSS position:sticky Not Working? Try This Fix</div><div class="kg-bookmark-description">FRONT END ENGINEER | PROBLEM SOLVER</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://michaelmovsesov.com/icons/icon-512x512.png?v=b5bfb92b196c687534898f3c007856e7" alt><span class="kg-bookmark-author">Michael Movsesov</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://michaelmovsesov.com/og-images/articles/5293d806-b588-58b3-963c-08ca96497eec.png" alt></div></a></figure><div class="kg-card kg-audio-card"><img src alt="audio-thumbnail" class="kg-audio-thumbnail kg-audio-hide"><div class="kg-audio-thumbnail placeholder"><svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 15.33a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm-2.25.75a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0ZM15 13.83a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm-2.25.75a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M14.486 6.81A2.25 2.25 0 0 1 17.25 9v5.579a.75.75 0 0 1-1.5 0v-5.58a.75.75 0 0 0-.932-.727.755.755 0 0 1-.059.013l-4.465.744a.75.75 0 0 0-.544.72v6.33a.75.75 0 0 1-1.5 0v-6.33a2.25 2.25 0 0 1 1.763-2.194l4.473-.746Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M3 1.5a.75.75 0 0 0-.75.75v19.5a.75.75 0 0 0 .75.75h18a.75.75 0 0 0 .75-.75V5.133a.75.75 0 0 0-.225-.535l-.002-.002-3-2.883A.75.75 0 0 0 18 1.5H3ZM1.409.659A2.25 2.25 0 0 1 3 0h15a2.25 2.25 0 0 1 1.568.637l.003.002 3 2.883a2.25 2.25 0 0 1 .679 1.61V21.75A2.25 2.25 0 0 1 21 24H3a2.25 2.25 0 0 1-2.25-2.25V2.25c0-.597.237-1.169.659-1.591Z"/></svg></div><div class="kg-audio-player-container"><audio src="https://ghost-o-matic.com/content/media/2023/04/hallelujah.mp3" preload="metadata"></audio><div class="kg-audio-title">Hallelujah</div><div class="kg-audio-player"><button class="kg-audio-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-audio-pause-icon kg-audio-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-audio-current-time">0:00</span><div class="kg-audio-time">/<span class="kg-audio-duration">0:09</span></div><input type="range" class="kg-audio-seek-slider" max="100" value="0"><button class="kg-audio-playback-rate">1&#xD7;</button><button class="kg-audio-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-audio-mute-icon kg-audio-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-audio-volume-slider" max="100" value="100"></div></div></div>]]></content:encoded></item><item><title><![CDATA[Prefetch Internal Link on Hover]]></title><description><![CDATA[Load same-site posts and pages faster by pre-loading them in the background on mouse hover...]]></description><link>https://ghost-o-matic.com/prefetch-internal-link-on-hover/</link><guid isPermaLink="false">65eb378455e87ebe7b833a13</guid><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Tue, 28 Mar 2023 00:30:29 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-embed-card"><iframe id="cp_embed_poZEoPY" src="https://codepen.io/2kool2/embed/preview/poZEoPY?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=poZEoPY" title="[Performance] Prefetch same-site link HTML upon mouse hover for faster page loads" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;"></iframe></figure>]]></content:encoded></item><item><title><![CDATA[Responsive Fonts]]></title><description><![CDATA[Auto-scaling, responsive fonts using CSS.]]></description><link>https://ghost-o-matic.com/responsive-fonts/</link><guid isPermaLink="false">65eb378455e87ebe7b833a12</guid><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Tue, 28 Mar 2023 00:25:18 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://websemantics.uk/articles/responsive-fonts/?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Responsive fonts - auto-scaling the root font-size</div><div class="kg-bookmark-description">Using pure CSS the root font size scales up and down proportionately, between defined values, dependent upon the viewport width.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://websemantics.uk/apple-touch-icon-180x180.png" alt><span class="kg-bookmark-author">auto-scaling the root font-size</span><span class="kg-bookmark-publisher">Mike Foskett</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://websemantics.uk/apple-touch-icon-152x152.png" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Sortable Tables in Details/Summary]]></title><description><![CDATA[Sortable Tables in Details/Summary]]></description><link>https://ghost-o-matic.com/sortable-tables-in-details-summary/</link><guid isPermaLink="false">65eb378455e87ebe7b833a0e</guid><category><![CDATA[Javascript Snippets]]></category><category><![CDATA[Eye Candy]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Wed, 15 Mar 2023 17:40:16 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: html--><style>

/* Compress with: https://cssminifier.org/ */
main {
  /* 1.125rem(18px) @ 40.75rem(652px) increasing to 1.6875rem(27px) @ 120rem(1920px) */
  font-size: clamp(1.125rem, calc(1.125rem + (1.6875 - 1.125) * ((100vw - 40.75rem) / (120 - 40.75))), 1.6875rem)
  /* Where: calc = min_font_size_in_rem + (max_font_size - min_font_size) * ((100vw - min_viewport_in_rem) / (max_viewport - min_viewport)) */
}
main {
  --sans-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif;
  --content-width: 70ch;
  --v-space: 1rem;
  --v-space-0_25: calc(var(--v-space) / 4);
  --v-space-0_5: calc(var(--v-space) / 2);
  --v-space-2: calc(var(--v-space) * 2);
  --h-space: 8px;
  --h-space-0_5: calc(var(--h-space) / 2);
  --h-space-0_25: calc(var(--h-space) / 4);
  --bg: #1a1a1a;
  --accent-bg: #292929;
  --bg-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2056 2056'%3E%3Cfilter id='b73'%3E%3CfeTurbulence type='fractalnoise' baseFrequency='.3' result='n73'/%3E%3CfeDiffuseLighting in='n73' lighting-color='hsl(0,0%,14%)'%3E%3CfeDistantLight azimuth='30' elevation='50'/%3E%3C/feDiffuseLighting%3E%3C/filter%3E%3Crect width='100%' height='100%' filter='url(%23b73)'/%3E%3C/svg%3E");
  --border: #6666;
  --border-gradient: linear-gradient(140deg, #ff09, #f609);
  --linear-gradient-1: linear-gradient(-3deg,#0a0a0a, #3a3a3a, #222);
  --linear-gradient-2: linear-gradient(-1deg,#0a0a0a,#3a3a3a,#222);
  --linear-gradient-3: linear-gradient(-0.7deg,#000,#3337,#111);
  --accent: #f90;
  --accent-hover: #fe6;
  --selectionColor: #000;
  --selectionBg: #cdf;
  --FocusRing-outline-color: #ee0;
  --highlight-bg: #000;
  --highlight-color: #fff;

  background-color: var(--bg);
  color: #ddd;
  color-scheme: dark;
  font-family: var(--sans-font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -moz-text-size-adjust: none;
  -webkit-text-size-adjust: none;
  text-size-adjust: none;
}


*,
:after,
:before {
  box-sizing: border-box;
  margin: 0;
}




main {
  background: transparent;
}

:is(main) > div {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--v-space)var(--h-space);
  text-align: center;
}

h1,
summary {
  font-weight: 400;
  line-height: calc(4px + 2ex);
}

h1 {
  color: #bbb;
  font-size: 1.25rem;
  letter-spacing: -0.03em;
}
h1 > * {
  display: block;
  margin-top: var(--v-space-0_25);
}
h1 > :first-child {
  color: #eee;
  font-size: 1.5rem;
}

h1 > :last-child {
  font-size: 1.1rem;
}

::marker,
a,
a:visited {
  color: var(--accent);
  display: inline-block;
  text-decoration-skip-ink: auto;
}
a,
a > * {
  transition: all .3s ease-out;
}
a:is(:focus, :hover) {
  color: var(--accent-hover);
  text-decoration-color: #0000;
}

a[rel=external][target=_blank]:after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><path d='M28,4 39,4 39,15 M39,4 23,20 M28,9 7,9 7,34 35,34 35,15' fill='none' stroke='%23808080' stroke-width='3'/></svg>");
  background-repeat: no-repeat;
  background-size: 1em 1em;
  content: "";
  display: inline-block;
  height: 1em;
  margin: 0 0 0 .125em;
  width: 1em;
}

button {
  background-color: var(--bg);
  border: 1px solid transparent;
  border-radius: 0;
  color: var(--accent);
  font-size: inherit;
  padding: var(--h-space-0_25) 0;
  padding-left: calc(var(--h-space) / 4);
  width: 100%;
}

button:is(:focus, :hover) {
  --FocusRing-outline-offset: -2px;
  border-image: linear-gradient(173deg, #ff0, #f60) 1;
  color: var(--accent-hover);
  cursor: pointer;
  position: relative;
}

@media(min-width:20em) {
  button:is(:focus, :hover) {
    --FocusRing-outline-offset: 2px;
  }
}

button:first-letter {
  text-transform: capitalize;
}

details {
  border: 1px solid var(--border);
  border-image: var(--border-gradient) 1;
  background: var(--accent-bg);
  margin: var(--v-space) 0;
  padding: 0;
  text-align: left;
}

* + details {
  margin-top: var(--v-space-2);
}

td details {
  background-color: transparent;
  border: 0;
  margin: 0;
}

::-webkit-details-marker {
  color: var(--accent);
}
    
details p {
    white-space: normal;
    }

summary:focus, summary:hover {
    background-color: unset;
}
    
summary {
  --FocusRing-outline-offset: 3px;
  background: var(--linear-gradient-2);
  cursor: pointer;
  display: list-item;
  padding: var(--v-space-0_5)var(--v-space);
}

td summary {
  background: inherit;
  padding: 0;
}

td summary ~ * {
  font-size: smaller;
}

summary > div {
  display: inline-block;
  pointer-events: none;
  vertical-align: top;
  width: calc(100% - 1.2em);
}

td summary > div {
 /* margin-left: -4px; */
  width: calc(100% - 1em);
}

td details > div {
  background-color: var(--bg);
  border: 1px solid var(--border);
  box-shadow: 0 0 4px black;
  left: 0;
  margin: 2px 14px;
  padding: var(--v-space-0_5) var(--h-space);
  position: absolute;
  width: calc(100% - var(--h-space) * 3);
  z-index: 1;
}

@media(min-width:30em) {
  td details > div {
    background-color: inherit;
    border: 0;
    box-shadow: none;
    margin: var(--v-space-0_5) 0 var(--v-space-0_25);
    position: initial;
    padding: 0;
    width: auto;
  }
  details tbody button {
    display: none;
  }
}

@media(min-width:40em) {
  td details > div {
    padding: 0 var(--h-space-0_5);
  }
}

td details > div * + * {
  margin-top: var(--v-space-0_5);
}

details button {
  border-color: var(--border);
  display: block;
}



a,
button,
summary {
  -ms-touch-action: manipulation;
  touch-action: manipulation;
}


#content > details > div {
  max-width: 100%;
  margin: 0;
  overflow: auto hidden;
}

@media(min-width:20em) {
  #content > details > div {
    overflow: initial;
  }
}

table {
  border-collapse: collapse;
  min-width: 16rem;
  width: 100% !important;
}

tr:nth-child(2n) {
  background:var(--bg);
}
tr:nth-child(2n+1) {
  background: var(--linear-gradient-3);
}

tr.current-time {
  background-color: var(--highlight-bg);
  color: var(--highlight-color);
}

td.time {
  border-left: 2px solid transparent;
  padding-left: calc(var(--h-space-0_5) - 2px);
}

tr.current-time .time {
  border-left-color: var(--accent);
}

tr:last-child td {
  border-bottom: 0;
}

th {
  background-color: transparent !important;
  font-size: smaller;
  letter-spacing: .02em;
  padding: 0;
  white-space: nowrap;
}

th,
td {
  border-top: 1px solid var(--border);
}

th + th,
td + td {
  border-left: 1px solid var(--border);
}

td {
  letter-spacing: -.04em;
  line-height: calc(6px + 2ex);
  padding: var(--v-space-0_25) var(--h-space-0_5);
  vertical-align: top;
background-image: none !important;
}
.time {
  min-width: 3.4rem;
}
.artist {
  letter-spacing: 0;
  width: 100%;
}
.venue {
  color: #aaa;
  min-width: 6.1em;
}
@media(min-width:40em) {
  td {
    padding: var(--v-space-0_5)var(--h-space-0_5);
  }
  .time {
    min-width: 6em;
    white-space: nowrap;
  }
  .artist {
    min-width: 6em;
  }
  .venue {
    max-width: 8.5em;
    min-width: 7em;
    white-space: nowrap;
  }
}
/* th button > span {
  filter: saturate(250%) hue-rotate(180deg) opacity(.75);
} */
.venue a {
  white-space: pre-line;
}

@media(prefers-reduced-motion:no-preference) {
  body {
    --FocusRing-transition-duration: .3s;
  }
}

:is(a[href], button, summary, .responsive_wrap) {
  outline: transparent solid var(--FocusRing-outline-width, 2px);
  outline-offset: var(--FocusRing-transition-offset, 5px);
  transition: all var(--FocusRing-transition-duration, 0) ease-out;
}

:focus-visible,
:is(a[href], button, summary, .responsive_wrap):focus {
  outline-color: var(--FocusRing-outline-color, #00f);
  outline-offset: var(--FocusRing-outline-offset, 2px);
}

@supports selector(:focus-visible) {
  :is(a[href], button, summary, .responsive_wrap):focus:not(:focus-visible) {
    outline: 0;
  }
}

iframe {
  border: 0;
  border-top: 1px solid var(--border);
  display: block;
  height: 90vh;
  max-height: 90vh;
  min-height: 300px;
  width: 100%;
}



a:is(:hover, :focus) svg {
  background-color: var(--accent-hover);
  fill: #292929;
}

::selection {
  background-color: var(--selectionBg);
  color: var(--selectionColor);
  opacity: 1;
  text-shadow: none;
}

.-visually-hidden {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  white-space: nowrap;
  width: 1px;
  position: absolute;
  overflow: hidden;
}

q {
  font-style: italic;
  font-weight: 500;
}

</style><!--kg-card-end: html--><!--kg-card-begin: html-->
<main>
  <div>
    <div id="content">
      
      <!-- Generating data table, rather than flat HTML, significantly reduced the HTML file size, far less repetition -->
      
      <!-- Added empty containers to reduce CLS (to 0), and improve TBT too -->
      <!-- Note: The JS doesn't rely upon these containers existing, or being the correct number, but it really helps! -->
      
      <!-- This version: Extend html shell, without data, and reduce JS overhead -->

      <details>
        <summary><div></div></summary>
        <div>
          <table>
            <caption></caption>
            <thead>
              <tr>
                <th scope="col"></th>
                <th scope="col"></th>
                <th scope="col"></th>
              </tr>
            </thead>
            <tbody>
            </tbody>
          </table>
        </div>
      </details>

      <details>
        <summary><div></div></summary>
        <div>
          <table>
            <caption></caption>
            <thead>
              <tr>
                <th scope="col"></th>
                <th scope="col"></th>
                <th scope="col"></th>
              </tr>
            </thead>
            <tbody>
            </tbody>
          </table>
        </div>
      </details>

      <details>
        <summary><div></div></summary>
        <div>
          <table>
            <caption></caption>
            <thead>
              <tr>
                <th scope="col"></th>
                <th scope="col"></th>
                <th scope="col"></th>
              </tr>
            </thead>
            <tbody>
            </tbody>
          </table>
        </div>
      </details>

      <details>
        <summary><div></div></summary>
        <div>
          <table>
            <caption></caption>
            <thead>
              <tr>
                <th scope="col"></th>
                <th scope="col"></th>
                <th scope="col"></th>
              </tr>
            </thead>
            <tbody>
            </tbody>
          </table>
        </div>
      </details>
      
    </div>

    <details>
      <summary id="map">
        <div></div>
      </summary>
      <div>
        <!-- Don't load nonessential data until it is required! -->
        <iframe aria-labelledby="map"></iframe>
      </div>
    </details>
  </div>
</main>
<!--kg-card-end: html--><!--kg-card-begin: html-->
<script>

console.clear();

const year = '2023';
const d = document;
const content = d.getElementById('content');
const date = new Date;
const todayName = date.toLocaleDateString('en-GB', {weekday: 'long'});


const dateDataFunctions = _ => {

  const datesArr = [
    {
      date:'Thursday 2nd March',
      dayName: 'Thursday',
      datetime:'2023-03-02',
      acts:[
        {
          time:'16:00',
          artist:' Geoff\'s Jam',
          venue:'Globe Inn'
        },
        {
          time:'20:30',
          artist:'The Million Dollar Bash',
          venue:'The Legion'
        },
        {
          time:'21:00',
          artist:'Ray Drury & Jon Walsh',
          venue:'Red Lion'
        }
      ]
    },

    {
      date:'Friday 3rd March',
      dayName: 'Friday',
      datetime:'2023-03-03',
      acts:[
        {
          time:'14:00 -16:30',
          artist:'Back Porch',
          venue:'The Legion'
        },
        {
          time:'14:00',
          artist:'Open Mic with Andy Bradshaw',
          venue:'Red Lion'
        },
        {
          time:'15:00',
          artist:'Robert Hokum',
          venue:'White Swan'
        },
        {
          time:'16:00 -18:00',
          artist:'The Robin Bibi Band',
          venue:'Showbar'
        },
        {
          time:'17:30 -20:00',
          artist:'Chicago 9 Rhythm & Blues Band',
          venue:'Con Club'
        },
        {
          time:'19:00',
          artist:'Pete Harris & Ray Drury',
          venue:'Tawny\'s'
        },
        {
          time:'20:00',
          artist:'Jon Storey Band',
          venue:'Globe Inn'
        },
        {
          time:'20:00',
          artist:'The Fabulous Duck Brothers',
          venue:'IoP Golf Club'
        },
        {
          time:'20:30',
          artist:'Zoë Schwarz Blue Commotion',
          venue:'Grand Hotel'
        },
        {
          time:'20:30',
          artist:'Blue Touch',
          venue:'The Legion'
        },
        {
          time:'20:30 -23:00',
          artist:'Vince Lee & the Big Combo',
          venue:'Showbar'
        },
        {
          time:'21:00',
          artist:'Back Porch',
          venue:'Herston Camping'
        },
        {
          time:'21:00',
          artist:'Tommy Allen Duo with Jon Vaughan',
          venue:'Red Lion'
        },
        {
          time:'21:00',
          artist:'The Mustangs',
          venue:'White Horse'
        },
        {
          time:'21:00',
          artist:'George Hall Trio',
          venue:'White Swan'
        }
      ]
    },
    {
      date:'Saturday 4th March',
      dayName: 'Saturday',
      datetime:'2023-03-04',
      acts:[
        {
          time:'12:00',
          artist:'Will Killeen',
          venue:'The Centre'
        },
        {
          time:'13:00',
          artist:'Lee Signey',
          venue:'The Centre'
        },
        {
          time:'13:00 -15:30',
          artist:'The Robin Bibi Band\'s Electric Jam Session',
          venue:'Con Club'
        },
        {
          time:'13:00',
          artist:'Vince Lee & the Big Combo',
          venue:'The Legion'
        },
        {
          time:'14:00',
          artist:'Liam Ward & Malcolm Thorp',
          venue:'The Centre'
        },
        {
          time:'14:00',
          artist:'Lewis Cohen',
          venue:'Greyhound'
        },
        {
          time:'14:00',
          artist:'Born Healer',
          venue:'Herston Camping'
        },
        {
          time:'14:00',
          artist:'Open Mic with Andy Bradshaw',
          venue:'Red Lion'
        },
        {
          time:'14:00',
          artist:'Thomas Heppell Band',
          venue:'YHA'
        },
        {
          time:'14:30',
          artist:'Robert Hokum\'s Acoustic Blues Bonanza',
          venue:'Grand Hotel'
        },
        {
          time:'15:00',
          artist:'Geoff Garbow Band',
          venue:'White Swan'
        },
        {
          time:'15:30',
          artist:'Ben White & Thomas Lucas',
          venue:'The Centre'
        },
        {
          time:'16:00 -18:30',
          artist:'The Fabulous Duck Brothers',
          venue:'Showbar'
        },
        {
          time:'16:30',
          artist:'Gary Fletcher Trio',
          venue:'The Centre'
        },
        {
          time:'16:30',
          artist:'Pete Harris Blues Band with Jon Vaughan & Ray Drury',
          venue:'The Legion'
        },
        {
          time:'17:30 -20:00',
          artist:'Back Porch',
          venue:'Con Club'
        },
        {
          time:'19:00',
          artist:'Lewis Cohen & Spencer Couzens',
          venue:'Tawny\'s'
        },
        {
          time:'22:00',
          artist:'Jon Storey Band',
          venue:'Globe Inn'
        },
        {
          time:'20:30',
          artist:'Robert Hokum\'s Electric Blues Bonanza',
          venue:'Grand Hotel'
        },
        {
          time:'20:30',
          artist:'The Robin Bibi Band',
          venue:'The Legion'
        },
        {
          time:'20:30 -23:00',
          artist:'Blue Touch',
          venue:'Showbar'
        },
        {
          time:'21:00',
          artist:'Tommy Allen Duo with Ray Dury',
          venue:'Herston Camping'
        },
        {
          time:'21:00',
          artist:'Isobel Thatcher Duo',
          venue:'Red Lion'
        },
        {
          time:'21:00',
          artist:'The Milk Men',
          venue:'White Horse'
        },
        {
          time:'21:00',
          artist:'Chicago 9 Rhythm & Blues Band',
          venue:'White Swan'
        }
      ]
    },
    {
      date:'Sunday 5th March',
      dayName: 'Sunday',
      datetime:'2023-03-05',
      acts:[
        {
          time:'12:00',
          artist:'Jonathan Townsend',
          venue:'The Centre'
        },
        {
          time:'13:00',
          artist:'Greg Brice',
          venue:'The Centre'
        },
        {
          time:'13:00 -15:30',
          artist:'Hugh Budden & the Blue Chords',
          venue:'Con Club'
        },
        {
          time:'13:00',
          artist:'Open Mic with Andy Bradshaw',
          venue:'Red Lion'
        },
        {
          time:'14:00',
          artist:'Ben White & Thomas Lucas',
          venue:'Greyhound'
        },
        {
          time:'14:00',
          artist:'The Robin Bibi Band\'s Electric Jam Session',
          venue:'The Legion'
        },
        {
          time:'14:15',
          artist:'Joff Watkins Duo',
          venue:'The Centre'
        },
        {
          time:'14:30 -17:00',
          artist:'Vince Lee & Sophie Lord',
          venue:'Grand Hotel'
        },
        {
          time:'15:00',
          artist:'Thomas Heppell Band',
          venue:'Black Swan'
        },
        {
          time:'15:00',
          artist:'Tommy Allen Duo with Jon Vaughan',
          venue:'White Swan'
        },
        {
          time:'15:30',
          artist:'Mark Harrison & Charles Benfield',
          venue:'The Centre'
        },
        {
          time:'16:30',
          artist:'Fran McGillivray & Mike Burke',
          venue:'The Centre'
        },
        {
          time:'20:00',
          artist:'Pete Harris & Jon Vaughan',
          venue:'Red Lion'
        },
        {
          time:'20:30 -23:00',
          artist:'Hugh Budden & the Blue Chords',
          venue:'Grand Hotel'
        },
        {
          time:'20:30',
          artist:'Tommy Allen Band',
          venue:'The Legion'
        }
      ]
    }
  ];

  function dayDetails(date, details) {
    const div = details.querySelector('summary > div');
    const time = d.createElement('time');
    time.setAttribute('datetime', date.datetime);
    time.textContent = date.date;
    div.appendChild(time);
    return details;
  }

  const domDetails = content.querySelectorAll('details');
  const fragment = new DocumentFragment();
  let count = 0;
  for (const date of datesArr) {
    const details = dayDetails(date, domDetails[count++]);
    details.date = date;
    fragment.appendChild(details);
  }
  content.appendChild(fragment);

};


const tableGeneration = _ => {

  function createDetailsSummary(text) {
    const details = d.createElement('details');
    const summary = d.createElement('summary');
    const div = d.createElement('div');
    div.textContent = text;
    summary.appendChild(div);
    details.appendChild(summary);
    return details;
  }

  function generateTableRows(table, data) {
    for (const element of data) {
      let row = table.insertRow();
      for (const key in element) {
        const cell = row.insertCell();
        cell.className = key;

        if (key === 'time') {
          cell.textContent = element[key];
          continue;
        }

        cell.appendChild(createDetailsSummary(element[key]));
      }
    }
    return table;
  }

  function createSortButton(text) {
    // Only interested in the visual at this point, actions added post load.
    const button = d.createElement('button')
    button.className = 'btn-sort';
    // button.setAttribute('aria-label', 'Sort timetable by ' + text);
    // button.textContent = text + '↕';
    button.textContent = text;
    return button;
  }

  function generateTableHead(table, data) {
    const thead = table.createTHead();
    const row = thead.insertRow();
    for (const key of data) {
      let th = d.createElement('th')
      th.className = key;
      th.setAttribute('scope', 'col');
      const button = createSortButton(key);
      th.appendChild(button);
      row.appendChild(th);
    }
    return table;
  }

  function createTableCaption(table) {
    const caption = d.createElement('caption');
    caption.className = '-visually-hidden';
    caption.textContent = table.dayName + '\'s acts, times and locations.';
    table.appendChild(caption);
    return table;
  }

  function generateTable(date) {
    let table = d.createElement('table');
    table.dayName = date.dayName;
    table = createTableCaption(table);
    table = generateTableRows(table, date.acts);
    const data = Object.keys(date.acts[0]);
    table = generateTableHead(table, data);
    return table;
  }

  // Runtime
  const contentDetails = content.querySelectorAll('details');
  for (const details of contentDetails) {

    const columnNames = Object.keys(details.date.acts[0]);

    const tableDom = details.querySelector('table');
    const table = tableDom.cloneNode(true);
    table.dayName = details.date.dayName;

    const caption = table.querySelector('caption');
    caption.className= '-visually-hidden';
    caption.textContent = table.dayName + '\'s acts, times and locations.';

    const ths = table.querySelectorAll('thead th');
    let count = 0;
    for (const th of ths) {
      const text = columnNames[count++];
      th.className = text;
      const button = d.createElement('button')
      button.className = 'btn-sort';
      button.textContent = text.charAt(0).toUpperCase() + text.slice(1) + ' ↕';
      button.setAttribute('aria-label', text);
      th.appendChild(button);
    }

    const tbody = table.querySelector('tbody');
    for (const element of details.date.acts) {
      let row = tbody.insertRow();
      for (const key in element) {
        const cell = row.insertCell();
        cell.className = key;

        if (key === 'time') {
          cell.textContent = element[key];
          continue;
        }

        const details = d.createElement('details');
        const summary = d.createElement('summary');
        const div = d.createElement('div');
        div.textContent = element[key];
        summary.appendChild(div);
        details.appendChild(summary);

        // cell.appendChild(createDetailsSummary(element[key]));
        cell.appendChild(details);
      }
    }
    
    if (details.date.dayName === todayName) {
      details.setAttribute('open', true);
    }
    tableDom.parentElement.replaceChild(table, tableDom);
  }

};

// // Added to tableGeneration
// const openTodayTimetable = _ => {
//   const n = new Date;
//   const day = n.toLocaleDateString('en-GB', {
//     weekday: 'long'
//   });
//   const contentDetails = d.querySelectorAll('#content > details');
//   for (const details of contentDetails) {
//     if (details.date.date.trim().split(' ')[0] === day) {
//       // requestAnimationFrame(_ => {
//         details.setAttribute('open', true);
//       // });
//       break;
//     }
//   }

// };


const venueDataFunctions = _ => {

  const mapAddress = 'https://ul.waze.com/ul?place=';

  const venuesArr = [
    {
      name: 'Black Swan',
      address: '159 High Street\nBH19 2NE',
      url: 'ChIJh9BBjW4Jc0gRqusdkuR0bbQ&ll=50.60777280%2C-1.96368560'
    },
    {
      name: 'Con Club',
      address: '27 Kings Rd West\nBH19 1HE',
      url: 'ChIJmc5g4KQBc0gRu__z8PwgzvI&ll=50.60606750%2C-1.95783700'
    },
    {
      name: 'Globe Inn',
      address: '3 Bell St\nBH19 2RY',
      url: 'ChIJ488Gq2UJc0gRxmYERQmRqM0&ll=50.60795970%2C-1.95672460'
    },
    {
      name: 'Grand Hotel',
      address: 'Burlington Road\nBH19 1LU',
      url: 'ChIJtdER9ngJc0gRda-rGciMNx8&ll=50.61937160%2C-1.95632680'
    },
    {
      name: 'Greyhound',
      address: 'The Square\nCorfe Castle\nWareham\nBH20 5EZ',
      url: 'ChIJCTNUqzUGc0gRafGDIYi6xN0&ll=50.63857700%2C-2.05725430'
    },
    {
      name: 'Herston Camping',
      address: 'Washpond Lane\nBH19 3DJ',
      url: 'ChIJh2TGDQkJc0gRGh8nbRq5scY&ll=50.61819760%2C-1.97932100'
    },
    {
      name: 'IoP Golf Club',
      address: 'Corfe Road\nStudland\nBH19 3AB',
      url: 'ChIJK4rxKroJc0gRTeRAj89diz8&ll=50.63663490%2C-1.98246030'
    },
    {
      name: 'Old Stables',
      address: '37 Commercial Rd\nBH19 1DF',
      url: 'ChIJL-qjb2UJc0gRaBWVC7d9sm0&ll=50.60929090%2C-1.95841840'
    },
    {
      name: 'Red Lion',
      address: '63 High Street\nBH19 2LY',
      url: 'ChIJDURTg2UJc0gRnNkGgrAf8ME&ll=50.60825080%2C-1.95841470'
    },
    {
      name: 'Showbar',
      address: 'Mowlem Theatre\nShore Road\nBH19 1DD',
      url: 'ChIJW2Rp4WYJc0gRn7y4WEcooV8&ll=50.60945670%2C-1.95671470'
    },
    {
      name: 'Tawny\'s',
      address: '52 High Street\nBH19 2NX',
      url: 'ChIJzThYnWUJc0gRhNUBDbpzHhA&ll=50.60842930%2C-1.95846890'
    },
    {
      name: 'The Centre',
      address: '7 Chapel Lane\nBH19 2PW',
      url: 'ChIJF-uMEW8Jc0gRFv8etp2iQCg&ll=50.60772200%2C-1.96104200'
    },
    {
      name: 'The Legion',
      address: '150 High Street\nBH19 2PA',
      url: 'ChIJUWWfK2wJc0gRpNf9siO6A4I&ll=50.60833330%2C-1.96583330'
    },
    {
      name: 'White Horse',
      address: '11 High Street\nBH19 2LP',
      url: 'ChIJI19wRGQJc0gR-j_fNUStbHk&ll=50.60770100%2C-1.95513100'
    },
    {
      name: 'White Swan',
      address: '31 High Street\nBH19 2LJ',
      url: 'ChIJ488Gq2UJc0gRxmYERQmRqM0&ll=50.60795970%2C-1.95672460'
    },
    {
      name: 'YHA',
      address: '159 High Street\nBH19 2NE',
      url: 'ChIJmc5g4KQBc0gRu__z8PwgzvI&ll=50.60606750%2C-1.95783700'
    }
  ];


  const venueDetails = content.querySelectorAll('td.venue > details');
  for (const details of venueDetails) {
    const name = details.textContent.trim();
    const venue = venuesArr.find(item => item.name === name);
    if (!venue) continue;

    const div = d.createElement('div');
    const link = d.createElement('a');
    link.href = mapAddress + venue.url;
    link.textContent = venue.address;
    div.appendChild(link);

    // Not visible, so apply directly:
    details.appendChild(div);
  }

};


const artistDataFunctions = _ => {

  const imgFolder = 'https://websemantics.uk/swanage-blues/img/artists/';
  // const imgFolder = '../../img/artists/'; // Local drive only

  const artistsArr = [
  {
    name: 'Back Porch',
    photo: 'back-porch.jpg',
    biog: '<p>Foot-stomping, danceable rhythms and a lot of fun, Back Porch will make you laugh, cry and tap your feet! It\'s a stripped-down line-up of harp, washboard and guitars &ndash; just some mates sitting on a back porch, playing the blues.</p>',
    url: 'http://www.backporchuk.com/'
  },
  {
    name: 'Ben White & Thomas Lucas',
    photo: 'ben-white-thomas-lucas.jpg',
    biog: '<p>Young performers whose enthusiasm, ability, wit and charm were very well received last festival. Enjoy good original material, paying homage to classic Chicago blues.</p>'
  },
  {
    name: 'Blue Touch',
    photo: 'blue-touch.jpg',
    biog: '<p>Blue Touch delivers heavy duty blues rock with a blend of original and re-worked classic blues songs in an entertaining stage show with Andrea Maria on vocals.</p>',
    url: 'https://www.bluetouch.info/'
  },
  {
    name: 'Born Healer',
    photo: 'born-healer.jpg',
    biog: '<p>Blues and blues rock. <q>Blistering blues-laced soul… stunning</q> &ndash; Blues in Britain</p> <p><q>Helen Turner\'s voice remains in a different class</q> &ndash; Classic Rock.</p>',
    url: 'http://www.bornhealer.com/'
  },
  {
    name: 'Chicago 9 Rhythm & Blues Band',
    photo: 'chicago-9-rhythm-blues-band.jpg',
    biog: '<p>Formed in 2002 from friendship and musical respect and led from the front by skilled guitar and saxophone interplay, driven by a solid backbeat and enhanced by keyboards and Angela\'s superb vocals.</p>',
    url: 'https://www.facebook.com/chicago9bluesband'
  },
  {
    name: 'Fran McGillivray & Mike Burke',
    photo: 'fran-mcgillivray-mike-burke.jpg',
    biog: '<p>Exciting and compelling performers who have developed a unique take on blues and roots music, and an amazing empathy on stage and on record.</p>',
    url: 'https://www.franmike.com/'
  },
  {
    name: 'Gary Fletcher Trio',
    photo: 'gary-fletcher-trio.jpg',
    biog: '<p>From The Blues Band, Gary Fletcher, guitar, slide and banjo, together with Alan Glen, harmonica and Nick Ritchie, guitar, play their take on blues & roots.</p>',
    url: 'https://www.garyfletchermusic.net/'
  },
  {
    name: 'Geoff Garbow Band',
    photo: 'geoff-garbow-blues-band.jpg',
    biog: '<p>The Geoff Garbow Band both experiment with and respect blues traditions but their vibe is distinctly West London &ndash; whether in environmental protest over Heathrow expansion or just singing the blues about life, love and toil.</p>',
    url: 'https://www.geoffgarbowband.com/'
  },
  {
    name: 'Geoff\'s Jam',
    biog: '<p>An informal gathering of musicians coming together to play music, often improvising and experimenting with different sounds and styles, but less focused on individual performances and more about the collaborative experience.</p>'
  },
  {
    name: 'George Hall Trio',
    photo: 'george-hall-trio.720.jpg',
    width: '720',
    height: '720',
    biog: '<p>The trio seek to put a modern twist to blues, funk and rock of bygone days.</p><p><q>George Hall gives some of the greatest guitarists alive a run for their money and can simultaneously switch from swaggering rock to blistering blues</q> &ndash; BeCider Seaside</p>',
    url: 'https://georgehalltrio.co.uk/'
  },
  {
    name: 'Greg Brice',
    photo: 'greg-brice.jpg',
    biog: '<p>The Nominations are in for The UK Blues Awards 2023, and Greg is in the top 20 over 3 categories.</p><p>…the rest of the UK Blues scene will soon realise &ndash; that Greg Brice is a proper talent…</p>',
    url: 'https://www.facebook.com/gregbricemusic'
  },
  {
    name: 'Hugh Budden & the Blue Chords',
    photo: 'hugh-budden-blue-chords.jpg',
    biog: '<p>Hugh will also be MC, host, guest artist and sound, lighting & stage manager at the Grand Hotel all weekend. He is the hardest working harmonica and vocals man I know, no doubt due to his style, showmanship and sheer professionalism! Make sure you catch him at least once!</p>',
    url: 'https://hughbudden.wixsite.com/hugh-budden/home-page'
  },
  {
    name: 'Isobel Thatcher Duo',
    photo: 'isobel-thatcher.jpg',
    biog: '<p>Isobel has been appearing at our open mics and jam sessions for 10 years and we are pleased to see her in her own named slot with her brother Domonic on saxophone. Sonja Christina of Curved Air said: <q>A confident performer with a sparkling voice and well-crafted songs. It was a pleasure to hear and to have a good reason to return to the Troubadour after 20 years. Congratulations.</q></p>',
    url: 'https://isobelthatcher.com/'
  },
  {
    name: 'Joff Watkins Duo',
    photo: 'joff-watkins-duo.jpg',
    biog: '<p>Joff Watkins on harmonica and vox and CJ Williams on guitar make a sound inspired by North Mississippi, New Orleans and South London. Joff is one of the best harmonica players on the scene and CJ is a uniquely talented guitarist. Both are members of Jimmy Regal and the Royals, one of the most exciting blues acts at the moment who have been playing festivals and venues up and down the UK.</p>',
    url: 'https://www.facebook.com/joff.watkins'
  },
  {
    name: 'Jon Storey Band',
    photo: 'jon-storey-band.jpg',
    biog: '<p>Based in Portugal and Spain, so it\'s a great pleasure and all credit to the Globe Inn for attracting them to Swanage! Quality, strong and hard rock-blues with contributions from other genres.</p>',
    url: 'https://jonstoreyguitar.wixsite.com/jon-storey'
  },
  {
    name: 'Jonathan Townsend',
    photo: 'jonathan-townsend.jpg',
    biog: '<p>Jonathan\'s performance of acoustic blues styles last festival rightly drew rapturous applause from the discerning audience. Expect early blues to Rory Gallagher and his own compositions.</p>',
    url: 'https://www.facebook.com/jonathan.townsend.773'
  },
  {
    name: 'Lee Signey',
    photo: 'lee-signey.jpg',
    biog: '<p>AKA The Infamous Rooster Fish! <q>Most original country blues I\'ve heard in years</q> &ndash; Kent Duchaine. <q>Highly original blues delivered with passion and aplomb</q> &ndash; Banbury Blues Club. <q>Great voice, great songs</q> &ndash; Richard Harris, Folk & Blues Show.</p>'
  },
  {
    name: 'Lewis Cohen',
    photo: 'lewis-cohen.jpg',
    biog: '<p>Lewis Cohen plays an eclectic mix of acoustic and electric country blues. As a solo performer, Lewis has built a strong reputation at home and abroad thanks to his powerful and versatile vocals and mastery of roots guitar styles which enthral, excite and above all, entertain.</p>',
    url: 'https://www.facebook.com/lewiscohen72'
  },
  {
    name: 'Lewis Cohen & Spencer Couzens',
    photo: 'lewis-cohen.jpg',
    biog: '<p>As a solo performer Lewis built a strong reputation thanks to his powerful and versatile vocals and mastery of roots guitar styles to enthral, excite and above all, entertain.</p><p>Spencer is a without doubt a marvellous, talented and versatile country & blues guitarist.</p>'
  },
  {
    name: 'Liam Ward & Malcolm Thorp',
    photo: 'liam-ward-malcolm-thorp.jpg',
    biog: '<p>Combine the authentic blues sound with rich lyrical originals to serve up a modern take on the classic harp-guitar duo. Together these young men will take you on a compelling and memorable musical journey.</p>',
    url: 'https://www.liamwardmusic.com/ward-thorne'
  },
  {
    name: 'Mark Harrison & Charles Benfield',
    photo: 'mark-harrison-charles-benfield.jpg',
    biog: '<p>Each song is a snapshot of life or has a story to tell, like a 3-minute film or novel. Mark Harrison, one of the most original and interesting singer-guitarists around, brings his unique music back to Swanage Blues Festival, this time with singer and double bassist Charles Benfield.</p>',
    url: 'https://www.markharrisonrootsmusic.com/'
  },
  {
    name: 'Open Mic with Andy Bradshaw',
    biog: '<p>A fantastic opportunity for musicians, and music lovers, to enjoy some great tunes. A supportive, fun and encouraging event for people to share their talents and express themselves in front of a live audience.</p><p><a href=\'https://www.swanage-blues.org/default.aspx?p=festivalartists\'>Participation details</a></p>'
  },
  {
    name: 'Pete Harris & Jon Vaughan',
    photo: 'pete-harris-jon-vaughan.jpg',
    biog: '<p>Pete & Jon play Ragtime with a hint of Gospel and Americana.</p>'
  },
  {
    name: 'Pete Harris & Ray Drury',
    photo: 'pete-harris-ray-drury.jpg',
    biog: '<p>Top bluesman, great voice, great guitar, great band leader! Pete & Ray play blues, soul and rock\'n\'roll.</p>'
  },
  {
    name: 'Pete Harris Blues Band with Jon Vaughan & Ray Drury',
    photo: 'pete-harris-band.jpg',
    biog: '<p>The Pete Harris Blues Band plays Chicago-style Blues with both Ray and Jon plus Henk Leerink on bass and Brian Wright on drums.</p>',
    url: 'https://www.facebook.com/pete.harris.33'
  },
  {
    name: 'Ray Drury & Jon Walsh',
    photo: 'jon-walsh.jpg',
    biog: '<p>Jon\'s ability to play guitar, sing, and write his own songs demonstrates his deep connection to jazz and blues, and loves to express himself through his art.</p><p><a href=\'https://www.raydrury.co.uk/\'>Ray Drury</a> is an incredibly talented and versatile keyboardist! With a wide range of styles and moods, he is clearly able to adapt to different genres of music, including soul, blues, jazz, funk, and more.</p>'
  },
  {
    name: 'Robert Hokum',
    photo: 'robert-hokum.jpg',
    biog: '<p>An informal but up-tempo, goodtime, foot-tappin acoustic Blues session with Bob, Geoff Garbow and the <a href=\'https://www.facebook.com/thegreatwestgroove\'>Great West Groove</a> to kick off the weekend!</p>',
    url: 'http://www.roberthokum.co.uk/'
  },
  {
    name: 'Robert Hokum\'s Acoustic Blues Bonanza',
    biog: '<p>Acoustic blues led by Robert Hokum, with Robert Hokum, Tim Staffell, Hugh Budden, Paul Cook and David Stone &ndash; all bandleaders in their own right &ndash; get together for a mega \'Revue style\' blues gig backed by <a href=\'https://www.facebook.com/thegreatwestgroove\'>Great West Groove</a> rhythm section of Paul White & Steve King.</p>',
    url: 'http://www.roberthokum.co.uk/'
  },
  {
    name: 'Robert Hokum\'s Electric Blues Bonanza',
    biog: '<p>Electric blues led by Robert Hokum, with Robert Hokum, Tim Staffell, Hugh Budden, Paul Cook and David Stone &ndash; all bandleaders in their own right &ndash; get together for a mega \'Revue style\' blues gig backed by <a href=\'https://www.facebook.com/thegreatwestgroove\'>Great West Groove</a> rhythm section of Paul White & Steve King.</p>',
    url: 'http://www.roberthokum.co.uk/'
  },
  {
    name: 'The Fabulous Duck Brothers',
    photo: 'fabulous-duck-brothers.jpg',
    biog: '<p>The Fabulous Duck Bros are a collection of professional and experienced musicians that wish to pay tribute to their love and appreciation of the solo career of Eric Clapton. Fronted by long term Clapton fan Phil Astles, the band concentrate on the songs produced by Eric throughout his long career including his hits from the 80\'s, 90\'s and modern era.</p><p><q>Light and shade throughout every number and the volume just about as perfect as possible</q> <q>Close your eyes and it\'s like Eric and his band are in the room</q>.</p>'
  },
  {
    name: 'The Milk Men',
    photo: 'the-milk-men.jpg',
    biog: '<p>The Milk Men is a band made up from the cream of British R\'n\'B talent and pedigree. With members of the Mustangs and Pirates on board, the band draws its influences from a wide range of classic bands from Dr Feelgood to Fleetwood Mac. Their original music is classic blues rock, but always played with attack, energy, melody and a sense of fun. Their latest album <i>Spin The Bottle</i>, has received rave reviews from the critics and looks set to cement their place at the forefront of the UK Blues Rock music scene.</p>',
    url: 'https://www.themilkmenmusic.com/'
  },
  {
    name: 'The Million Dollar Bash',
    biog: '<p>George Hall and Robbie McIntosh (ex-Pretenders and Wings) on guitar, Chris \'Kipper\' Roberts and Roye Membury on vocals, Chris Lonergan bass, Ady Millward vocals & drums, Thomas Hughes vocals & keyboards, all celebrate the fine music of Bob Dylan and The Band in their own unique style, with some blues favourites thrown in!</p>',
    url: 'https://www.facebook.com/groups/208460715834039'
  },
  {
    name: 'The Mustangs',
    photo: 'the-mustangs.jpg',
    biog: '<p>With over 20 years together, the Mustangs are one of the most established and best-loved blues rock bands in the UK. They have toured Europe, won awards and even played Glastonbury. The band\'s jam-packed nights in Swanage have become tradition, with the band playing a huge range of songs from originals, rock, blues and even often improvising covers and requests from the audience. Perfect let your hair down fun.</p>',
    url: 'https://www.themustangsband.co.uk/'
  },
  {
    name: 'The Robin Bibi Band',
    photo: 'robin-bibi.271.jpg',
    width: '720',
    height: '271',
    biog: '<p>Explosive, passionate, dynamic and entertaining! Stalwart of UK Blues Rock, award winning singer guitarist Robin Bibi is an amazing crowd puller who has played every Swanage Blues Festival since 2007.</p>',
    url: 'https://robinbibiband.co.uk/'
  },
  {
    name: 'The Robin Bibi Band\'s Electric Jam Session',
    biog: '<p>Some of the finest impromptu music of the weekend with one of the best <i>Jam Masters</i> I\'ve ever seen. Check in with Robin at the Jam Sessions, drummers bring your own sticks.</p>'
  },
  {
    name: 'Thomas Heppell Band',
    photo: 'thomas-heppell.jpg',
    biog: '<p>Thomas Heppell is a Berkshire based musician who performs Blues, Jazz and Rock & Roll solo or in his band, alongside his own compositions.</p>',
    url: 'https://thomasheppell.wixsite.com/thomasheppellmusic'
  },
  {
    name: 'Tommy Allen Band',
    photo: 'tommy-allen.jpg',
    biog: '<p>The heart of the band and their music ventures beyond the blues stereotypes with their contemporary guitar driven gutsy blues rock, that inspires the soul. The bands music is rooted within the blues through Tommy\'s own influences, for example, Robert Johnson and BB King to name a few. However, it\'s in Tommy\'s own interpretation of these artists that the crossover really begins to take place and it\'s his individual adaptation that adds a distinct edge to his music.</p>',
    url: 'https://tommyallenmusic.com/tommy-allen-band/'
  },
  {
    name: 'Tommy Allen Duo with Jon Vaughan',
    photo: 'tommy-allen-jon-vaughan.jpg',
    biog: '<p>Tommy Allen covering vocals, guitar and foot drums. If harmonica blues is more your flavour then Jon Vaughan with his soulful tone, crying out Big Walter Horton and Sonny Boy Williamson, will please your ears and leave you wanting more.</p>',
    url: 'https://tommyallenmusic.com/'
  },
  {
    name: 'Tommy Allen Duo with Ray Dury',
    photo: 'tommy-allen.jpg',
    biog: '<p>Tommy Allen covering vocals, guitar and foot drums, with Ray Drury, who, with his amazing piano skills, will keep you on the dance floor boogying till the sun comes up.</p>',
    url: 'https://tommyallenmusic.com/'
  },
  {
    name: 'Vince Lee & Sophie Lord',
    photo: 'vince-lee-sophie-lord.jpg',
    biog: '<p>A voice, a guitar and a double bass… some of their YouTube videos have achieved over 500,000 views in just a few days! A variety of blues-based material and all excellent.</p>',
    url: 'https://www.youtube.com/@vinceleeblues'
  },
  {
    name: 'Vince Lee & the Big Combo',
    photo: 'vince-lee.720.jpg',
    biog: '<p>A variety of blues, R\'n\'B, swing, jazz, slide and more from this excellent guitarist singer with his band. Come see for yourself!</p>',
    url: 'http://www.vinceleebigcombo.co.uk/'
  },
  {
    name: 'Will Killeen',
    photo: 'will-killeen.jpg',
    biog: '<p>Celtic roots, American blues, Dylan classics by a unique singer/guitarist.</p>',
    url: 'http://willkilleen.weebly.com/'
  },
  {
    name: 'Zoë Schwarz Blue Commotion',
    photo: 'zoe-schwartz.jpg',
    biog: '<p>Vibrant and melodic funky rocking blues featuring Rob Koral &ndash; guitar, Pete Whittaker &ndash; Hammond-organ, Dave Mayne &ndash; drums complimenting the commanding vocal delivery of Zoë Schwarz. The band refresh the blues genre with eclectic arrangements, virtuosic playing and vocal prowess; expect an exciting live set based around rootsy original songs, strong catchy riffs and exciting grooves, they mix old school tradition with contemporary flare and sophistication. <q>Powerful singing and a stylish performer, great guitar work, phenomenal Hammond… a great set</q> &ndash; Live at Carlisle Blues & Rock Festival, Blues Matters</p>',
    url: 'https://www.zoeschwarzmusic.com/'
  }
];

  const imageFormatTest = (_ => {
    
    const testData = {
      avif: 'data:image/avif;base64,AAAAHGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZgAAAPBtZXRhAAAAAAAAAChoZGxyAAAAAAAAAABwaWN0AAAAAAAAAAAAAAAAbGliYXZpZgAAAAAOcGl0bQAAAAAAAQAAAB5pbG9jAAAAAEQAAAEAAQAAAAEAAAEUAAAAFQAAAChpaW5mAAAAAAABAAAAGmluZmUCAAAAAAEAAGF2MDFDb2xvcgAAAABoaXBycAAAAElpcGNvAAAAFGlzcGUAAAAAAAAAAQAAAAEAAAAOcGl4aQAAAAABCAAAAAxhdjFDgQAcAAAAABNjb2xybmNseAABAAEAAQAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB1tZGF0EgAKBxgADlgICAkyCB/xgAAghQm0',
      webp: 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA'
    }

    const setImg = format => {

      // Format supported... do something!
      for (const artist of artistsArr) {
        if (!artist.photo) continue;
        artist.photo = imgFolder + artist.photo.replace('.jpg', '.' + format);
      }

      // Add a class to the <html> so CSS can enjoy smaller images too.
      d.documentElement.classList.add(format + 'Supported');
    };

    const webpTest = _ => {
      const webp = new Image();
      webp.addEventListener('load', _ => setImg('webp'), {once: true});
      // Is already .jpg, no error fallback required.
      webp.src = testData.webp;
    };

    const avif = new Image();
    avif.addEventListener('load', _ => setImg('avif'), {once: true});
    avif.addEventListener('error', webpTest, {once: true});
    avif.src = testData.avif;
  })();

  function generatePhoto(artist) {
    // Max width: 1049px @ 1920 * 200%
    if (!artist.photo) return false;
    const image = d.createElement('img');
    image.width = artist.width || '720';
    image.height = artist.height || '480';
    image.alt = artist.name;
    image.addEventListener('load', e => {
      e.target.classList.add('show');
    }, {once: true});
    image.src = artist.photo;
    return image;
  }
  
  function closeButton(summary) {
    const button = document.createElement('button');
    button.textContent = 'Close Artist';
    button.addEventListener('click', e => {
      summary.click();
      summary.focus();
    });
    return button;
  }
  
  // function closeDetails() {
  //   // If screen-width < 480 then close any open details
  //   if (!window.matchMedia('(min-width: 30em)').matches) {
  //     const openDetails = content.querySelectorAll('td.artist > details[open]');
  //     console.log(openDetails.length)
  //     for (const details of openDetails) {
  //       details.removeAttribute('open');
  //     }
  //   }
  // }

  function artistSummaryClicked(e) {
    const summary = e.target;
    summary.focus();
    // closeDetails();
    const div = summary.nextElementSibling;
    div.appendChild(closeButton(summary));
    // Fetch image only when it's required.
    const photo = generatePhoto(summary.artist);
    if (!photo) return;
    div.insertBefore(photo, div.children[0]);
    div.insertBefore(closeButton(summary), photo);
  }


  function createArtistDiv(artist) {
    const div = d.createElement('div');
    div.innerHTML = artist.biog || '';
    if (artist.url) {
      const link = d.createElement('a');
      link.href = artist.url;
      link.textContent = artist.name;
      div.appendChild(link);
    }
    return div;
  }


  const artistDetails = content.querySelectorAll('td.artist > details');
  for (const details of artistDetails) {
    const name = details.textContent.trim();
    const artist = artistsArr.find(item => item.name === name);
    if (!artist) continue;

    const div = createArtistDiv(artist);
    const summary = details.querySelector('summary');
    summary.artist = artist;
    summary.addEventListener('click', artistSummaryClicked, {
      once: true
    });
    
    // Not visible, so apply directly
    details.appendChild(div);
  }
};

const externalLinks = _ => {
  const links = document.querySelectorAll('a:not([href^="/"])');
  for (const a of links) {
    a.setAttribute('target', '_blank');
    a.setAttribute('rel', 'external');
    a.setAttribute('title', 'Opens in new window');
  }
};


const highlightCurrentHour = _ => {
  const highlightClass = 'current-time';
  const date = new Date;
  const hour = date.getHours() + '';
  const tables = content.querySelectorAll('table');
  for (const table of tables) {
    if (table.dayName !== todayName) continue;
    const tds = table.querySelectorAll('tbody td.time');
    for (const td of tds) {
      const timeHour = td.textContent.trim().substring(0, 2);
      const tr = td.parentElement;
      tr.classList.remove(highlightClass);
      (timeHour === hour) && tr.classList.add(highlightClass);
    }
    break;
  }
};


// WIP
const sortTableByColumnHeading = _ => {
  
  const resetButtonSortDirections = (table, button) => {
    const buttons = table.querySelectorAll('.btn-sort');
    for (const btn of buttons) {
      if (button === btn) continue;
      btn.textContent = btn.textContent.replace('↑', '↕').replace('↓', '↕');
    }
  };

  const getCellValue = (tr, idx) => tr.children[idx].textContent;

  const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2))(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));

  const buttons = content.querySelectorAll('th button');
  for (const btn of buttons) {
    btn.addEventListener('click', event => {
      const th = btn.closest('th');
      const table = btn.closest('table');
      const tbody = table.querySelector('tbody');

      // let sort = btn.getAttribute('aria-label');
      // if (btn.textContent.includes('↕')) {
      //   btn.textContent = btn.textContent.replace('↕', '↑');
      //   sort = '(ascending)';
      // } else {
      //   if (btn.textContent.includes('↑')) {
      //     btn.textContent = btn.textContent.replace('↑', '↓');
      //     sort = '(descending)';
      //   } else {
      //     btn.textContent = btn.textContent.replace('↓', '↑');
      //     sort = '(ascending)';
      //   }
      // }
      // btn.setAttribute('aria-label', sort);
      
      Array.from(tbody.querySelectorAll('tr'))
        .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
        .forEach(tr => tbody.appendChild(tr))
    });
  }
};


const lateLoadGoogleMap = _ => {
  const map_src = 'https://snazzymaps.com/embed/461112';

  const summary = d.querySelector('#map');
  if (!summary) return;
  summary.addEventListener('click', _ => {
    d.querySelector('iframe').src = map_src
  }, {
    once: true
  })
};


// MINIMISE WORK ON THE MAIN THREAD

// Immediate, pre render required:
dateDataFunctions();
tableGeneration();

// ...Release main thread
// No visible updates:

setTimeout(_ => {
  venueDataFunctions();
}, 0);
setTimeout(_ => {
  artistDataFunctions();
}, 0);
setTimeout(_ => {
  externalLinks();
}, 0);

// ...Release main thread
// Delayed outputs:

setTimeout(_ => {
  sortTableByColumnHeading();
  lateLoadGoogleMap();
}, 30);

setTimeout(_ => {
  highlightCurrentHour();
}, 100); // .1 seconds
setInterval(highlightCurrentHour, 60000); // every minute
          </script><!--kg-card-end: html--><p>From <a href="https://codepen.io/2kool2/pen/NWLGYbv?ref=ghost-o-matic.com">https://codepen.io/2kool2/pen/NWLGYbv</a></p>]]></content:encoded></item><item><title><![CDATA[Accordions - One Open at a Time]]></title><description><![CDATA[Multiple accordions on a post, but only one is open at a time...]]></description><link>https://ghost-o-matic.com/accordions-one-open-at-a-time/</link><guid isPermaLink="false">65eb378455e87ebe7b833a0d</guid><category><![CDATA[Javascript Snippets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Wed, 15 Mar 2023 10:50:46 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: html--><style>
.flex {
  display: flex;
  gap: 1rem;
}
.flex > div {
  margin: 0;
  width: 33%;
  border: 1px solid #333;
  background-color: rgb(0,0,0,.0625);
  padding: 0.25rem .5rem;
}
</style><!--kg-card-end: html--><!--kg-card-begin: html-->  <div class="flex">
  
    <div class="accordion">

      <details>
        <summary>One</summary>
        <div aria-label="Yes">&#x1F44D;</div>
      </details>

      <details>
        <summary>Two</summary>
        <div aria-label="Yes, yes">&#x1F44D;&#x1F44D;</div>
      </details>

      <details>
        <summary>Three</summary>
        <div aria-label="Yes, yes, yes">&#x1F44D;&#x1F44D;&#x1F44D;</div>
      </details>

    </div>

    <div class="accordion" lang="es">

      <details>
        <summary>Uno</summary>
        <div aria-label="Bueno">&#x1F44C;</div>
      </details>

      <details>
        <summary>Dos</summary>
        <div aria-label="Bueno, bueno">&#x1F44C;&#x1F44C;</div>
      </details>

      <details>
        <summary>Tres</summary>
        <div aria-label="Bueno, bueno, bueno">&#x1F44C;&#x1F44C;&#x1F44C;</div>
      </details>

    </div>

    <div class="accordion" lang="fr">

      <details>
        <summary>Un</summary>
        <div aria-label="Tu g&#xE8;res">&#x1F918;</div>
      </details>

      <details>
        <summary>Deux</summary>
        <div aria-label="Tu g&#xE8;res, tu g&#xE8;res">&#x1F918;&#x1F918;</div>
      </details>

      <details>
        <summary>Trois</summary>
        <div aria-label="Tu g&#xE8;res, tu g&#xE8;res, tu g&#xE8;res">&#x1F918;&#x1F918;&#x1F918;</div>
      </details>

    </div>
    
  </div><!--kg-card-end: html--><!--kg-card-begin: html--><script>
    // JS is required, falls back to default details behaviour
const accordions = (_ => {

  // Class used but could be data attribute or custom element
  const accordionQuery = '.accordion';

  const accordionClicked = event => {
    const summary = event.target;
    if (summary.tagName.toLowerCase() !== 'summary') return;

    const currentDetails = summary.parentElement;
    const accordion = currentDetails.closest(accordionQuery);

    const allOpenDetails = accordion.querySelectorAll('details[open]');
    for (const details of allOpenDetails) {
      
      // But not the clicked summary
      if (details === currentDetails) continue;
      
      details.removeAttribute('open');
    }
  };

  // Consider each group of details (individual accordian)
  const accordions = document.querySelectorAll(accordionQuery);
  for (const accordion of accordions) {
    accordion.addEventListener('click', accordionClicked);
  }

})();
</script><!--kg-card-end: html--><h3 id="the-css">The CSS...</h3><pre><code class="language-CSS">&lt;style&gt;
.flex {
  display: flex;
  gap: 1rem;
}
.flex &gt; div {
  margin: 0;
  width: 33%;
  border: 1px solid #333;
  background-color: rgb(0,0,0,.0625);
  padding: 0.25rem .5rem;
}
&lt;/style&gt;</code></pre><h3 id="the-html">The HTML...</h3><pre><code class="language-HTML">  &lt;div class=flex&gt;
  
    &lt;div class=accordion&gt;

      &lt;details&gt;
        &lt;summary&gt;One&lt;/summary&gt;
        &lt;div aria-label=Yes&gt;&#x1F44D;&lt;/div&gt;
      &lt;/details&gt;

      &lt;details&gt;
        &lt;summary&gt;Two&lt;/summary&gt;
        &lt;div aria-label=&quot;Yes, yes&quot;&gt;&#x1F44D;&#x1F44D;&lt;/div&gt;
      &lt;/details&gt;

      &lt;details&gt;
        &lt;summary&gt;Three&lt;/summary&gt;
        &lt;div aria-label=&quot;Yes, yes, yes&quot;&gt;&#x1F44D;&#x1F44D;&#x1F44D;&lt;/div&gt;
      &lt;/details&gt;

    &lt;/div&gt;

    &lt;div class=accordion lang=es&gt;

      &lt;details&gt;
        &lt;summary&gt;Uno&lt;/summary&gt;
        &lt;div aria-label=Bueno&gt;&#x1F44C;&lt;/div&gt;
      &lt;/details&gt;

      &lt;details&gt;
        &lt;summary&gt;Dos&lt;/summary&gt;
        &lt;div aria-label=&quot;Bueno, bueno&quot;&gt;&#x1F44C;&#x1F44C;&lt;/div&gt;
      &lt;/details&gt;

      &lt;details&gt;
        &lt;summary&gt;Tres&lt;/summary&gt;
        &lt;div aria-label=&quot;Bueno, bueno, bueno&quot;&gt;&#x1F44C;&#x1F44C;&#x1F44C;&lt;/div&gt;
      &lt;/details&gt;

    &lt;/div&gt;

    &lt;div class=accordion lang=fr&gt;

      &lt;details&gt;
        &lt;summary&gt;Un&lt;/summary&gt;
        &lt;div aria-label=&quot;Tu g&#xE8;res&quot;&gt;&#x1F918;&lt;/div&gt;
      &lt;/details&gt;

      &lt;details&gt;
        &lt;summary&gt;Deux&lt;/summary&gt;
        &lt;div aria-label=&quot;Tu g&#xE8;res, tu g&#xE8;res&quot;&gt;&#x1F918;&#x1F918;&lt;/div&gt;
      &lt;/details&gt;

      &lt;details&gt;
        &lt;summary&gt;Trois&lt;/summary&gt;
        &lt;div aria-label=&quot;Tu g&#xE8;res, tu g&#xE8;res, tu g&#xE8;res&quot;&gt;&#x1F918;&#x1F918;&#x1F918;&lt;/div&gt;
      &lt;/details&gt;

    &lt;/div&gt;
    
  &lt;/div&gt;</code></pre><h3 id="the-javascript">The Javascript...</h3><pre><code class="language-Javascript">&lt;script&gt;
    // JS is required, falls back to default details behaviour
const accordions = (_ =&gt; {

  // Class used but could be data attribute or custom element
  const accordionQuery = &apos;.accordion&apos;;

  const accordionClicked = event =&gt; {
    const summary = event.target;
    if (summary.tagName.toLowerCase() !== &apos;summary&apos;) return;

    const currentDetails = summary.parentElement;
    const accordion = currentDetails.closest(accordionQuery);

    const allOpenDetails = accordion.querySelectorAll(&apos;details[open]&apos;);
    for (const details of allOpenDetails) {
      
      // But not the clicked summary
      if (details === currentDetails) continue;
      
      details.removeAttribute(&apos;open&apos;);
    }
  };

  // Consider each group of details (individual accordian)
  const accordions = document.querySelectorAll(accordionQuery);
  for (const accordion of accordions) {
    accordion.addEventListener(&apos;click&apos;, accordionClicked);
  }

})();
&lt;/script&gt;</code></pre><p>From <a href="https://codepen.io/2kool2/pen/poOgxKb?ref=ghost-o-matic.com">https://codepen.io/2kool2/pen/poOgxKb</a></p>]]></content:encoded></item><item><title><![CDATA[Hamburger Menu Using Details-Summary]]></title><description><![CDATA[A hamburger menu built using Details and Summary...]]></description><link>https://ghost-o-matic.com/hamburger-menu-using-details-summary/</link><guid isPermaLink="false">65eb378455e87ebe7b833a0c</guid><category><![CDATA[Javascript Snippets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Wed, 15 Mar 2023 09:04:30 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: html--><style>
/* Start Reset  */
details {
    width: 100%;
    background-color: unset !important;
    padding: unset !important;
    border-radius: unset !important;
    top: unset !important;
}
    
summary {
    background-color: unset !important;
    color: unset !important;
    cursor: pointer !important;
}
/* End Reset */
</style><!--kg-card-end: html--><!--kg-card-begin: html--><style>
    
*, *:after, *:before {
  box-sizing: border-box;
  margin: 0;
}
* + * {
  margin-top: 1rem;
}

/* The mobile nav styles */

/* Enforce list semantics */
nav [role="list"] {
  list-style: none;
  padding-left: 1rem;
  margin: 0;
}

summary {
  border: 1px solid #ccc;
  border-radius: 4px;
  display: inline-block;
  height: 3rem !important;
  line-height: 1;
  list-style: none;
  padding: .5rem !important;
  position: relative;
  text-align: center;
  transition: .4s border-radius ease-out;
  width: 3rem;
  will-change: border-radius;
}
summary span {
  position: relative;
  top: .75rem;
  transition-delay: 0.2s;
  transition-duration: 0s;
}
summary span:before,
summary span:after {
  position: absolute;
  content: '';
}
summary span,
summary span:before,
summary span:after {
  background-color: #000;
  display: block;
  height: .375rem;
  width: 100%;
  will-change: background-color, margin, transform;
}
summary span:before {
  /* margin-top: -.75rem; */
  transform: translateY(-.75rem) rotate(0); 
}
summary span:after {
  /* margin-top: .75rem; */
  transform: translateY(.75rem) rotate(0);
}
summary x {
  bottom: -2.125rem;
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 2em;
  width: 4rem;
  left: 50%;
  letter-spacing: .05em;
  position: absolute;
  text-transform: uppercase;
  transform: translate3d(-50%,0%,0);
}

details[open] > summary {
  border-radius: 100%;
}
details[open] > summary > span {
  background-color: transparent;
  transition-delay: 0.2s;
}
summary span:before {
  transition-delay: 0.2s, 0s;
  transition-duration: 0.2s;
  transition-property: margin, transform;
/*   transition-property: transform; */
}
details[open] > summary span:before {
  margin-top: 0;
  transform: rotate(45deg);
/*   transform: translateY(0) rotate(45deg); */
  transition-delay: 0s, 0.2s;
}
summary span:after {
  transition-delay: 0.2s, 0s;
  transition-duration: 0.2s;
  transition-property: margin, transform;
/*   transition-property: transform; */
}
details[open] > summary span:after {
  margin-top: 0;
  transform: rotate(-45deg);
/*   transform: translateY(0) rotate(-45deg); */
  transition-delay: 0s, 0.2s;
}

nav details {
  display: inline-block;
}
    
nav summary {
    width: auto !important;
    border: none;
    height: auto !important;
    }
    
nav summary:after {
    position: absolute;
    content: '▶';
    padding-left: 5px;
}
    
nav details[open] > summary:after {
    position: absolute;
    content: '▼';
    padding-left: 5px;
}
    
details[open] > summary x {
display: none;
}
        

@media (min-width: 40em) { /* 640px */

  /* Note: dropdowns may use position absolute,
      but was considered beyond scope in this simple demo. */

  nav > details > [role="list"] {
    /* display: flex; */
    gap: 1rem;
    margin-top: 0 !important;
    padding: 0;
  }
  nav > details > ul > li {
    margin-top: 0 !important;
  }
}
</style>

<details>
  <summary>
    <span></span>
    <x>Menu</x>
  </summary>
  <nav>
      <ul role="list">
        <li><a href="#">About us</a></li>
        <li>
          <details>
            <summary>Products</summary>
            <ul role="list">
              <li><a href="#">Product 1</a></li>
              <li><a href="#">Product 2</a></li>
              <li>
                <details>
                  <summary>Sub</summary>
                  <ul role="list">
                    <li><a href="#">Sub 1</a></li>
                    <li><a href="#">Sub 2</a></li>
                  </ul>
                </details>
              </li>
            </ul>
          </details>
        </li>
        <li><a href="#">Insights</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
  </nav>
</details>

<!--kg-card-end: html--><h3 id="the-css">The CSS...</h3><pre><code class="language-CSS">&lt;style&gt;
    
*, *:after, *:before {
  box-sizing: border-box;
  margin: 0;
}
* + * {
  margin-top: 1rem;
}

/* The mobile nav styles */

/* Enforce list semantics */
nav [role=&quot;list&quot;] {
  list-style: none;
  padding-left: 1rem;
  margin: 0;
}

summary {
  border: 1px solid #ccc;
  border-radius: 4px;
  display: inline-block;
  height: 3rem !important;
  line-height: 1;
  list-style: none;
  padding: .5rem !important;
  position: relative;
  text-align: center;
  transition: .4s border-radius ease-out;
  width: 3rem;
  will-change: border-radius;
}
summary span {
  position: relative;
  top: .75rem;
  transition-delay: 0.2s;
  transition-duration: 0s;
}
summary span:before,
summary span:after {
  position: absolute;
  content: &apos;&apos;;
}
summary span,
summary span:before,
summary span:after {
  background-color: #000;
  display: block;
  height: .375rem;
  width: 100%;
  will-change: background-color, margin, transform;
}
summary span:before {
  /* margin-top: -.75rem; */
  transform: translateY(-.75rem) rotate(0); 
}
summary span:after {
  /* margin-top: .75rem; */
  transform: translateY(.75rem) rotate(0);
}
summary x {
  bottom: -2.125rem;
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 2em;
  width: 4rem;
  left: 50%;
  letter-spacing: .05em;
  position: absolute;
  text-transform: uppercase;
  transform: translate3d(-50%,0%,0);
}

details[open] &gt; summary {
  border-radius: 100%;
}
details[open] &gt; summary &gt; span {
  background-color: transparent;
  transition-delay: 0.2s;
}
summary span:before {
  transition-delay: 0.2s, 0s;
  transition-duration: 0.2s;
  transition-property: margin, transform;
/*   transition-property: transform; */
}
details[open] &gt; summary span:before {
  margin-top: 0;
  transform: rotate(45deg);
/*   transform: translateY(0) rotate(45deg); */
  transition-delay: 0s, 0.2s;
}
summary span:after {
  transition-delay: 0.2s, 0s;
  transition-duration: 0.2s;
  transition-property: margin, transform;
/*   transition-property: transform; */
}
details[open] &gt; summary span:after {
  margin-top: 0;
  transform: rotate(-45deg);
/*   transform: translateY(0) rotate(-45deg); */
  transition-delay: 0s, 0.2s;
}

nav details {
  display: inline-block;
}
    
nav summary {
    width: auto !important;
    border: none;
    height: auto !important;
    }
    
nav summary:after {
    position: absolute;
    content: &apos;&#x25B6;&apos;;
    padding-left: 5px;
}
    
nav details[open] &gt; summary:after {
    position: absolute;
    content: &apos;&#x25BC;&apos;;
    padding-left: 5px;
}
    
details[open] &gt; summary x {
display: none;
}
        

@media (min-width: 40em) { /* 640px */

  /* Note: dropdowns may use position absolute,
      but was considered beyond scope in this simple demo. */

  nav &gt; details &gt; [role=&quot;list&quot;] {
    /* display: flex; */
    gap: 1rem;
    margin-top: 0 !important;
    padding: 0;
  }
  nav &gt; details &gt; ul &gt; li {
    margin-top: 0 !important;
  }
}
&lt;/style&gt;</code></pre><h3 id="the-html">The HTML...</h3><pre><code class="language-HTML">&lt;details&gt;
  &lt;summary&gt;
    &lt;span&gt;&lt;/span&gt;
    &lt;x&gt;Menu&lt;/x&gt;
  &lt;/summary&gt;
  &lt;nav&gt;
      &lt;ul role=list&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;About us&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;
          &lt;details&gt;
            &lt;summary&gt;Products&lt;/summary&gt;
            &lt;ul role=list&gt;
              &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Product 1&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Product 2&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;
                &lt;details&gt;
                  &lt;summary&gt;Sub&lt;/summary&gt;
                  &lt;ul role=list&gt;
                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Sub 1&lt;/a&gt;&lt;/li&gt;
                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Sub 2&lt;/a&gt;&lt;/li&gt;
                  &lt;/ul&gt;
                &lt;/details&gt;
              &lt;/li&gt;
            &lt;/ul&gt;
          &lt;/details&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Insights&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
  &lt;/nav&gt;
&lt;/details&gt;


&lt;script&gt;
    console.clear();

// The mobile disclosure button only:
// Progressive enhancement, works without JS too.

const responsiveMenuButton = (document =&gt; {
  &apos;use strict&apos;;

  const minViewportWidth = &apos;40em&apos;; // @ 640px

  const details = document.querySelector(&apos;nav &gt; details&apos;);
  if (!details) return;

  const summary = details.querySelector(&apos;summary&apos;);
  if (!summary) return;

  const mediaQuery = window.matchMedia(`(min-width: ${minViewportWidth})`);
  let isSmallScreen = !mediaQuery.matches;

  const showMenu = _ =&gt; {

    // Edge case: Orientation may change viewport width without moving focus
    const isSummaryFocused = !!details.querySelector(&apos;summary:is(:focus)&apos;);

    details.open = true;
    summary.hidden = true;

    if (isSummaryFocused) {
      const firstLink = details.querySelector(&apos;a[href]&apos;);
      firstLink &amp;&amp; firstLink.focus();
    }
  };

  const hideMenu = _ =&gt; {

    // Edge case: Orientation may change viewport width without moving focus
    const isMenuLinkFocused = !!details.querySelector(&apos;ul:is(:focus-within)&apos;);

    details.removeAttribute(&apos;open&apos;);
    summary.removeAttribute(&apos;hidden&apos;);

    isMenuLinkFocused &amp;&amp; summary.focus();
  };

  const controlResponsiveMenu = event =&gt; {
    if (isSmallScreen &amp;&amp; event.matches) {
      showMenu();
      isSmallScreen = true;
    }

    isSmallScreen &amp;&amp; !event.matches &amp;&amp; hideMenu();

    !isSmallScreen &amp;&amp; event.matches &amp;&amp; showMenu();

    if (!isSmallScreen &amp;&amp; !event.matches) {
      hideMenu();
      isSmallScreen = false;
    }
  };

  mediaQuery.addListener(controlResponsiveMenu);
  controlResponsiveMenu(mediaQuery);
})(document);
&lt;/script&gt;</code></pre><h3 id="the-javascript">The Javascript...</h3><pre><code class="language-JAVASCRIPT">&lt;script&gt;
    console.clear();

// The mobile disclosure button only:
// Progressive enhancement, works without JS too.

const responsiveMenuButton = (document =&gt; {
  &apos;use strict&apos;;

  const minViewportWidth = &apos;40em&apos;; // @ 640px

  const details = document.querySelector(&apos;nav &gt; details&apos;);
  if (!details) return;

  const summary = details.querySelector(&apos;summary&apos;);
  if (!summary) return;

  const mediaQuery = window.matchMedia(`(min-width: ${minViewportWidth})`);
  let isSmallScreen = !mediaQuery.matches;

  const showMenu = _ =&gt; {

    // Edge case: Orientation may change viewport width without moving focus
    const isSummaryFocused = !!details.querySelector(&apos;summary:is(:focus)&apos;);

    details.open = true;
    summary.hidden = true;

    if (isSummaryFocused) {
      const firstLink = details.querySelector(&apos;a[href]&apos;);
      firstLink &amp;&amp; firstLink.focus();
    }
  };

  const hideMenu = _ =&gt; {

    // Edge case: Orientation may change viewport width without moving focus
    const isMenuLinkFocused = !!details.querySelector(&apos;ul:is(:focus-within)&apos;);

    details.removeAttribute(&apos;open&apos;);
    summary.removeAttribute(&apos;hidden&apos;);

    isMenuLinkFocused &amp;&amp; summary.focus();
  };

  const controlResponsiveMenu = event =&gt; {
    if (isSmallScreen &amp;&amp; event.matches) {
      showMenu();
      isSmallScreen = true;
    }

    isSmallScreen &amp;&amp; !event.matches &amp;&amp; hideMenu();

    !isSmallScreen &amp;&amp; event.matches &amp;&amp; showMenu();

    if (!isSmallScreen &amp;&amp; !event.matches) {
      hideMenu();
      isSmallScreen = false;
    }
  };

  mediaQuery.addListener(controlResponsiveMenu);
  controlResponsiveMenu(mediaQuery);
})(document);
&lt;/script&gt;</code></pre><p>From <a href="https://codepen.io/2kool2/pen/bGxvQaO?ref=ghost-o-matic.com">https://codepen.io/2kool2/pen/bGxvQaO</a></p>]]></content:encoded></item><item><title><![CDATA[Responsive Details-Summary Menu]]></title><description><![CDATA[A mobile-responsive multi-level click-down menu using Details-Summary...]]></description><link>https://ghost-o-matic.com/responsive-details-summary-menu/</link><guid isPermaLink="false">65eb378455e87ebe7b833a0b</guid><category><![CDATA[Javascript Snippets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Wed, 15 Mar 2023 03:35:14 GMT</pubDate><content:encoded><![CDATA[<p>Expand and contract this window around the 640px width mark...</p><!--kg-card-begin: html--><style>
/* Start Reset  */
details {
    width: 100%;
    background-color: unset !important;
    padding: unset !important;
    border-radius: unset !important;
    top: unset !important;
}
    
summary {
    background-color: unset !important;
    color: unset !important;
    padding: unset !important;
    margin: unset !important;
    cursor: pointer !important;
    border-radius: unset !important;
}
/* End Reset */
</style><!--kg-card-end: html--><!--kg-card-begin: html--><style>

/* The mobile nav styles */

/* Enforce list semantics */
nav [role="list"] {
  list-style: none;
  padding-left: 1rem;
}

nav details {
  display: inline-block;
}

@media (min-width: 40em) { /* 640px */

  /* Note: dropdowns may use position absolute,
      but was considered beyond scope in this simple demo. */

  nav > details > [role="list"] {
    display: flex;
    gap: 1rem;
    margin-top: 0 !important;
    padding: 0;
  }
  nav > details > ul > li {
    margin-top: 0 !important;
  }
}
</style>

<nav>
    <details>
      <summary>Mobile menu</summary>
      <ul role="list">
        <li><a href="#">About us</a></li>
        <li>
          <details>
            <summary>Products</summary>
            <ul role="list">
              <li><a href="#">Product 1</a></li>
              <li><a href="#">Product 2</a></li>
              <li>
                <details>
                  <summary>Sub</summary>
                  <ul role="list">
                    <li><a href="#">Sub 1</a></li>
                    <li><a href="#">Sub 2</a></li>
                  </ul>
                </details>
              </li>
            </ul>
          </details>
        </li>
        <li><a href="#">Insights</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
    </details>
  </nav>


<script>
    console.clear();

// The mobile disclosure button only:
// Progressive enhancement, works without JS too.

const responsiveMenuButton = (document => {
  'use strict';

  const minViewportWidth = '40em'; // @ 640px

  const details = document.querySelector('nav > details');
  if (!details) return;

  const summary = details.querySelector('summary');
  if (!summary) return;

  const mediaQuery = window.matchMedia(`(min-width: ${minViewportWidth})`);
  let isSmallScreen = !mediaQuery.matches;

  const showMenu = _ => {

    // Edge case: Orientation may change viewport width without moving focus
    const isSummaryFocused = !!details.querySelector('summary:is(:focus)');

    details.open = true;
    summary.hidden = true;

    if (isSummaryFocused) {
      const firstLink = details.querySelector('a[href]');
      firstLink && firstLink.focus();
    }
  };

  const hideMenu = _ => {

    // Edge case: Orientation may change viewport width without moving focus
    const isMenuLinkFocused = !!details.querySelector('ul:is(:focus-within)');

    details.removeAttribute('open');
    summary.removeAttribute('hidden');

    isMenuLinkFocused && summary.focus();
  };

  const controlResponsiveMenu = event => {
    if (isSmallScreen && event.matches) {
      showMenu();
      isSmallScreen = true;
    }

    isSmallScreen && !event.matches && hideMenu();

    !isSmallScreen && event.matches && showMenu();

    if (!isSmallScreen && !event.matches) {
      hideMenu();
      isSmallScreen = false;
    }
  };

  mediaQuery.addListener(controlResponsiveMenu);
  controlResponsiveMenu(mediaQuery);
})(document);
</script><!--kg-card-end: html--><h3 id="the-css">The CSS...</h3><pre><code class="language-CSS">&lt;style&gt;

/* The mobile nav styles */

/* Enforce list semantics */
nav [role=&quot;list&quot;] {
  list-style: none;
  padding-left: 1rem;
}

nav details {
  display: inline-block;
}

@media (min-width: 40em) { /* 640px */

  /* Note: dropdowns may use position absolute,
      but was considered beyond scope in this simple demo. */

  nav &gt; details &gt; [role=&quot;list&quot;] {
    display: flex;
    gap: 1rem;
    margin-top: 0 !important;
    padding: 0;
  }
  nav &gt; details &gt; ul &gt; li {
    margin-top: 0 !important;
  }
}
&lt;/style&gt;</code></pre><h3 id="the-html">The HTML...</h3><pre><code class="language-HTML">&lt;nav&gt;
    &lt;details&gt;
      &lt;summary&gt;Mobile menu&lt;/summary&gt;
      &lt;ul role=list&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;About us&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;
          &lt;details&gt;
            &lt;summary&gt;Products&lt;/summary&gt;
            &lt;ul role=list&gt;
              &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Product 1&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Product 2&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;
                &lt;details&gt;
                  &lt;summary&gt;Sub&lt;/summary&gt;
                  &lt;ul role=list&gt;
                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Sub 1&lt;/a&gt;&lt;/li&gt;
                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Sub 2&lt;/a&gt;&lt;/li&gt;
                  &lt;/ul&gt;
                &lt;/details&gt;
              &lt;/li&gt;
            &lt;/ul&gt;
          &lt;/details&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Insights&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/details&gt;
  &lt;/nav&gt;</code></pre><h3 id="the-javascript">The Javascript...</h3><pre><code class="language-JAVASCRIPT">&lt;script&gt;
    console.clear();

// The mobile disclosure button only:
// Progressive enhancement, works without JS too.

const responsiveMenuButton = (document =&gt; {
  &apos;use strict&apos;;

  const minViewportWidth = &apos;40em&apos;; // @ 640px

  const details = document.querySelector(&apos;nav &gt; details&apos;);
  if (!details) return;

  const summary = details.querySelector(&apos;summary&apos;);
  if (!summary) return;

  const mediaQuery = window.matchMedia(`(min-width: ${minViewportWidth})`);
  let isSmallScreen = !mediaQuery.matches;

  const showMenu = _ =&gt; {

    // Edge case: Orientation may change viewport width without moving focus
    const isSummaryFocused = !!details.querySelector(&apos;summary:is(:focus)&apos;);

    details.open = true;
    summary.hidden = true;

    if (isSummaryFocused) {
      const firstLink = details.querySelector(&apos;a[href]&apos;);
      firstLink &amp;&amp; firstLink.focus();
    }
  };

  const hideMenu = _ =&gt; {

    // Edge case: Orientation may change viewport width without moving focus
    const isMenuLinkFocused = !!details.querySelector(&apos;ul:is(:focus-within)&apos;);

    details.removeAttribute(&apos;open&apos;);
    summary.removeAttribute(&apos;hidden&apos;);

    isMenuLinkFocused &amp;&amp; summary.focus();
  };

  const controlResponsiveMenu = event =&gt; {
    if (isSmallScreen &amp;&amp; event.matches) {
      showMenu();
      isSmallScreen = true;
    }

    isSmallScreen &amp;&amp; !event.matches &amp;&amp; hideMenu();

    !isSmallScreen &amp;&amp; event.matches &amp;&amp; showMenu();

    if (!isSmallScreen &amp;&amp; !event.matches) {
      hideMenu();
      isSmallScreen = false;
    }
  };

  mediaQuery.addListener(controlResponsiveMenu);
  controlResponsiveMenu(mediaQuery);
})(document);
&lt;/script&gt;</code></pre><p>From <a href="https://codepen.io/2kool2/pen/JjaLLWb?ref=ghost-o-matic.com">https://codepen.io/2kool2/pen/JjaLLWb</a></p>]]></content:encoded></item><item><title><![CDATA[Pretty Simple Accordions]]></title><description><![CDATA[Altogether in one HTML Card on a post, some simple but pretty multi-colored Accordions...]]></description><link>https://ghost-o-matic.com/pretty-simple-accordions/</link><guid isPermaLink="false">65eb378455e87ebe7b833a0a</guid><category><![CDATA[Javascript Snippets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Wed, 15 Mar 2023 02:34:42 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: html--><style>
/* Start Reset for Conflicts */
summary {
    background-color: unset !important;
    color: unset !important;
    }
 details.accordion {
    padding-left: unset !important;
    margin-top: 0 !important;
  }
/* End Reset for Conflicts */
</style><!--kg-card-end: html--><!--kg-card-begin: html--><details class="accordion">
  <summary>When will payments begin?</summary>
  <p>When we receive your agreement, we send you a letter or email confirming the original terms of your agreement. This includes your payment amount, balance due, and date your authorized payments begin. Payments will continue until the total balance is paid in full.</p>
</details>

<details class="accordion" style="--color-accent: royalblue;">
  <summary>I forgot my username/password. How do I login?</summary>
  <p>To retrieve your username or password, visit this link. If you&apos;ve forgotten your username, it will be sent to the email address associated with your account. If you&#x2019;ve forgotten your password, a link will be emailed to the email address associated with your account that allows you to reset your password.</p>
</details>

<details class="accordion" style="--color-accent: aquamarine;">
  <summary>How do I upgrade, downgrade, or cancel a subscription?</summary>
  <p>We offer yearly and monthly plans, which you can read more about on our Pricing page. All our plans are recurring, and if you want to unsubscribe you should cancel your plan before your prepaid period ends (term end). You can cancel your subscription under the Account section on the Plan &amp; billing page.</p>
</details>

<style>
  details.accordion {
    --color-accent: #222;
    margin-bottom: 1em;
    border-radius: 5px;
    padding: 1.5em;
    position: relative;
    padding-left: 3.5em !important;
    border-left: 5px solid var(--color-accent);
    overflow: hidden;
    width: auto;
  }

  details.accordion::before {
    background-color: var(--color-accent);
    opacity: 0.1;
    content: "";
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
  }

  details.accordion summary {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  details.accordion summary::marker {
    display: none;
  }

  details.accordion summary::before {
    position: absolute;
    content: '+';
    left: 1.5rem;
    color: #000;
    font-weight: bold;
    cursor: pointer;
  }

  details.accordion[open] summary::before {
    transform: rotate(45deg);
  }

  details.accordion[open] summary {
    font-weight: 700;
  }
</style><!--kg-card-end: html--><h3 id="the-css">The CSS...</h3><pre><code class="language-CSS">&lt;style&gt;
  details.accordion {
    --color-accent: #222;
    margin-bottom: 1em;
    border-radius: 5px;
    padding: 1.5em;
    position: relative;
    padding-left: 3.5em;
    border-left: 5px solid var(--color-accent);
    overflow: hidden;
    width: auto;
  }

  details.accordion::before {
    background-color: var(--color-accent);
    opacity: 0.1;
    content: &quot;&quot;;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
  }

  details.accordion summary {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  details.accordion summary::marker {
    display: none;
  }

  details.accordion summary::before {
    position: absolute;
    content: &apos;+&apos;;
    left: 1.5rem;
    color: #000;
    font-weight: bold;
    cursor: pointer;
  }

  details.accordion[open] summary::before {
    transform: rotate(45deg);
  }

  details.accordion[open] summary {
    font-weight: 700;
  }
&lt;/style&gt;</code></pre><h3 id="the-html">The HTML...</h3><pre><code class="language-HTML">&lt;details class=&quot;accordion&quot;&gt;
  &lt;summary&gt;When will payments begin?&lt;/summary&gt;
  &lt;p&gt;When we receive your agreement, we send you a letter or email confirming the original terms of your agreement. This includes your payment amount, balance due, and date your authorized payments begin. Payments will continue until the total balance is paid in full.&lt;/p&gt;
&lt;/details&gt;

&lt;details class=&quot;accordion&quot; style=&quot;--color-accent: royalblue;&quot;&gt;
  &lt;summary&gt;I forgot my username/password. How do I login?&lt;/summary&gt;
  &lt;p&gt;To retrieve your username or password, visit this link. If you&apos;ve forgotten your username, it will be sent to the email address associated with your account. If you&#x2019;ve forgotten your password, a link will be emailed to the email address associated with your account that allows you to reset your password.&lt;/p&gt;
&lt;/details&gt;

&lt;details class=&quot;accordion&quot; style=&quot;--color-accent: aquamarine;&quot;&gt;
  &lt;summary&gt;How do I upgrade, downgrade, or cancel a subscription?&lt;/summary&gt;
  &lt;p&gt;We offer yearly and monthly plans, which you can read more about on our Pricing page. All our plans are recurring, and if you want to unsubscribe you should cancel your plan before your prepaid period ends (term end). You can cancel your subscription under the Account section on the Plan &amp; billing page.&lt;/p&gt;
&lt;/details&gt;</code></pre>]]></content:encoded></item><item><title><![CDATA[Expandable Ticker]]></title><description><![CDATA[A Customizable Content Ticker for your Ghost site, either site-wide or just on certain posts or pages...]]></description><link>https://ghost-o-matic.com/expandable-ticker/</link><guid isPermaLink="false">65eb378455e87ebe7b833a09</guid><category><![CDATA[Javascript Snippets]]></category><category><![CDATA[Widgets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Thu, 05 Jan 2023 21:17:19 GMT</pubDate><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<center>
<!--kg-card-end: html-->

<!--kg-card-begin: html-->



<div id="expandticker1" class="expandticker" style="text-align:center">

<div class="expandcontent">
This is ticker content 1
</div>

<div class="expandcontent">
This is ticker content 2
</div>
    
</div>



<!--kg-card-end: html-->

<!--kg-card-begin: html-->
</center>
<!--kg-card-end: html-->
<h3 id="header-code-injection">Header Code Injection...</h3><pre><code class="language-CSS">&lt;style&gt;
.expandticker{
border:1px solid black;
padding:7px;
background:lightyellow;
width: 200px;
height:130px;
overflow-y:auto; /*set DIV to scroll if content exceeds ticker height*/
position: relative;
}

.expandcontent{
display:none;
}

ul.dropdownlist{
font: normal 13px Verdana;
margin: 0;
padding: 0;
position: absolute;
left: 0;
top: 0;
z-index: 100;
list-style-type: none;
background: white;
border: 1px solid #ca431a;
padding: 3px;
}

ul.dropdownlist li a{
display: block;
background: #ffdb8d;
color: black;
text-decoration: none;
padding: 3px 5px 3px 3px;
}

ul.dropdownlist li a:hover{
background: #ffbf6d;
color: black;
}

ul.dropdownlist li.selected a{
background: #ca431a;
color: white;
}
&lt;/style&gt;</code></pre><h3 id="footer-code-injection">Footer Code Injection...</h3><pre><code class="language-Javascript">&lt;script&gt;

/* Expandable Drop Down Ticker
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code
* Last Edited: Jan 25th, 2010
*/

var expandticker={
	buttonhtml: &apos;&lt;img src=&quot;https://ghost-o-matic.com/content/images/2023/01/show-all.webp&quot; style=&quot;width:70px; height:27px; cursor:pointer&quot; /&gt;&apos;, //HTML of &quot;expand&quot; button
	buttonoffset: [5, -10], //offset of button from lower left edge of ticker
	//No need to edit beyond here

	dsetting: {snippetlength:30, manual:false, timers: {rotatepause:3000, fxduration:300}},
	effectfuncts: [&apos;fadeIn&apos;, &apos;slideDown&apos;],

fetchajaxcontent:function($, s){
window.status+=&apos;x&apos;
	clearTimeout(s.playtimer) //clear timers and remove $button, $menu if fetchajaxcontent() is being called more than once
	clearTimeout(s.pausetimer)
	clearTimeout(s.refreshtimer)
	if (s.$button){
		s.$button.remove()
		s.$menu.remove()
	}
	s.$ticker.html(&quot;(Re)Fetching Ticker Contents...&quot;)
	$.ajax({
		url: s.remotecontent[0],
		dataType: &apos;html&apos;,
		error:function(ajaxrequest){
			s.$ticker.html(&apos;Error fetching content.&lt;br /&gt;Server Response: &apos;+ajaxrequest.responseText)
		},
		success:function(content){
			s.$ticker.html(content)
			expandticker.setup($, s)
			if (s.remotecontent[1]&gt;5000) //5 secs minimum time allowed between updates
				s.refreshtimer=setTimeout(function(){expandticker.fetchajaxcontent($, s)}, s.remotecontent[1])
			else if (s.remotecontent[1]&gt;0) //if value is NOT 0 (0=never refetch)
				alert(&quot;Please Enter a value larger than 5 (sec) for the time between Ajax updates&quot;)
		}
	})
},

getmsgtitles:function(s){
	var titlearray=[]
	for (var i=0; i&lt;s.msglength; i++){
		var title=s.$contents.eq(i).attr(&apos;title&apos;) || s.$contents.eq(i).text().substring(0, s.snippetlength)+&apos; ...&apos; //extract snippet of message
		titlearray.push(title)
	}
	return titlearray
},

adddropmenu:function($, s){
	var titles=this.getmsgtitles(s)
	var $lis=$([])
	var $menu=$(&apos;&lt;ul class=&quot;dropdownlist&quot;&gt;&lt;/ul&gt;&apos;)
	for (var i=0; i&lt;s.msglength; i++){ //construct a new LI element for each ticker message title
		$lis=$lis.add($(&apos;&lt;li/&gt;&apos;).html((i+1)+&quot;. &quot;+titles[i]).wrapInner(&apos;&lt;a href=&quot;#message&apos;+(i+1)+&apos;&quot; data-pos=&quot;&apos;+i+&apos;&quot;&gt;&lt;/a&gt;&apos;))
	}
	$menu.append($lis).hide().unbind(&apos;click&apos;).click(function(e){ //go to particular message when menu title is clicked on
		if (e.target.tagName==&quot;A&quot;){
			clearTimeout(s.playtimer)
			s.curmsg=parseInt(e.target.getAttribute(&apos;data-pos&apos;))
			expandticker.selectmsg($, s, s.curmsg)
			if (!s.manual)
				s.playtimer=setTimeout(function(){expandticker.rotatemsg($, s)}, s.timers.rotatepause)
			e.preventDefault()
		}
	})
	$menu.appendTo(document.body)
	$menu.data(&apos;state&apos;, &apos;closed&apos;) //indicate menu is currently closed
	s.$menu=$menu //remember $menu
	s.$menulis=$lis //remember $menu LIs
},

positionbutton:function($, s){
	var toffset=s.$ticker.offset()
	var buttonpos=[toffset.left+this.buttonoffset[0], toffset.top+s.$ticker.outerHeight()+this.buttonoffset[1]]
	s.$button.css({left:buttonpos[0], top:buttonpos[1]})	
},

addexpandbutton:function($, s){
	s.$button=$(this.buttonhtml).css({position:&apos;absolute&apos;, zIndex:1000}).appendTo(document.body) //create expand button, add it to page, and remember it
	this.positionbutton($, s)
	this.adddropmenu($, s)
	s.$button.unbind(&apos;click&apos;).bind(&apos;click&apos;, function(e){ //show menu when expand button is clicked
		s.$menu.css({left:s.$button.css(&apos;left&apos;), top:parseInt(s.$button.css(&apos;top&apos;))-expandticker.buttonoffset[1]}).show()
		s.$menulis.removeClass(&apos;selected&apos;).eq(s.curmsg).addClass(&apos;selected&apos;) //highlight current message within menu
		s.$menu.data(&apos;state&apos;, &apos;open&apos;) //indicate menu is open
		e.stopPropagation()
	})
},


selectmsg:function($, s, selected){
	s.$contents.stop(true,true).hide().eq(selected)[s.effectfunct](s.timers.fxduration, function(){  //animate message into view
		if (this.style &amp;&amp; this.style.removeAttribute)
			this.style.removeAttribute(&apos;filter&apos;) //fix IE clearType problem when animation is fade-in
	})
	s.curmsg=selected
	if (s.$menu.data(&apos;state&apos;)==&quot;open&quot;)
		s.$menulis.removeClass(&apos;selected&apos;).eq(selected).addClass(&apos;selected&apos;) //highlight current message within menu
},

rotatemsg:function($, s){
	if (s.$ticker.data(&apos;state&apos;)==&quot;over&quot;){ //pause ticker onMouseover
		clearTimeout(s.pausetimer)
		s.pausetimer=setTimeout(function(){expandticker.rotatemsg($, s)}, 100)
		return
	}
	s.nextmsg=(s.curmsg&lt;s.msglength-1)? s.curmsg+1 : 0 //go to next message
	this.selectmsg($, s, s.nextmsg)
	s.playtimer=setTimeout(function(){expandticker.rotatemsg($, s)}, s.timers.rotatepause)
},

setup:function($, s){
		s.$contents=s.$ticker.find(&apos;.expandcontent&apos;).hide()
		s.msglength=s.$contents.length
		s.curmsg=0
		expandticker.addexpandbutton($, s)
		expandticker.selectmsg($, s, s.curmsg)
		if (!s.manual){
			s.$ticker.unbind(&apos;mouseenter&apos;).bind(&apos;mouseenter&apos;, function(){$(this).data(&apos;state&apos;, &apos;over&apos;)})
			s.$ticker.unbind(&apos;mouseleave&apos;).bind(&apos;mouseleave&apos;, function(){$(this).data(&apos;state&apos;, &apos;out&apos;)})
			s.playtimer=setTimeout(function(){expandticker.rotatemsg($, s)}, s.timers.rotatepause)
		}	
},
	

init:function(setting){
	jQuery(document).ready(function($){ //fire on DOM ready
		var s=setting
		s=jQuery.extend({}, expandticker.dsetting, s)
		s.timers.rotatepause+=s.timers.fxduration //add slide duration to rotate timer
		s.$ticker=$(&apos;#&apos;+s.id)
		if (s.$ticker.length==0)
			return
		s.effectfunct=s.fx==&quot;fade&quot;? expandticker.effectfuncts[0] : expandticker.effectfuncts[1]
		if (s.remotecontent &amp;&amp; s.remotecontent[0].length&gt;0){
			s.remotecontent[1]=s.remotecontent[1]*1000 //convert units into seconds
			expandticker.fetchajaxcontent($, s)
		}
		else
			expandticker.setup($, s)
		$(window).bind(&apos;load resize&apos;, function(e){ //reposition enlarge images when window has loaded or is resized
			if (s.$button)
				setTimeout(function(){expandticker.positionbutton($, s)}, (e.type==&quot;load&quot;)? 200 : 0)
		})
		$(document).click(function(){
			if (s.$menu){ //hide menu when user clicks anywhere on page
				s.$menu.hide()
				s.$menu.data(&apos;state&apos;, &apos;closed&apos;)
			}
		})
		
	})
}
}
&lt;/script&gt;

&lt;script&gt;

expandticker.init({
	id: &apos;expandticker1&apos;,
	snippetlength: 25,
	fx: &apos;slide&apos;,
	timers: {rotatepause:3000, fxduration:500} //--No comma following last option!
})

&lt;/script&gt;</code></pre>]]></content:encoded></item><item><title><![CDATA[Colors and Gradients]]></title><description><![CDATA[<p>Some useful tools for choosing colors and gradients:</p><ul><li><a href="https://fffuel.co/cccolor/?ref=ghost-o-matic.com" rel="noopener noreferrer">Fuel HSL color picker</a></li><li><a href="https://components.ai/gradient/?ref=ghost-o-matic.com" rel="noopener noreferrer">Gradients | Components AI</a></li><li><a href="https://cssgradient.io/?ref=ghost-o-matic.com" rel="noopener noreferrer">CSS Gradient Generator</a></li></ul>]]></description><link>https://ghost-o-matic.com/colors-and-gradients/</link><guid isPermaLink="false">65eb378455e87ebe7b833a08</guid><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Fri, 16 Dec 2022 14:33:13 GMT</pubDate><content:encoded><![CDATA[<p>Some useful tools for choosing colors and gradients:</p><ul><li><a href="https://fffuel.co/cccolor/?ref=ghost-o-matic.com" rel="noopener noreferrer">Fuel HSL color picker</a></li><li><a href="https://components.ai/gradient/?ref=ghost-o-matic.com" rel="noopener noreferrer">Gradients | Components AI</a></li><li><a href="https://cssgradient.io/?ref=ghost-o-matic.com" rel="noopener noreferrer">CSS Gradient Generator</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Ghost Site Injection-Only Drop Down Menu]]></title><description><![CDATA[Finally! A copy-and-paste drop down menu for Ghost with NO editing of theme files...]]></description><link>https://ghost-o-matic.com/ghost-site-injection-only-drop-down-menu/</link><guid isPermaLink="false">65eb378455e87ebe7b833a07</guid><category><![CDATA[Tips and Tricks]]></category><category><![CDATA[Javascript Snippets]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Wed, 09 Nov 2022 14:36:52 GMT</pubDate><content:encoded><![CDATA[<p>This simple little drop-down menu is ready to drop into the Site Code Injections in the Admin area of the Casper Theme... &#xA0;I posted this in the Ghost Forums too so you can get help <a href="https://forum.ghost.org/t/hover-down-submenus-for-casper-here/34010/22?ref=ghost-o-matic.com">over there if you need it</a> &gt;&gt;</p><p></p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://ghost-o-matic.com/content/images/2022/11/jens-drop-down-desktop.png" width="2000" height="1365" loading="lazy" alt srcset="https://ghost-o-matic.com/content/images/size/w600/2022/11/jens-drop-down-desktop.png 600w, https://ghost-o-matic.com/content/images/size/w1000/2022/11/jens-drop-down-desktop.png 1000w, https://ghost-o-matic.com/content/images/size/w1600/2022/11/jens-drop-down-desktop.png 1600w, https://ghost-o-matic.com/content/images/size/w2400/2022/11/jens-drop-down-desktop.png 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://ghost-o-matic.com/content/images/2022/11/jens-drop-down-mobile.png" width="730" height="1560" loading="lazy" alt srcset="https://ghost-o-matic.com/content/images/size/w600/2022/11/jens-drop-down-mobile.png 600w, https://ghost-o-matic.com/content/images/2022/11/jens-drop-down-mobile.png 730w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>^^ Above is the Desktop view &#x2013; The mobile phone view is over there on the right side --&gt;&gt;&gt;</figcaption></figure><p></p><h2 id="here-goes-the-how-to"><u>Here goes the HOW-TO...</u></h2><p></p><figure class="kg-card kg-image-card"><img src="https://ghost-o-matic.com/content/images/2022/11/ghost-o-matic-simple-drop-down.jpeg" class="kg-image" alt loading="lazy" width="1380" height="896" srcset="https://ghost-o-matic.com/content/images/size/w600/2022/11/ghost-o-matic-simple-drop-down.jpeg 600w, https://ghost-o-matic.com/content/images/size/w1000/2022/11/ghost-o-matic-simple-drop-down.jpeg 1000w, https://ghost-o-matic.com/content/images/2022/11/ghost-o-matic-simple-drop-down.jpeg 1380w" sizes="(min-width: 720px) 720px"></figure><p></p><h3 id="paste-this-into-your-site-header-code-injection">Paste this into your Site Header Code Injection...</h3><pre><code>&lt;style&gt;

li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;] {
	position: relative;
}
li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;] a:after {
	content: &quot;&#x25BC;&quot;;
	padding-left: 5px;
	font-size: 12px;
	color: inherit;
}
li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;] .isHoverDown a:after {
	display:none;
}
li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;]:focus-within &gt; li[class*=&quot;nav-&quot;]:after,
li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;]:hover &gt; li[class*=&quot;nav-&quot;]:after {
	background-color: transparent;
}
li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;]:focus-within .isHoverDown,
li[class*=&quot;nav-&quot;][class*=&quot;--hasHoverDown&quot;]:hover .isHoverDown {
	opacity: 1;
	visibility: visible;
}
.isHoverDown {
	z-index: 1;
	opacity: 0;
	visibility: hidden;
	position: absolute;
	margin: 0;
	max-width: unset;
	list-style: none;
	/* The padding inside the Hover down (the space surrounding the links) */
	padding: 10px;
	/* The rounded corners of the Hover down */
	border-radius: 6px;
	/* The background color of the Hover down */
	background: #000;
    /* The color of the text in the Hover down */
    color: #fff;
}
.isHoverDown a {
    /* The color of the link text in the Hover down */
    color: #fff;
}
.isHoverDown li[class*=&quot;nav-&quot;] {
	margin-right: 0 !important;
}
.isHoverDown li[class*=&quot;nav-&quot;]:not(:last-child) {
	margin-bottom: 0;
    /* Dividers between the Hover down items */
    border-bottom: 1px solid #ddd;
}

/* OPTIONAL: in mobile, left align all menu items and indent submenu items */
    /*
@media (max-width: 991px) {
    #gh-head .gh-head-inner {
        grid-template-columns: 1fr;
    	height: auto;
	}
	.gh-head-open #gh-head .gh-head-menu,
    #gh-head .gh-head-menu .nav {
    	align-items: flex-start;
    	display: flex;
    	flex-direction: column;
        margin: 0 auto;
	}
    .gh-head-menu .nav li {
        text-align: left;
	}
    .gh-head-menu .nav li.hasHoverDown {
        margin: 0;
    	padding: 0;
    	display: flex;
    	flex-direction: column;
    	align-items: flex-start;
	}
    .gh-head-menu ul.isHoverDown {
    	list-style: none;
    	text-align: left;
    	margin: 0;
    	padding: 0 0 0 10px;
	}
    .gh-head-menu ul.isHoverDown li {
    	margin: 0;
    	padding: 0;
    	text-align: left;
	}
    .gh-head-menu ul.isHoverDown li a {
    	font-size: 2rem;
    	line-height: 1.5;
	}
}
    */

&lt;/style&gt;

</code></pre><h3 id="paste-this-into-your-site-footer-code-injection">Paste this into your Site Footer Code Injection...</h3><pre><code class="language-Javascript">&lt;script&gt;
    
(function () {
    const mediaQuery = window.matchMedia(&apos;(max-width: 767px)&apos;);
    
    // IMPORTANT: For themes other than Casper, change the selector just below to select your theme&apos;s header menu selector
    const menu = document.querySelector(&apos;.gh-head-menu&apos;);
    const nav = menu.querySelector(&apos;.nav&apos;);
    if (!nav) return;

    // IMPORTANT: For themes other than Casper, change the selector just below to select your theme&apos;s header logo selector
    const logo = document.querySelector(&apos;.gh-head-logo&apos;);
    const navHTML = nav.innerHTML;

    if (mediaQuery.matches) {
        const items = nav.querySelectorAll(&apos;li&apos;);
        items.forEach(function (item, index) {
            item.style.transitionDelay = 0.03 * (index + 1) + &apos;s&apos;;
        });
    }
    
    const makeHoverdown = function () {
        if (mediaQuery.matches) return;

        var hoverDown_list = [],
        latest_navigation_item,
        // IMPORTANT: For themes other than Casper, change the selector just below to select your theme&apos;s header menu item selector 
        nav_list = document.querySelectorAll(&apos;.gh-head-menu li&apos;);
        var newMenuList = [];
        var menuTree = {};

        nav_list.forEach( (item, index) =&gt; {
            if(item.childNodes[0].innerText.startsWith(&apos;-&apos;)) {
                if(menuTree[newMenuList.length - 1]) {
            menuTree[newMenuList.length - 1].push(item);
                } else {
            menuTree[newMenuList.length - 1] = [item];
            }
        } else {
        newMenuList.push(item);
        }
        });
        
        nav_list = newMenuList.map((item, index) =&gt; {
        if(menuTree[index]) {
            let hoverdown = document.createElement(&apos;ul&apos;);
            hoverdown.className = &apos;isHoverDown&apos;;
            menuTree[index].forEach(child =&gt; {
                hoverDown_item_text = child.childNodes[0].innerText;
                child.childNodes[0].innerText = hoverDown_item_text.replace(&apos;- &apos;, &apos;&apos;);
                hoverdown.appendChild(child);
            });
        item.className += &apos;--hasHoverDown&apos;;
        item.appendChild(hoverdown);
        }
        return item;
        });
    }

    imagesLoaded(logo, function () {
        makeHoverdown();
    });

    window.addEventListener(&apos;resize&apos;, function () {
        setTimeout(function () {
            nav.innerHTML = navHTML;
            makeHoverdown();
        }, 1);
    });

})();
&lt;/script&gt;</code></pre><p>Inspired by the work of ...</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://aspirethemes.com/?ref=ghost-o-matic.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Premium Ghost Themes</div><div class="kg-bookmark-description">Ghost themes that save time and money are simple and easily customizable. Choose a theme for your blog, newsletter, portfolio, or news website.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://aspirethemes.com/favicon.ico" alt><span class="kg-bookmark-author">Aspire Themes</span><span class="kg-bookmark-publisher">Leslie Camacho</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://aspirethemes.com/images/themes/bundle/bundle.png" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Tag Post Archive Template]]></title><description><![CDATA[A duo of templates to display a Tag Collection as an Archive List...]]></description><link>https://ghost-o-matic.com/tag-post-archive-template/</link><guid isPermaLink="false">65eb378455e87ebe7b833a05</guid><category><![CDATA[Templates]]></category><category><![CDATA[Tips and Tricks]]></category><dc:creator><![CDATA[Jen Wallace]]></dc:creator><pubDate>Tue, 04 Oct 2022 13:17:05 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://ghost-o-matic.com/content/images/2022/10/ghost-tag-page-example.png" class="kg-image" alt loading="lazy" width="2000" height="2010" srcset="https://ghost-o-matic.com/content/images/size/w600/2022/10/ghost-tag-page-example.png 600w, https://ghost-o-matic.com/content/images/size/w1000/2022/10/ghost-tag-page-example.png 1000w, https://ghost-o-matic.com/content/images/size/w1600/2022/10/ghost-tag-page-example.png 1600w, https://ghost-o-matic.com/content/images/size/w2400/2022/10/ghost-tag-page-example.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>tag.hbs</p><pre><code class="language-HTML">{{!&lt; default}}

&lt;div class=&quot;gh-page&quot;&gt;
    &lt;div class=&quot;gh-container&quot;&gt;

        {{#tag}}
        &lt;header class=&quot;gh-page-head&quot;&gt;

            &lt;h1&gt;{{name}}&lt;/h1&gt;

            &lt;p&gt;
                {{#if description}}
                    {{description}}
                {{else}}
                    A collection of {{plural ../pagination.total empty=&apos;posts&apos; singular=&apos;% post&apos; plural=&apos;% posts&apos;}}
                {{/if}}
            &lt;/p&gt;

        &lt;/header&gt;
        {{/tag}}

        &lt;div class=&quot;gh-content&quot;&gt;
        {{#foreach posts}}

            {{&gt; &quot;card&quot;}} {{!-- partials/postlist-item.hbs --}}

        {{/foreach}}
        &lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;</code></pre><p>partials/postlist-item.hbs</p><pre><code class="language-HTML">&lt;a href=&quot;{{url}}&quot; class=&quot;gh-postlist-item&quot;&gt;
    &lt;article&gt;
        &lt;h2 class=&quot;gh-postlist-item-title&quot;&gt;{{title}}&lt;/h2&gt;
        &lt;time class=&quot;gh-postlist-item-date&quot; datetime=&quot;{{date format=&quot;YYYY-MM-DD&quot;}}&quot;&gt;{{date format=&quot;D MMM YYYY&quot;}}&lt;/time&gt;
        &lt;span class=&quot;gh-postlist-item-duration&quot;&gt;{{reading_time}}&lt;/span&gt;
        &lt;div class=&quot;right-arrow&quot;&gt;&lt;i class=&quot;fa fa-arrow-right&quot;&gt;&lt;/i&gt;&lt;/div&gt;
    &lt;/article&gt;
&lt;/a&gt;</code></pre>]]></content:encoded></item></channel></rss>