Open demo

CSS code

HTML
<div><span class="lbl">Contact card with an illustrated map, address and hours</span>
<section class="lc lc-card" aria-labelledby="lc-rosa-title">
  <div class="lm-map">
    <svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b8d4e3"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b8d4e3" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b8d4e3" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b8d4e3"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg>
    <span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span><span class="lm-tag" aria-hidden="true">Atelier Rosa</span>
  </div>
  <div class="lc-body">
    <p class="lc-kicker">Visit the studio</p>
    <h2 id="lc-rosa-title">Atelier Rosa, Bairro Alto</h2>
    <address>Rua da Rosa 112, ground floor<br>1200-388 Lisboa, Portugal</address>
    <dl class="lc-hours"><dt>Tue–Fri</dt><dd>10:00–19:00</dd><dt>Saturday</dt><dd>10:00–14:00</dd><dt>Sun–Mon</dt><dd>Closed</dd></dl>
    <p class="lc-contact"><a href="tel:+351213450112">+351 213 450 112</a><a href="mailto:[email protected]">[email protected]</a></p>
    <div class="lc-actions"><a class="lc-btn" href="https://www.openstreetmap.org/directions?route=%3B38.7130%2C-9.1450" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M3 11l18-8-8 18-2-8z"/></svg>Get directions<span class="sr-only"> (opens in a new tab)</span></a><a class="lc-btn is-ghost" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">Open in OpenStreetMap<span class="sr-only"> (opens in a new tab)</span></a></div>
  </div>
</section></div>
<div><span class="lbl">Office cards with a mini map each</span>
<section class="lc" aria-label="Our offices">
  <ul class="lc-trio" style="list-style:none">
    <li class="lc-office"><div class="lm-map"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b9d3e8"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b9d3e8" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b9d3e8" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b9d3e8"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="lc-o"><h3>London</h3><address>Studio 4, 21 Hoxton Square<br>London N1 6NN, United Kingdom</address><p>Mon–Fri 9:00–17:30</p><a href="https://www.openstreetmap.org/?mlat=51.5280&mlon=-0.0820#map=17/51.5280/-0.0820" target="_blank" rel="noopener">View London on the map<span class="sr-only"> (opens in a new tab)</span></a></div></li>
    <li class="lc-office"><div class="lm-map"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#bcd8e6"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#bcd8e6" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#bcd8e6" stroke-width="9" stroke-linecap="round"/>
      <g fill="#bcd8e6"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="lc-o"><h3>Lisbon</h3><address>Rua da Rosa 112, 2.º andar<br>1200-388 Lisboa, Portugal</address><p>Mon–Fri 9:30–18:00</p><a href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">View Lisbon on the map<span class="sr-only"> (opens in a new tab)</span></a></div></li>
    <li class="lc-office"><div class="lm-map"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b5cfe6"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b5cfe6" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b5cfe6" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b5cfe6"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="lc-o"><h3>Toronto</h3><address>401 Richmond Street West, Suite 210<br>Toronto ON M5V 3A8, Canada</address><p>Mon–Fri 9:00–17:00</p><a href="https://www.openstreetmap.org/?mlat=43.6480&mlon=-79.3950#map=17/43.6480/-79.3950" target="_blank" rel="noopener">View Toronto on the map<span class="sr-only"> (opens in a new tab)</span></a></div></li>
  </ul>
</section></div>
<div><span class="lbl">Privacy-friendly click-to-load OpenStreetMap embed</span>
<section class="lc" aria-labelledby="lc-embed-title">
  <div class="lm-facade" data-map-facade data-src="https://www.openstreetmap.org/export/embed.html?bbox=-9.1520%2C38.7095%2C-9.1380%2C38.7165&layer=mapnik&marker=38.7130%2C-9.1450" data-title="Map of Atelier Rosa, Rua da Rosa 112, Lisbon, on OpenStreetMap">
    <div data-map-preview class="lm-preview"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b8d4e3"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b8d4e3" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b8d4e3" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b8d4e3"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg></div>
    <div class="lm-consent">
      <div class="lc-panel">
        <h3 id="lc-embed-title">Show the interactive map?</h3>
        <p>The map is loaded from OpenStreetMap, which will receive your IP address. Nothing is loaded until you choose.</p>
        <div class="lc-actions"><button class="lc-btn" type="button" data-map-load>Load map</button><a class="lc-btn is-ghost" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">Open in a new tab<span class="sr-only"> (opens in a new tab)</span></a></div>
        <small>Map data © OpenStreetMap contributors</small>
      </div>
    </div>
  </div>
</section></div>
CSS
/* Location cards: illustrated map (inline SVG, not to scale) with a centred pin, and a click-to-load OpenStreetMap facade. */
.lm-map{position:relative;overflow:hidden;background:#f4e9dc;min-height:180px}
.lm-map>svg{position:absolute;inset:0;width:100%;height:100%}
.lm-pin{position:absolute;left:50%;top:50%;width:38px;height:47px;transform:translate(-50%,-100%);filter:drop-shadow(0 4px 5px rgba(42,29,22,.35))}
.lm-pin svg{display:block;width:100%;height:100%}
.lm-pin::before{content:"";position:absolute;left:50%;bottom:-6px;width:22px;height:8px;border-radius:50%;background:rgba(42,29,22,.25);transform:translateX(-50%);z-index:-1}
.lm-tag{position:absolute;left:50%;top:calc(50% + 10px);transform:translateX(-50%);padding:5px 10px;border-radius:9px;background:#2a1d16;color:#fff;font-size:.75rem;font-weight:700;white-space:nowrap}
.lm-facade{position:relative;width:100%;aspect-ratio:16/9;min-height:330px;overflow:hidden;border-radius:18px;background:#f4e9dc}
.lm-facade>svg{position:absolute;inset:0;width:100%;height:100%;filter:saturate(.7) blur(1.5px);transform:scale(1.04)}
.lm-facade iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.lm-consent{position:absolute;inset:0;display:grid;place-items:center;padding:18px;background:rgba(244,233,220,.55)}
.lm-consent[hidden]{display:none}
.lc{--lc-ink:#2a1d16;--lc-muted:#6b5446;--lc-line:#eadccc;--lc-accent:#c2410c;--lc-accent-dark:#9a3412;color:var(--lc-ink)}
.lc-card{display:grid;background:#fff;border:1px solid var(--lc-line);border-radius:22px;overflow:hidden;box-shadow:0 10px 30px -18px rgba(42,29,22,.35)}
@media (min-width:820px){.lc-card{grid-template-columns:1.1fr 1fr}.lc-card .lm-map{min-height:100%}}
.lc-card .lm-map{min-height:240px}
.lc-body{padding:28px}
.lc-kicker{font-size:.75rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--lc-accent-dark)}
.lc h2{margin-top:6px;font-size:1.5rem;letter-spacing:-.02em;line-height:1.2}
.lc address{margin-top:14px;font-style:normal;line-height:1.55}
.lc-hours{display:grid;grid-template-columns:auto 1fr;gap:6px 18px;margin-top:18px;padding:14px 16px;border-radius:14px;background:#fbf6f0;font-size:.92rem}
.lc-hours dt{color:var(--lc-muted)}
.lc-hours dd{font-weight:600;font-variant-numeric:tabular-nums}
.lc-contact{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:16px;font-size:.92rem}
.lc a{color:var(--lc-accent-dark);font-weight:700;text-underline-offset:3px}
.lc-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px}
.lc .lc-btn{display:inline-flex;align-items:center;gap:8px;padding:11px 18px;border-radius:999px;background:var(--lc-accent-dark);color:#fff;font-weight:700;font-size:.92rem;text-decoration:none;border:2px solid var(--lc-accent-dark);transition:background-color .15s;cursor:pointer;font-family:inherit}
.lc .lc-btn:hover{background:#7c2d12;border-color:#7c2d12}
.lc .lc-btn.is-ghost{background:#fff;color:var(--lc-accent-dark)}
.lc .lc-btn.is-ghost:hover{background:#fff4ec}
.lc :is(a,button):focus-visible{outline:3px solid var(--lc-ink);outline-offset:3px;border-radius:999px}
.lc-trio{display:grid;gap:18px}
@media (min-width:760px){.lc-trio{grid-template-columns:repeat(3,minmax(0,1fr))}}
.lc-office{background:#fff;border:1px solid var(--lc-line);border-radius:18px;overflow:hidden;display:flex;flex-direction:column}
.lc-office .lm-map{min-height:0;aspect-ratio:16/9}
.lc-office .lm-pin{width:28px;height:35px}
.lc-office div.lc-o{padding:18px 20px 20px;display:flex;flex-direction:column;flex:1}
.lc-office h3{font-size:1.1rem}
.lc-office address{margin-top:6px;font-size:.92rem;color:var(--lc-muted)}
.lc-office p{margin-top:10px;font-size:.85rem;color:var(--lc-muted)}
.lc-office a{margin-top:auto;padding-top:14px;font-size:.9rem;border-radius:6px}
.lc-office a:focus-visible{border-radius:6px}
.lc-panel{max-width:400px;padding:22px;border-radius:16px;background:#fff;text-align:center;box-shadow:0 18px 40px -20px rgba(42,29,22,.5)}
.lc-panel h3{font-size:1.1rem}
.lc-panel p{margin-top:6px;font-size:.88rem;color:var(--lc-muted)}
.lc-panel .lc-actions{justify-content:center;margin-top:16px}
.lc-panel small{display:block;margin-top:12px;font-size:.78rem;color:var(--lc-muted)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (max-width:640px){.lc-body{padding:20px}}
@media (prefers-reduced-motion:reduce){.lc .lc-btn{transition:none}}
.lm-preview,.lm-preview>svg{position:absolute;inset:0;width:100%;height:100%}
.lm-preview>svg{filter:saturate(.7) blur(1.5px);transform:scale(1.04)}
JavaScript
// Click-to-load map: nothing is requested from OpenStreetMap until the visitor asks for the map.
document.querySelectorAll('[data-map-facade]').forEach(function (box) {
  var btn = box.querySelector('[data-map-load]');
  if (!btn) return;
  btn.addEventListener('click', function () {
    var frame = document.createElement('iframe');
    frame.src = box.dataset.src;
    frame.title = box.dataset.title;
    frame.setAttribute('loading', 'lazy');
    box.querySelector('[data-map-preview]').remove();
    box.querySelector('.lm-consent').hidden = true;
    box.appendChild(frame);
    frame.focus();
  });
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Contact card with an illustrated map, address and hours</span>
<section class="lc card rounded-4 overflow-hidden shadow-sm" aria-labelledby="lc-rosa-title">
  <div class="row g-0">
    <div class="col-md-6 lm-map" style="min-height:240px">
    <svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b8d4e3"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b8d4e3" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b8d4e3" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b8d4e3"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg>
      <span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span><span class="lm-tag" aria-hidden="true">Atelier Rosa</span>
    </div>
    <div class="col-md-6 p-4">
      <p class="lc-kicker fw-bolder text-uppercase mb-0">Visit the studio</p>
      <h2 id="lc-rosa-title" class="h3 fw-bold mt-1 mb-0">Atelier Rosa, Bairro Alto</h2>
      <address class="mt-3 mb-0">Rua da Rosa 112, ground floor<br>1200-388 Lisboa, Portugal</address>
      <dl class="lc-hours row g-0 row-gap-1 rounded-3 px-3 py-2 mt-3 mb-0"><dt class="col-5">Tue–Fri</dt><dd class="col-7 fw-semibold mb-0">10:00–19:00</dd><dt class="col-5">Saturday</dt><dd class="col-7 fw-semibold mb-0">10:00–14:00</dd><dt class="col-5">Sun–Mon</dt><dd class="col-7 fw-semibold mb-0">Closed</dd></dl>
      <p class="d-flex flex-wrap gap-1 column-gap-3 mt-3 mb-0" style="font-size:.92rem"><a href="tel:+351213450112">+351 213 450 112</a><a href="mailto:[email protected]">[email protected]</a></p>
      <div class="d-flex flex-wrap gap-2 mt-4"><a class="btn btn-rosa d-inline-flex align-items-center gap-2" href="https://www.openstreetmap.org/directions?route=%3B38.7130%2C-9.1450" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M3 11l18-8-8 18-2-8z"/></svg>Get directions<span class="visually-hidden"> (opens in a new tab)</span></a><a class="btn btn-outline-rosa" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">Open in OpenStreetMap<span class="visually-hidden"> (opens in a new tab)</span></a></div>
    </div>
  </div>
</section></div>
<div><span class="lbl">Office cards with a mini map each</span>
<section class="lc" aria-label="Our offices">
  <ul class="row g-3 list-unstyled mb-0">
    <li class="col-md-4"><div class="lc-office card h-100 rounded-4 overflow-hidden"><div class="lm-map"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b9d3e8"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b9d3e8" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b9d3e8" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b9d3e8"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="card-body d-flex flex-column"><h3 class="h5 fw-bold mb-1">London</h3><address class="small text-body-secondary mb-2" style="color:#6b5446!important">Studio 4, 21 Hoxton Square<br>London N1 6NN, United Kingdom</address><p class="small mb-0" style="color:#6b5446">Mon–Fri 9:00–17:30</p><a class="mt-auto pt-3 small rounded-2" href="https://www.openstreetmap.org/?mlat=51.5280&mlon=-0.0820#map=17/51.5280/-0.0820" target="_blank" rel="noopener">View London on the map<span class="visually-hidden"> (opens in a new tab)</span></a></div></div></li>
    <li class="col-md-4"><div class="lc-office card h-100 rounded-4 overflow-hidden"><div class="lm-map"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#bcd8e6"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#bcd8e6" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#bcd8e6" stroke-width="9" stroke-linecap="round"/>
      <g fill="#bcd8e6"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="card-body d-flex flex-column"><h3 class="h5 fw-bold mb-1">Lisbon</h3><address class="small text-body-secondary mb-2" style="color:#6b5446!important">Rua da Rosa 112, 2.º andar<br>1200-388 Lisboa, Portugal</address><p class="small mb-0" style="color:#6b5446">Mon–Fri 9:30–18:00</p><a class="mt-auto pt-3 small rounded-2" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">View Lisbon on the map<span class="visually-hidden"> (opens in a new tab)</span></a></div></div></li>
    <li class="col-md-4"><div class="lc-office card h-100 rounded-4 overflow-hidden"><div class="lm-map"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b5cfe6"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b5cfe6" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b5cfe6" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b5cfe6"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="card-body d-flex flex-column"><h3 class="h5 fw-bold mb-1">Toronto</h3><address class="small text-body-secondary mb-2" style="color:#6b5446!important">401 Richmond Street West, Suite 210<br>Toronto ON M5V 3A8, Canada</address><p class="small mb-0" style="color:#6b5446">Mon–Fri 9:00–17:00</p><a class="mt-auto pt-3 small rounded-2" href="https://www.openstreetmap.org/?mlat=43.6480&mlon=-79.3950#map=17/43.6480/-79.3950" target="_blank" rel="noopener">View Toronto on the map<span class="visually-hidden"> (opens in a new tab)</span></a></div></div></li>
  </ul>
</section></div>
<div><span class="lbl">Privacy-friendly click-to-load OpenStreetMap embed</span>
<section class="lc" aria-labelledby="lc-embed-title">
  <div class="lm-facade" data-map-facade data-src="https://www.openstreetmap.org/export/embed.html?bbox=-9.1520%2C38.7095%2C-9.1380%2C38.7165&layer=mapnik&marker=38.7130%2C-9.1450" data-title="Map of Atelier Rosa, Rua da Rosa 112, Lisbon, on OpenStreetMap">
    <div data-map-preview class="lm-preview"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b8d4e3"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b8d4e3" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b8d4e3" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b8d4e3"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg></div>
    <div class="lm-consent">
      <div class="lc-panel card border-0 rounded-4 p-4 text-center">
        <h3 id="lc-embed-title" class="h5 fw-bold mb-1">Show the interactive map?</h3>
        <p class="small mb-0" style="color:#6b5446">The map is loaded from OpenStreetMap, which will receive your IP address. Nothing is loaded until you choose.</p>
        <div class="d-flex flex-wrap justify-content-center gap-2 mt-3"><button class="btn btn-rosa" type="button" data-map-load>Load map</button><a class="btn btn-outline-rosa" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">Open in a new tab<span class="visually-hidden"> (opens in a new tab)</span></a></div>
        <small class="d-block mt-3" style="font-size:.78rem;color:#6b5446">Map data © OpenStreetMap contributors</small>
      </div>
    </div>
  </div>
</section></div>
CSS
/* Location cards: illustrated map (inline SVG, not to scale) with a centred pin, and a click-to-load OpenStreetMap facade. */
.lm-map{position:relative;overflow:hidden;background:#f4e9dc;min-height:180px}
.lm-map>svg{position:absolute;inset:0;width:100%;height:100%}
.lm-pin{position:absolute;left:50%;top:50%;width:38px;height:47px;transform:translate(-50%,-100%);filter:drop-shadow(0 4px 5px rgba(42,29,22,.35))}
.lm-pin svg{display:block;width:100%;height:100%}
.lm-pin::before{content:"";position:absolute;left:50%;bottom:-6px;width:22px;height:8px;border-radius:50%;background:rgba(42,29,22,.25);transform:translateX(-50%);z-index:-1}
.lm-tag{position:absolute;left:50%;top:calc(50% + 10px);transform:translateX(-50%);padding:5px 10px;border-radius:9px;background:#2a1d16;color:#fff;font-size:.75rem;font-weight:700;white-space:nowrap}
.lm-facade{position:relative;width:100%;aspect-ratio:16/9;min-height:330px;overflow:hidden;border-radius:18px;background:#f4e9dc}
.lm-facade>svg{position:absolute;inset:0;width:100%;height:100%;filter:saturate(.7) blur(1.5px);transform:scale(1.04)}
.lm-facade iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.lm-consent{position:absolute;inset:0;display:grid;place-items:center;padding:18px;background:rgba(244,233,220,.55)}
.lm-consent[hidden]{display:none}
.lm-preview,.lm-preview>svg{position:absolute;inset:0;width:100%;height:100%}
.lm-preview>svg{filter:saturate(.7) blur(1.5px);transform:scale(1.04)}
.lc{color:#2a1d16}
.lc .card{--bs-card-border-color:#eadccc}
.lc-kicker{font-size:.75rem;letter-spacing:.12em;color:#9a3412}
.lc-hours{background:#fbf6f0;font-size:.92rem}
.lc-hours dt{color:#6b5446;font-weight:400}
.lc a:not(.btn){color:#9a3412;font-weight:700;text-underline-offset:3px}
.lc .btn{--bs-btn-padding-y:9px;--bs-btn-padding-x:16px;--bs-btn-font-size:.92rem;--bs-btn-font-weight:700;--bs-btn-border-radius:999px;--bs-btn-border-width:2px}
.lc .btn-rosa{--bs-btn-color:#fff;--bs-btn-bg:#9a3412;--bs-btn-border-color:#9a3412;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#7c2d12;--bs-btn-hover-border-color:#7c2d12;--bs-btn-active-bg:#7c2d12;--bs-btn-active-border-color:#7c2d12;--bs-btn-active-color:#fff}
.lc .btn-outline-rosa{--bs-btn-color:#9a3412;--bs-btn-bg:#fff;--bs-btn-border-color:#9a3412;--bs-btn-hover-color:#9a3412;--bs-btn-hover-bg:#fff4ec;--bs-btn-hover-border-color:#9a3412;--bs-btn-active-bg:#fff4ec;--bs-btn-active-color:#9a3412;--bs-btn-active-border-color:#9a3412}
.lc :is(a,button):focus-visible{outline:3px solid #2a1d16;outline-offset:3px;box-shadow:none}
.lc .btn:focus-visible{border-radius:999px}
.lc-office .lm-map{min-height:0;aspect-ratio:16/9}
.lc-office .lm-pin{width:28px;height:35px}
.lc-panel{max-width:400px;box-shadow:0 18px 40px -20px rgba(42,29,22,.5)}
JavaScript
// Click-to-load map: nothing is requested from OpenStreetMap until the visitor asks for the map.
document.querySelectorAll('[data-map-facade]').forEach(function (box) {
  var btn = box.querySelector('[data-map-load]');
  if (!btn) return;
  btn.addEventListener('click', function () {
    var frame = document.createElement('iframe');
    frame.src = box.dataset.src;
    frame.title = box.dataset.title;
    frame.setAttribute('loading', 'lazy');
    box.querySelector('[data-map-preview]').remove();
    box.querySelector('.lm-consent').hidden = true;
    box.appendChild(frame);
    frame.focus();
  });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#6b5446] uppercase">Contact card with an illustrated map, address and hours</span>
<section class="grid overflow-hidden rounded-[22px] border border-[#eadccc] bg-white text-[#2a1d16] shadow-[0_10px_30px_-18px_rgba(42,29,22,.35)] min-[820px]:grid-cols-[1.1fr_1fr]" aria-labelledby="lc-rosa-title">
  <div class="lm-map min-h-[240px]">
    <svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b8d4e3"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b8d4e3" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b8d4e3" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b8d4e3"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg>
    <span class="lm-pin"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span><span class="lm-tag" aria-hidden="true">Atelier Rosa</span>
  </div>
  <div class="p-5 sm:p-7">
    <p class="text-[.75rem] font-extrabold tracking-[.12em] text-[#9a3412] uppercase">Visit the studio</p>
    <h2 id="lc-rosa-title" class="mt-1.5 text-[1.5rem] leading-tight font-bold tracking-[-.02em]">Atelier Rosa, Bairro Alto</h2>
    <address class="mt-3.5 leading-[1.55] not-italic">Rua da Rosa 112, ground floor<br>1200-388 Lisboa, Portugal</address>
    <dl class="mt-[18px] grid grid-cols-[auto_1fr] gap-x-[18px] gap-y-1.5 rounded-[14px] bg-[#fbf6f0] px-4 py-3.5 text-[.92rem]"><dt class="text-[#6b5446]">Tue–Fri</dt><dd class="font-semibold tabular-nums">10:00–19:00</dd><dt class="text-[#6b5446]">Saturday</dt><dd class="font-semibold tabular-nums">10:00–14:00</dd><dt class="text-[#6b5446]">Sun–Mon</dt><dd class="font-semibold">Closed</dd></dl>
    <p class="mt-4 flex flex-wrap gap-x-[18px] gap-y-1.5 text-[.92rem]"><a class="font-bold text-[#9a3412] underline underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] rounded-full" href="tel:+351213450112">+351 213 450 112</a><a class="font-bold text-[#9a3412] underline underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] rounded-full" href="mailto:[email protected]">[email protected]</a></p>
    <div class="mt-[22px] flex flex-wrap gap-2.5"><a class="inline-flex cursor-pointer items-center gap-2 rounded-full border-2 border-[#9a3412] bg-[#9a3412] px-[18px] py-[11px] text-[.92rem] font-bold text-white transition-colors hover:border-[#7c2d12] hover:bg-[#7c2d12] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] motion-reduce:transition-none" href="https://www.openstreetmap.org/directions?route=%3B38.7130%2C-9.1450" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M3 11l18-8-8 18-2-8z"/></svg>Get directions<span class="sr-only"> (opens in a new tab)</span></a><a class="inline-flex cursor-pointer items-center gap-2 rounded-full border-2 border-[#9a3412] bg-white px-[18px] py-[11px] text-[.92rem] font-bold text-[#9a3412] transition-colors hover:bg-[#fff4ec] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] motion-reduce:transition-none" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">Open in OpenStreetMap<span class="sr-only"> (opens in a new tab)</span></a></div>
  </div>
</section></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#6b5446] uppercase">Office cards with a mini map each</span>
<section aria-label="Our offices">
  <ul class="grid gap-[18px] text-[#2a1d16] min-[760px]:grid-cols-3">
    <li class="flex flex-col overflow-hidden rounded-[18px] border border-[#eadccc] bg-white"><div class="lm-map aspect-video min-h-0"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b9d3e8"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b9d3e8" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b9d3e8" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b9d3e8"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin h-[35px] w-7"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="flex flex-1 flex-col px-5 pt-[18px] pb-5"><h3 class="text-[1.1rem] font-bold">London</h3><address class="mt-1.5 text-[.92rem] text-[#6b5446] not-italic">Studio 4, 21 Hoxton Square<br>London N1 6NN, United Kingdom</address><p class="mt-2.5 text-[.85rem] text-[#6b5446]">Mon–Fri 9:00–17:30</p><a class="font-bold text-[#9a3412] underline underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] mt-auto self-start rounded-md pt-3.5 text-[.9rem]" href="https://www.openstreetmap.org/?mlat=51.5280&mlon=-0.0820#map=17/51.5280/-0.0820" target="_blank" rel="noopener">View London on the map<span class="sr-only"> (opens in a new tab)</span></a></div></li>
    <li class="flex flex-col overflow-hidden rounded-[18px] border border-[#eadccc] bg-white"><div class="lm-map aspect-video min-h-0"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#bcd8e6"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#bcd8e6" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#bcd8e6" stroke-width="9" stroke-linecap="round"/>
      <g fill="#bcd8e6"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin h-[35px] w-7"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="flex flex-1 flex-col px-5 pt-[18px] pb-5"><h3 class="text-[1.1rem] font-bold">Lisbon</h3><address class="mt-1.5 text-[.92rem] text-[#6b5446] not-italic">Rua da Rosa 112, 2.º andar<br>1200-388 Lisboa, Portugal</address><p class="mt-2.5 text-[.85rem] text-[#6b5446]">Mon–Fri 9:30–18:00</p><a class="font-bold text-[#9a3412] underline underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] mt-auto self-start rounded-md pt-3.5 text-[.9rem]" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">View Lisbon on the map<span class="sr-only"> (opens in a new tab)</span></a></div></li>
    <li class="flex flex-col overflow-hidden rounded-[18px] border border-[#eadccc] bg-white"><div class="lm-map aspect-video min-h-0"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b5cfe6"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b5cfe6" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b5cfe6" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b5cfe6"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg><span class="lm-pin h-[35px] w-7"><svg viewBox="0 0 34 42" aria-hidden="true" focusable="false"><path d="M17 41C17 41 32 25.5 32 16A15 15 0 0 0 2 16C2 25.5 17 41 17 41Z" fill="#c2410c" stroke="#fff" stroke-width="2.5"/><circle cx="17" cy="16" r="5.5" fill="#fff"/></svg></span></div>
      <div class="flex flex-1 flex-col px-5 pt-[18px] pb-5"><h3 class="text-[1.1rem] font-bold">Toronto</h3><address class="mt-1.5 text-[.92rem] text-[#6b5446] not-italic">401 Richmond Street West, Suite 210<br>Toronto ON M5V 3A8, Canada</address><p class="mt-2.5 text-[.85rem] text-[#6b5446]">Mon–Fri 9:00–17:00</p><a class="font-bold text-[#9a3412] underline underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] mt-auto self-start rounded-md pt-3.5 text-[.9rem]" href="https://www.openstreetmap.org/?mlat=43.6480&mlon=-79.3950#map=17/43.6480/-79.3950" target="_blank" rel="noopener">View Toronto on the map<span class="sr-only"> (opens in a new tab)</span></a></div></li>
  </ul>
</section></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#6b5446] uppercase">Privacy-friendly click-to-load OpenStreetMap embed</span>
<section class="text-[#2a1d16]" aria-labelledby="lc-embed-title">
  <div class="lm-facade" data-map-facade data-src="https://www.openstreetmap.org/export/embed.html?bbox=-9.1520%2C38.7095%2C-9.1380%2C38.7165&layer=mapnik&marker=38.7130%2C-9.1450" data-title="Map of Atelier Rosa, Rua da Rosa 112, Lisbon, on OpenStreetMap">
    <div data-map-preview class="lm-preview"><svg class="" viewBox="0 0 600 450" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">
      <rect width="600" height="450" fill="#f4e9dc"/>
      <g stroke="#ecdfcf" stroke-width="2.5" fill="none">
        <path d="M0 60h600M0 160h600M0 360h600M0 410h600M60 0v450M180 0v450M290 0v450M520 0v450M0 210l600 40M120 0l90 450M380 0l-60 450"/>
      </g>
      <path d="M420 0H600V170C560 150 520 110 475 72C452 52 434 26 420 0Z" fill="#b8d4e3"/>
      <path d="M472 74C458 150 446 205 436 250C420 320 382 385 330 450" fill="none" stroke="#b8d4e3" stroke-width="28"/>
      <path d="M528 340C505 306 474 294 440 288" fill="none" stroke="#b8d4e3" stroke-width="9" stroke-linecap="round"/>
      <g fill="#b8d4e3"><rect x="238" y="70" width="26" height="70" rx="13" transform="rotate(28 251 105)"/><rect x="214" y="138" width="26" height="70" rx="13" transform="rotate(28 227 173)"/><rect x="190" y="206" width="26" height="62" rx="13" transform="rotate(28 203 237)"/></g>
      <g fill="#d6e3bf"><rect x="24" y="290" width="86" height="62" rx="14"/><rect x="346" y="168" width="58" height="46" rx="10"/><rect x="292" y="14" width="96" height="44" rx="14"/><circle cx="560" cy="420" r="46"/></g>
      <g fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="#e2d2bd" stroke-width="11" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
        <path stroke="#fffaf3" stroke-width="7" d="M0 302C150 292 250 270 334 204M118 0C150 100 205 190 334 204M0 128L334 204M334 204C346 262 300 380 262 450M94 0C74 150 58 300 92 450M334 204L600 236M436 0C430 120 410 300 600 330"/>
      </g>
    </svg></div>
    <div class="lm-consent">
      <div class="max-w-[400px] rounded-2xl bg-white p-[22px] text-center shadow-[0_18px_40px_-20px_rgba(42,29,22,.5)]">
        <h3 id="lc-embed-title" class="text-[1.1rem] font-bold">Show the interactive map?</h3>
        <p class="mt-1.5 text-[.88rem] text-[#6b5446]">The map is loaded from OpenStreetMap, which will receive your IP address. Nothing is loaded until you choose.</p>
        <div class="mt-4 flex flex-wrap justify-center gap-2.5"><button class="inline-flex cursor-pointer items-center gap-2 rounded-full border-2 border-[#9a3412] bg-[#9a3412] px-[18px] py-[11px] text-[.92rem] font-bold text-white transition-colors hover:border-[#7c2d12] hover:bg-[#7c2d12] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] motion-reduce:transition-none" type="button" data-map-load>Load map</button><a class="inline-flex cursor-pointer items-center gap-2 rounded-full border-2 border-[#9a3412] bg-white px-[18px] py-[11px] text-[.92rem] font-bold text-[#9a3412] transition-colors hover:bg-[#fff4ec] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#2a1d16] motion-reduce:transition-none" href="https://www.openstreetmap.org/?mlat=38.7130&mlon=-9.1450#map=17/38.7130/-9.1450" target="_blank" rel="noopener">Open in a new tab<span class="sr-only"> (opens in a new tab)</span></a></div>
        <small class="mt-3 block text-[.78rem] text-[#6b5446]">Map data © OpenStreetMap contributors</small>
      </div>
    </div>
  </div>
</section></div>
CSS
@layer components {
/* Location cards: illustrated map (inline SVG, not to scale) with a centred pin, and a click-to-load OpenStreetMap facade. */
.lm-map{position:relative;overflow:hidden;background:#f4e9dc;min-height:180px}
.lm-map>svg{position:absolute;inset:0;width:100%;height:100%}
.lm-pin{position:absolute;left:50%;top:50%;width:38px;height:47px;transform:translate(-50%,-100%);filter:drop-shadow(0 4px 5px rgba(42,29,22,.35))}
.lm-pin svg{display:block;width:100%;height:100%}
.lm-pin::before{content:"";position:absolute;left:50%;bottom:-6px;width:22px;height:8px;border-radius:50%;background:rgba(42,29,22,.25);transform:translateX(-50%);z-index:-1}
.lm-tag{position:absolute;left:50%;top:calc(50% + 10px);transform:translateX(-50%);padding:5px 10px;border-radius:9px;background:#2a1d16;color:#fff;font-size:.75rem;font-weight:700;white-space:nowrap}
.lm-facade{position:relative;width:100%;aspect-ratio:16/9;min-height:330px;overflow:hidden;border-radius:18px;background:#f4e9dc}
.lm-facade>svg{position:absolute;inset:0;width:100%;height:100%;filter:saturate(.7) blur(1.5px);transform:scale(1.04)}
.lm-facade iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.lm-consent{position:absolute;inset:0;display:grid;place-items:center;padding:18px;background:rgba(244,233,220,.55)}
.lm-consent[hidden]{display:none}
.lm-preview,.lm-preview>svg{position:absolute;inset:0;width:100%;height:100%}
.lm-preview>svg{filter:saturate(.7) blur(1.5px);transform:scale(1.04)}
}
JavaScript
// Click-to-load map: nothing is requested from OpenStreetMap until the visitor asks for the map.
document.querySelectorAll('[data-map-facade]').forEach(function (box) {
  var btn = box.querySelector('[data-map-load]');
  if (!btn) return;
  btn.addEventListener('click', function () {
    var frame = document.createElement('iframe');
    frame.src = box.dataset.src;
    frame.title = box.dataset.title;
    frame.setAttribute('loading', 'lazy');
    box.querySelector('[data-map-preview]').remove();
    box.querySelector('.lm-consent').hidden = true;
    box.appendChild(frame);
    frame.focus();
  });
});

About this set

Three ways to show where a place is on a contact or about page without loading a third-party map up front. The contact card pairs an illustrated map, drawn in inline SVG with a centred pin and a name tag, with the studio address in an address element, opening hours in a definition list, phone and email links and two actions: Get directions and Open in OpenStreetMap. The office cards repeat the idea at a smaller size for three offices, each with a mini map, address, hours and a link to the exact spot on OpenStreetMap. The third variant is a privacy-friendly embed facade: a blurred preview with a short notice that the map comes from OpenStreetMap and will receive the visitor’s IP address, a Load map button and a link to open the map in a new tab. Nothing is requested from OpenStreetMap until the button is pressed; a few lines of JavaScript then swap the preview for the OpenStreetMap embed iframe with a descriptive title and move focus to it. Use the static cards when the address is enough and the facade when visitors need to pan and zoom.

What’s included

  • Illustrated SVG map with a centred pin, no tiles or API key
  • Address, opening hours and contact links in semantic markup
  • Directions and OpenStreetMap links with exact coordinates
  • Click-to-load OpenStreetMap iframe that loads nothing until asked
  • Same drawing reused for three office cards

Accessibility

Decorative maps are hidden from assistive technology, so the address text carries the meaning. Links that open a new tab say so in visually hidden text, the Load map control is a real button, and the embedded iframe gets a descriptive title and receives focus once loaded. Every link and button has a visible focus outline.

Customise it

Pass your own colours to the map drawing or change the fills in the SVG, and update the coordinates in the OpenStreetMap links and the data-src embed URL (bbox and marker). Button colours are set in the .lc-btn rules, the Bootstrap .btn variables or the Tailwind classes.