Open demo

CSS code

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="nb-i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v6M12 7.5h.01"/></symbol>
  <symbol id="nb-i-success" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m7.5 12.5 3 3 6-6.5"/></symbol>
  <symbol id="nb-i-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5 2.5 20h19z"/><path d="M12 10v4.5M12 17.5h.01"/></symbol>
  <symbol id="nb-i-error" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m8.5 8.5 7 7M15.5 8.5l-7 7"/></symbol>
  <symbol id="nb-i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m4.5 12.5 5 5L19.5 7"/></symbol>
  <symbol id="nb-i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6l12 12M18 6 6 18"/></symbol>
  <symbol id="nb-i-clock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/></symbol>
  <symbol id="nb-i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15V4M7.5 8.5 12 4l4.5 4.5M5 13v6.5h14V13"/></symbol>
  <symbol id="nb-i-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M4.5 19.5h15"/></symbol>
  <symbol id="nb-i-chev-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="nb-i-edit" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h4.5L19.5 9 15 4.5 4 15.5z"/><path d="m12.5 7 4.5 4.5"/></symbol>
  <symbol id="nb-i-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><rect x="8.5" y="8.5" width="12" height="12" rx="1.5"/><path d="M15.5 8.5V4.5a1 1 0 0 0-1-1h-10a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h4"/></symbol>
  <symbol id="nb-i-trash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6.5h16M9 6.5V4h6v2.5M6 6.5l1 14h10l1-14M10 10.5v6M14 10.5v6"/></symbol>
</svg>
<section><span class="lbl">Alerts · the type is in the icon, the title and hidden text</span><div class="nb-stack">
<div class="nb-alert" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-info"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="nb-sr">Information: </span>Payouts move to Fridays</p><p>From 1 November, earnings are paid every Friday instead of on the first of the month.</p></div></div>
<div class="nb-alert nb-alert--success" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-success"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="nb-sr">Success: </span>Post published</p><p>It is live, and 12,480 subscribers were emailed. <a href="#">View post</a></p></div></div>
<div class="nb-alert nb-alert--warning" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-alert"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="nb-sr">Warning: </span>Storage almost full</p><p>You have used 9.2 GB of 10 GB. New episodes may fail to upload.</p></div></div>
<div class="nb-alert nb-alert--error" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-error"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="nb-sr">Error: </span>Payment failed</p><p>We could not charge the card ending 4242. <a href="#">Update your card</a> by 20 October.</p></div></div>
</div></section>
<div class="cols">
<section><span class="lbl">Toasts · in a polite live region</span><div class="nb-toasts" role="status" aria-live="polite">
<div class="nb-toast" data-nb-toast><span class="nb-toast__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-check"/></svg></span><div class="nb-toast__body"><strong class="nb-toast__title">Link copied</strong><span class="nb-toast__text">loudhaus.com/mira/ep-42</span></div><button class="nb-btn nb-btn--icon nb-btn--icon-sm" type="button" aria-label="Dismiss" data-nb-dismiss><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
<div class="nb-toast" data-nb-toast><span class="nb-toast__icon nb-toast__icon--cyan"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-clock"/></svg></span><div class="nb-toast__body"><strong class="nb-toast__title">Post scheduled</strong><span class="nb-toast__text">Goes live Fri 23 Oct, 9:00</span></div><button class="nb-toast__action" type="button">Undo</button><button class="nb-btn nb-btn--icon nb-btn--icon-sm" type="button" aria-label="Dismiss" data-nb-dismiss><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
</div></section>
<section><span class="lbl">Tooltips · hover or focus, Escape hides</span><div class="nb-cluster tip-stage">
<span class="nb-tip nb-tip--open nb-tip--start" data-nb-tip><button class="nb-btn nb-btn--icon nb-btn--round" type="button" aria-label="Share" aria-describedby="tip-share"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-share"/></svg></button><span class="nb-tip__bubble" role="tooltip" id="tip-share">Copy a share link</span></span>
<span class="nb-tip" data-nb-tip><button class="nb-btn nb-btn--icon" type="button" aria-label="Download" aria-describedby="tip-dl"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-download"/></svg></button><span class="nb-tip__bubble" role="tooltip" id="tip-dl">MP3, 42 MB</span></span>
<span class="nb-tip nb-tip--right" data-nb-tip><button class="nb-btn nb-btn--sm" type="button" aria-describedby="tip-fee"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-info"/></svg>Fees</button><span class="nb-tip__bubble" role="tooltip" id="tip-fee">5% per sale, card costs included</span></span>
</div></section>
</div>
<div class="cols">
<section><span class="lbl">Dropdown · Escape or a click outside closes it</span><div class="menu-stage">
<div class="nb-dd"><button class="nb-btn nb-dd__btn" type="button" aria-expanded="true" aria-controls="dd-episode" data-nb-dropdown>Episode actions<svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-chev-down"/></svg></button>
<ul class="nb-dd__menu" id="dd-episode">
<li><button class="nb-dd__item" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-edit"/></svg>Edit details<kbd>E</kbd></button></li>
<li><button class="nb-dd__item" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-copy"/></svg>Duplicate<kbd>D</kbd></button></li>
<li><button class="nb-dd__item" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-download"/></svg>Download audio</button></li>
<li class="nb-dd__sep" aria-hidden="true"></li>
<li><button class="nb-dd__item nb-dd__item--danger" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode</button></li>
</ul></div></div></section>
<section><span class="lbl">Modal · the native dialog</span>
<button class="nb-btn nb-btn--red" type="button" aria-haspopup="dialog" data-nb-open="dlg-delete"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode…</button>
<dialog class="nb-dialog" id="dlg-delete" aria-labelledby="dlg-delete-title" aria-describedby="dlg-delete-desc"><form method="dialog">
<div class="nb-dialog__head"><h2 class="nb-dialog__title nb-display" id="dlg-delete-title">Delete episode 42?</h2><button class="nb-btn nb-btn--icon nb-btn--icon-sm" type="submit" value="close" aria-label="Close"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
<div class="nb-dialog__body"><p id="dlg-delete-desc">“How we print 500 zines in a weekend” and its 38 comments are removed for good. Members who downloaded it keep their copy.</p></div>
<div class="nb-dialog__foot"><button class="nb-btn" type="submit" value="cancel">Keep it</button><button class="nb-btn nb-btn--red" type="submit" value="delete"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode</button></div>
</form></dialog></section>
</div>
CSS
/* ── Neobrutalism UI kit tokens (uiCookies) — identical in every set ─────────────
   Thick ink borders, hard offset shadows and flat saturated fills on cream paper.
   Change a token and the whole kit follows; the border and shadow recipes below are built from them. */
:root{
  --nb-paper:#fff6e0;        /* page background, cream */
  --nb-surface:#ffffff;      /* card, field and button faces */
  --nb-ink:#111111;          /* text, 17.5:1 on paper */
  --nb-muted:#454036;        /* secondary text, 9.6:1 on paper */
  --nb-line:#111111;         /* border colour */
  --nb-bw:3px;               /* border width */
  --nb-shadow-x:4px;         /* hard shadow offset; pressed controls move this far into it */
  --nb-shadow-y:4px;
  --nb-shadow-color:#111111;
  --nb-radius:12px;          /* cards and panels */
  --nb-radius-sm:8px;        /* buttons and fields */
  --nb-focus:#1d4ed8;        /* dashed focus outline, 6.2:1 on paper, never the shadow */
  --nb-on-fill:#111111;      /* text on every palette fill below, 6.8:1 or more */
  --nb-on-fill-muted:#2b2822;/* secondary text on fills, 5.2:1 or more */
  --nb-lemon:#ffe14d;--nb-pink:#ff90d0;--nb-cyan:#62e2e8;--nb-lime:#b6f36a;
  --nb-orange:#ffa94d;--nb-violet:#b9a3ff;--nb-red:#ff6b6b;
  --nb-blue:#2448e0;--nb-on-blue:#ffffff; /* the only fill that takes white text, 6.8:1 */
  --nb-danger:#b42318;       /* destructive text, 6.1:1 on paper */
  --nb-font:"Space Grotesk","Archivo","Helvetica Neue",Arial,system-ui,sans-serif;
  --nb-font-display:"Archivo Black","Arial Black","Helvetica Neue",Arial,sans-serif;
}
/* Dark brutalism: data-nb="dark" on any wrapper, or a checked .nb-theme-input inside a [data-nb] element.
   :is() is a forgiving list, so browsers without :has() still apply data-nb="dark". Fills keep dark text. */
[data-nb]:is([data-nb="dark"],:has(.nb-theme-input:checked)){
  --nb-paper:#17150f;--nb-surface:#25221b;--nb-ink:#fbf3dc;--nb-muted:#d6ccb2;--nb-line:#fbf3dc;
  --nb-shadow-color:#fbf3dc;--nb-focus:#8db4ff;--nb-danger:#ff9b8f;color-scheme:dark}
/* More contrast requested: secondary text turns full ink */
@media (prefers-contrast:more){:root,[data-nb]:is([data-nb],:has(.nb-theme-input:checked)){--nb-muted:var(--nb-ink);--nb-on-fill-muted:var(--nb-on-fill)}}
:root,[data-nb]{
  --nb-border:var(--nb-bw) solid var(--nb-line);
  --nb-shadow:var(--nb-shadow-x) var(--nb-shadow-y) 0 0 var(--nb-shadow-color);
  --nb-shadow-sm:calc(var(--nb-shadow-x)*.5) calc(var(--nb-shadow-y)*.5) 0 0 var(--nb-shadow-color);
  --nb-shadow-lg:calc(var(--nb-shadow-x)*1.75) calc(var(--nb-shadow-y)*1.75) 0 0 var(--nb-shadow-color);
  --nb-shadow-hover:calc(var(--nb-shadow-x) + 2px) calc(var(--nb-shadow-y) + 2px) 0 0 var(--nb-shadow-color);
  --nb-press:var(--nb-shadow-x) var(--nb-shadow-y);                       /* translate for a pressed control */
  --nb-press-sm:calc(var(--nb-shadow-x)*.5) calc(var(--nb-shadow-y)*.5);  /* …for one with the small shadow */
}
[data-nb]{background:var(--nb-paper);color:var(--nb-ink);font-family:var(--nb-font)}
/* Components */
:where([class*="nb-"]),:where([class*="nb-"])::before,:where([class*="nb-"])::after{box-sizing:border-box}
.nb-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.nb-ico{width:20px;height:20px;flex:none}
.nb-display{font-family:var(--nb-font-display);font-weight:900;letter-spacing:-.01em;line-height:1.05}
.nb-link{color:inherit;font-weight:700;text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}
.nb-link:hover{text-decoration-thickness:4px}
.nb-link:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:3px;border-radius:2px}
/* Buttons: a face, a thick border and a hard shadow. Hover lifts it, pressing moves it into its shadow */
.nb-btn{--nb-fill:var(--nb-surface);--nb-text:var(--nb-ink);
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:46px;padding:.6rem 1.2rem;
  border:var(--nb-border);border-radius:var(--nb-radius-sm);background:var(--nb-fill);color:var(--nb-text);
  font:700 1rem/1.2 var(--nb-font);text-decoration:none;cursor:pointer;box-shadow:var(--nb-shadow);
  transition:translate .12s,box-shadow .12s}
.nb-btn:hover{translate:-2px -2px;box-shadow:var(--nb-shadow-hover)}
.nb-btn:active{translate:var(--nb-press);box-shadow:none}
.nb-btn:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:5px}
.nb-btn--lemon{--nb-fill:var(--nb-lemon);--nb-text:var(--nb-on-fill)}
.nb-btn--pink{--nb-fill:var(--nb-pink);--nb-text:var(--nb-on-fill)}
.nb-btn--cyan{--nb-fill:var(--nb-cyan);--nb-text:var(--nb-on-fill)}
.nb-btn--lime{--nb-fill:var(--nb-lime);--nb-text:var(--nb-on-fill)}
.nb-btn--red{--nb-fill:var(--nb-red);--nb-text:var(--nb-on-fill)}
.nb-btn--blue{--nb-fill:var(--nb-blue);--nb-text:var(--nb-on-blue)}
.nb-btn--ink{--nb-fill:var(--nb-ink);--nb-text:var(--nb-paper)}
.nb-btn--sm{min-height:38px;padding:.4rem .85rem;font-size:.875rem}
.nb-btn--lg{min-height:56px;padding:.8rem 1.6rem;font-size:1.15rem}
.nb-btn--block{width:100%}
.nb-btn--icon{width:48px;height:48px;min-height:0;padding:0}
.nb-btn--icon-sm{width:38px;height:38px;box-shadow:var(--nb-shadow-sm)}
.nb-btn--icon-sm:hover{box-shadow:var(--nb-shadow)}
.nb-btn--icon-sm:active{translate:var(--nb-press-sm)}
.nb-btn--round{border-radius:50%}
.nb-btn:disabled{--nb-fill:var(--nb-paper);--nb-text:var(--nb-muted);border-style:dashed;box-shadow:none;translate:none;cursor:not-allowed}
/* Layout helpers */
.nb-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:18px}
.nb-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:20px}
.nb-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));gap:28px;align-items:start}
.nb-stack{display:grid;gap:1.25rem}
/* Fields: a white well with the thick border and a small shadow; focus adds a dashed outline */
.nb-field{display:grid;gap:.4rem;min-width:0}
.nb-label{font-weight:800;font-size:.95rem}
.nb-input,.nb-select,.nb-textarea{width:100%;min-height:48px;padding:.65rem .9rem;border:var(--nb-border);border-radius:var(--nb-radius-sm);background:var(--nb-surface);color:var(--nb-ink);
  font:500 1rem/1.4 var(--nb-font);box-shadow:var(--nb-shadow-sm);transition:box-shadow .12s}
.nb-textarea{min-height:110px;resize:vertical}
.nb-input::placeholder,.nb-textarea::placeholder{color:var(--nb-muted);opacity:1}
.nb-input:focus,.nb-select:focus,.nb-textarea:focus{outline:3px dashed var(--nb-focus);outline-offset:4px;box-shadow:var(--nb-shadow)}
.nb-hint{font-size:.85rem;color:var(--nb-muted)}
.nb-row{display:flex;justify-content:space-between;align-items:baseline;gap:1rem}
.nb-control{position:relative}
.nb-control>.nb-ico{position:absolute;top:50%;left:14px;translate:0 -50%;pointer-events:none}
.nb-control>.nb-ico~.nb-input{padding-left:2.75rem}
.nb-select{appearance:none;padding-right:2.75rem;cursor:pointer}
.nb-control--select::after{content:"";position:absolute;top:50%;right:18px;width:10px;height:10px;border:solid var(--nb-ink);border-width:0 3px 3px 0;translate:0 -70%;rotate:45deg;pointer-events:none}
.nb-input[aria-invalid="true"]{box-shadow:var(--nb-shadow-x) var(--nb-shadow-y) 0 0 var(--nb-red)}
.nb-error{display:flex;align-items:center;gap:.45rem;width:fit-content;max-width:100%;padding:.3rem .65rem;border:2px solid var(--nb-line);border-radius:6px;background:var(--nb-red);color:var(--nb-on-fill);font-size:.85rem;font-weight:700}
.nb-error .nb-ico{width:16px;height:16px}
/* Alerts: the type is named by an icon, a bold title and hidden text, never by colour alone */
.nb-alert{display:flex;align-items:flex-start;gap:.85rem;padding:1rem 1.1rem;border:var(--nb-border);border-radius:var(--nb-radius);background:var(--nb-tone,var(--nb-cyan));color:var(--nb-on-fill);box-shadow:var(--nb-shadow);font-family:var(--nb-font)}
.nb-alert--success{--nb-tone:var(--nb-lime)}.nb-alert--warning{--nb-tone:var(--nb-lemon)}.nb-alert--error{--nb-tone:var(--nb-red)}
.nb-alert__icon{display:grid;place-items:center;flex:none;width:38px;height:38px;border-radius:50%;background:var(--nb-on-fill);color:var(--nb-tone,var(--nb-cyan))}
.nb-alert__body{flex:1;min-width:0}
.nb-alert__title{margin:0;font-weight:800}
.nb-alert__body p+p{margin:.15rem 0 0}
.nb-alert a{color:inherit;font-weight:800;text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}
.nb-alert a:focus-visible{outline:3px dashed var(--nb-on-fill);outline-offset:3px}
/* Toasts: in a polite live region, each with its own close button */
.nb-toasts{display:grid;gap:1rem;max-width:400px}
.nb-toast{display:flex;align-items:center;gap:.8rem;padding:.8rem .9rem;border:var(--nb-border);border-radius:var(--nb-radius);background:var(--nb-surface);color:var(--nb-ink);box-shadow:var(--nb-shadow-lg);font-family:var(--nb-font)}
.nb-toast[hidden]{display:none}
.nb-toast__icon{display:grid;place-items:center;flex:none;width:38px;height:38px;border:var(--nb-border);border-radius:8px;background:var(--nb-lime);color:var(--nb-on-fill);rotate:-5deg}
.nb-toast__icon--cyan{background:var(--nb-cyan)}
.nb-toast__body{flex:1;min-width:0;line-height:1.35}
.nb-toast__title{display:block;font-weight:800}
.nb-toast__text{font-size:.9rem;color:var(--nb-muted)}
.nb-toast__action{padding:.2rem .1rem;border:0;background:none;color:var(--nb-ink);font:800 .9rem/1.2 var(--nb-font);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px;cursor:pointer}
.nb-toast__action:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:3px}
/* Tooltips: shown on hover and keyboard focus, tied to the trigger with aria-describedby, hidden again with Escape */
.nb-tip{position:relative;display:inline-flex}
.nb-tip__bubble{position:absolute;bottom:calc(100% + 14px);left:50%;z-index:5;width:max-content;max-width:220px;padding:.45rem .7rem;border:var(--nb-border);border-radius:var(--nb-radius-sm);
  background:var(--nb-lemon);color:var(--nb-on-fill);font:700 .85rem/1.3 var(--nb-font);box-shadow:var(--nb-shadow-sm);translate:-50% 0;visibility:hidden;opacity:0;transition:opacity .12s,visibility .12s}
.nb-tip__bubble::after{content:"";position:absolute;top:100%;left:50%;width:12px;height:12px;margin:-5px 0 0 -6px;border:solid var(--nb-line);border-width:0 var(--nb-bw) var(--nb-bw) 0;background:var(--nb-lemon);rotate:45deg}
.nb-tip:hover .nb-tip__bubble,.nb-tip:focus-within .nb-tip__bubble,.nb-tip--open .nb-tip__bubble{visibility:visible;opacity:1}
.nb-tip.is-dismissed .nb-tip__bubble{visibility:hidden;opacity:0}
.nb-tip--start .nb-tip__bubble{left:0;translate:none}
.nb-tip--start .nb-tip__bubble::after{left:24px}
.nb-tip--right .nb-tip__bubble{bottom:auto;top:50%;left:calc(100% + 14px);translate:0 -50%}
.nb-tip--right .nb-tip__bubble::after{top:50%;left:0;margin:-6px 0 0 -5px;border-width:0 0 var(--nb-bw) var(--nb-bw)}
@media (max-width:600px){.nb-tip--right .nb-tip__bubble{top:auto;bottom:calc(100% + 14px);left:50%;translate:-50% 0}.nb-tip--right .nb-tip__bubble::after{top:100%;left:50%;margin:-5px 0 0 -6px;border-width:0 var(--nb-bw) var(--nb-bw) 0}}
/* Dropdown: a disclosure button and a list of actions; Escape or a click outside closes it */
.nb-dd{position:relative;display:inline-block}
.nb-dd__btn[aria-expanded="true"]{translate:var(--nb-press);box-shadow:none}
.nb-dd__btn .nb-ico:last-child{transition:rotate .12s}
.nb-dd__btn[aria-expanded="true"] .nb-ico:last-child{rotate:180deg}
.nb-dd__menu{position:absolute;top:calc(100% + 12px);left:0;z-index:10;display:grid;gap:2px;min-width:230px;margin:0;padding:.4rem;border:var(--nb-border);border-radius:var(--nb-radius);
  background:var(--nb-surface);box-shadow:var(--nb-shadow-lg);list-style:none}
.nb-dd__menu[hidden]{display:none}
.nb-dd__item{display:flex;align-items:center;gap:.65rem;width:100%;padding:.5rem .65rem;border:2px solid transparent;border-radius:6px;background:none;color:var(--nb-ink);
  font:700 .95rem/1.2 var(--nb-font);text-align:left;cursor:pointer}
.nb-dd__item kbd{margin-left:auto;padding:0 .35rem;border:2px solid currentColor;border-radius:4px;font:700 .72rem/1.4 var(--nb-font)}
.nb-dd__item:hover{border-color:var(--nb-line);background:var(--nb-lemon);color:var(--nb-on-fill)}
.nb-dd__item:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:1px}
.nb-dd__item--danger{color:var(--nb-danger)}
.nb-dd__item--danger:hover{background:var(--nb-red);color:var(--nb-on-fill)}
.nb-dd__sep{height:0;margin:.3rem 0;border-top:var(--nb-border)}
/* Modal: the native <dialog>. showModal() traps focus, makes the page inert and closes on Escape;
   buttons inside <form method="dialog"> close it without script */
.nb-dialog{width:min(100% - 32px,460px);padding:0;border:var(--nb-border);border-radius:var(--nb-radius);background:var(--nb-surface);color:var(--nb-ink);
  box-shadow:calc(var(--nb-shadow-x)*2.5) calc(var(--nb-shadow-y)*2.5) 0 0 var(--nb-shadow-color);font-family:var(--nb-font);overflow:visible}
.nb-dialog::backdrop{background:rgba(17,17,17,.6)}
.nb-dialog[open]{animation:nb-drop .18s ease-out}
@keyframes nb-drop{from{translate:0 -14px;opacity:0}}
.nb-dialog form{margin:0}
.nb-dialog__head{display:flex;align-items:center;gap:.8rem;padding:1rem 1.2rem;border-bottom:var(--nb-border);border-radius:calc(var(--nb-radius) - var(--nb-bw)) calc(var(--nb-radius) - var(--nb-bw)) 0 0;background:var(--nb-pink);color:var(--nb-on-fill)}
.nb-dialog__title{flex:1;margin:0;font-size:1.3rem}
.nb-dialog__head .nb-btn{--nb-fill:var(--nb-surface);--nb-text:var(--nb-ink)}
.nb-dialog__body{padding:1.2rem 1.2rem .4rem}
.nb-dialog__body p{margin:0 0 .8rem}
.nb-dialog__foot{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:14px;padding:.8rem 1.2rem 1.3rem}
@media (prefers-reduced-motion:reduce){[class*="nb-"],[class*="nb-"]::before,[class*="nb-"]::after{transition:none!important;animation:none!important}}
JavaScript
// Modal: any button with data-nb-open="dialog-id" opens that <dialog>; focus returns to the button on close
document.querySelectorAll('[data-nb-open]').forEach(function (btn) {
  var dialog = document.getElementById(btn.getAttribute('data-nb-open'));
  if (!dialog) return;
  btn.addEventListener('click', function () {
    dialog.showModal();
    dialog.addEventListener('close', function () { btn.focus(); }, { once: true });
  });
  dialog.addEventListener('click', function (e) { if (e.target === dialog) dialog.close(); }); // backdrop click
});
// Tooltips: Escape hides the visible tooltip until the pointer or focus leaves it
document.addEventListener('keydown', function (e) {
  if (e.key !== 'Escape') return;
  document.querySelectorAll('[data-nb-tip]').forEach(function (t) { if (t.matches(':hover, :focus-within')) t.classList.add('is-dismissed'); });
});
document.querySelectorAll('[data-nb-tip]').forEach(function (t) {
  ['mouseleave', 'focusout'].forEach(function (ev) { t.addEventListener(ev, function () { t.classList.remove('is-dismissed'); }); });
});
// Toasts: a close button removes its toast
document.querySelectorAll('[data-nb-dismiss]').forEach(function (b) {
  b.addEventListener('click', function () { b.closest('[data-nb-toast]').hidden = true; });
});
// Dropdown: toggle on click; Escape (focus back to the button) or a click outside closes it
document.querySelectorAll('[data-nb-dropdown]').forEach(function (btn) {
  var menu = document.getElementById(btn.getAttribute('aria-controls'));
  function set(open) { btn.setAttribute('aria-expanded', open); menu.hidden = !open; }
  btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
  document.addEventListener('click', function (e) { if (!btn.parentNode.contains(e.target)) set(false); });
  btn.parentNode.addEventListener('keydown', function (e) { if (e.key === 'Escape' && btn.getAttribute('aria-expanded') === 'true') { set(false); btn.focus(); } });
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS, Bootstrap 5.3.8 JS bundle

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="nb-i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v6M12 7.5h.01"/></symbol>
  <symbol id="nb-i-success" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m7.5 12.5 3 3 6-6.5"/></symbol>
  <symbol id="nb-i-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5 2.5 20h19z"/><path d="M12 10v4.5M12 17.5h.01"/></symbol>
  <symbol id="nb-i-error" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m8.5 8.5 7 7M15.5 8.5l-7 7"/></symbol>
  <symbol id="nb-i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m4.5 12.5 5 5L19.5 7"/></symbol>
  <symbol id="nb-i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6l12 12M18 6 6 18"/></symbol>
  <symbol id="nb-i-clock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/></symbol>
  <symbol id="nb-i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15V4M7.5 8.5 12 4l4.5 4.5M5 13v6.5h14V13"/></symbol>
  <symbol id="nb-i-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M4.5 19.5h15"/></symbol>
  <symbol id="nb-i-chev-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="nb-i-edit" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h4.5L19.5 9 15 4.5 4 15.5z"/><path d="m12.5 7 4.5 4.5"/></symbol>
  <symbol id="nb-i-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><rect x="8.5" y="8.5" width="12" height="12" rx="1.5"/><path d="M15.5 8.5V4.5a1 1 0 0 0-1-1h-10a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h4"/></symbol>
  <symbol id="nb-i-trash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6.5h16M9 6.5V4h6v2.5M6 6.5l1 14h10l1-14M10 10.5v6M14 10.5v6"/></symbol>
</svg>
<section><span class="lbl">Alerts · the type is in the icon, the title and hidden text</span><div class="nb-stack">
<div class="alert nb-alert" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-info"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="visually-hidden">Information: </span>Payouts move to Fridays</p><p>From 1 November, earnings are paid every Friday instead of on the first of the month.</p></div></div>
<div class="alert nb-alert nb-alert-success" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-success"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="visually-hidden">Success: </span>Post published</p><p>It is live, and 12,480 subscribers were emailed. <a class="alert-link" href="#">View post</a></p></div></div>
<div class="alert nb-alert nb-alert-warning" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-alert"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="visually-hidden">Warning: </span>Storage almost full</p><p>You have used 9.2 GB of 10 GB. New episodes may fail to upload.</p></div></div>
<div class="alert nb-alert nb-alert-error" role="note"><span class="nb-alert__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-error"/></svg></span><div class="nb-alert__body"><p class="nb-alert__title"><span class="visually-hidden">Error: </span>Payment failed</p><p>We could not charge the card ending 4242. <a class="alert-link" href="#">Update your card</a> by 20 October.</p></div></div>
</div></section>
<div class="cols">
<section><span class="lbl">Toasts · in a polite live region</span><div class="nb-toasts" role="status" aria-live="polite">
<div class="toast show nb-toast"><div class="toast-body"><span class="nb-toast__icon"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-check"/></svg></span><div class="nb-toast__body"><strong class="nb-toast__title">Link copied</strong><span class="nb-toast__text">loudhaus.com/mira/ep-42</span></div><button class="btn btn-nb btn-nb-icon btn-nb-icon-sm" type="button" aria-label="Dismiss" data-bs-dismiss="toast"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div></div>
<div class="toast show nb-toast"><div class="toast-body"><span class="nb-toast__icon nb-toast__icon-cyan"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-clock"/></svg></span><div class="nb-toast__body"><strong class="nb-toast__title">Post scheduled</strong><span class="nb-toast__text">Goes live Fri 23 Oct, 9:00</span></div><button class="nb-toast__action" type="button">Undo</button><button class="btn btn-nb btn-nb-icon btn-nb-icon-sm" type="button" aria-label="Dismiss" data-bs-dismiss="toast"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div></div>
</div></section>
<section><span class="lbl">Tooltips · hover or focus, Escape hides</span><div class="nb-cluster tip-stage">
<span class="nb-tip nb-tip--open nb-tip--start" data-nb-tip><button class="btn btn-nb btn-nb-icon rounded-circle" type="button" aria-label="Share" aria-describedby="tip-share"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-share"/></svg></button><span class="nb-tip__bubble" role="tooltip" id="tip-share">Copy a share link</span></span>
<span class="nb-tip" data-nb-tip><button class="btn btn-nb btn-nb-icon" type="button" aria-label="Download" aria-describedby="tip-dl"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-download"/></svg></button><span class="nb-tip__bubble" role="tooltip" id="tip-dl">MP3, 42 MB</span></span>
<span class="nb-tip nb-tip--right" data-nb-tip><button class="btn btn-nb btn-sm" type="button" aria-describedby="tip-fee"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-info"/></svg>Fees</button><span class="nb-tip__bubble" role="tooltip" id="tip-fee">5% per sale, card costs included</span></span>
</div></section>
</div>
<div class="cols">
<section><span class="lbl">Dropdown · Escape or a click outside closes it</span><div class="menu-stage">
<div class="dropdown nb-dd"><button class="btn btn-nb dropdown-toggle show" type="button" aria-expanded="true" data-bs-toggle="dropdown" data-bs-display="static">Episode actions<svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-chev-down"/></svg></button>
<ul class="dropdown-menu show" data-bs-popper="static">
<li><button class="dropdown-item" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-edit"/></svg>Edit details<kbd>E</kbd></button></li>
<li><button class="dropdown-item" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-copy"/></svg>Duplicate<kbd>D</kbd></button></li>
<li><button class="dropdown-item" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-download"/></svg>Download audio</button></li>
<li aria-hidden="true"><hr class="dropdown-divider"></li>
<li><button class="dropdown-item nb-danger" type="button"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode</button></li>
</ul></div></div></section>
<section><span class="lbl">Modal · the native dialog</span>
<button class="btn btn-nb btn-nb-red" type="button" aria-haspopup="dialog" data-nb-open="dlg-delete"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode…</button>
<dialog class="nb-dialog" id="dlg-delete" aria-labelledby="dlg-delete-title" aria-describedby="dlg-delete-desc"><form method="dialog">
<div class="nb-dialog__head"><h2 class="nb-dialog__title nb-display" id="dlg-delete-title">Delete episode 42?</h2><button class="btn btn-nb btn-nb-icon btn-nb-icon-sm" type="submit" value="close" aria-label="Close"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
<div class="nb-dialog__body"><p id="dlg-delete-desc">“How we print 500 zines in a weekend” and its 38 comments are removed for good. Members who downloaded it keep their copy.</p></div>
<div class="nb-dialog__foot"><button class="btn btn-nb" type="submit" value="cancel">Keep it</button><button class="btn btn-nb btn-nb-red" type="submit" value="delete"><svg class="nb-ico" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode</button></div>
</form></dialog></section>
</div>
CSS
/* ── Neobrutalism UI kit tokens (uiCookies) — identical in every set ─────────────
   Thick ink borders, hard offset shadows and flat saturated fills on cream paper.
   Change a token and the whole kit follows; the border and shadow recipes below are built from them. */
:root{
  --nb-paper:#fff6e0;        /* page background, cream */
  --nb-surface:#ffffff;      /* card, field and button faces */
  --nb-ink:#111111;          /* text, 17.5:1 on paper */
  --nb-muted:#454036;        /* secondary text, 9.6:1 on paper */
  --nb-line:#111111;         /* border colour */
  --nb-bw:3px;               /* border width */
  --nb-shadow-x:4px;         /* hard shadow offset; pressed controls move this far into it */
  --nb-shadow-y:4px;
  --nb-shadow-color:#111111;
  --nb-radius:12px;          /* cards and panels */
  --nb-radius-sm:8px;        /* buttons and fields */
  --nb-focus:#1d4ed8;        /* dashed focus outline, 6.2:1 on paper, never the shadow */
  --nb-on-fill:#111111;      /* text on every palette fill below, 6.8:1 or more */
  --nb-on-fill-muted:#2b2822;/* secondary text on fills, 5.2:1 or more */
  --nb-lemon:#ffe14d;--nb-pink:#ff90d0;--nb-cyan:#62e2e8;--nb-lime:#b6f36a;
  --nb-orange:#ffa94d;--nb-violet:#b9a3ff;--nb-red:#ff6b6b;
  --nb-blue:#2448e0;--nb-on-blue:#ffffff; /* the only fill that takes white text, 6.8:1 */
  --nb-danger:#b42318;       /* destructive text, 6.1:1 on paper */
  --nb-font:"Space Grotesk","Archivo","Helvetica Neue",Arial,system-ui,sans-serif;
  --nb-font-display:"Archivo Black","Arial Black","Helvetica Neue",Arial,sans-serif;
}
/* Dark brutalism: data-nb="dark" on any wrapper, or a checked .nb-theme-input inside a [data-nb] element.
   :is() is a forgiving list, so browsers without :has() still apply data-nb="dark". Fills keep dark text. */
[data-nb]:is([data-nb="dark"],:has(.nb-theme-input:checked)){
  --nb-paper:#17150f;--nb-surface:#25221b;--nb-ink:#fbf3dc;--nb-muted:#d6ccb2;--nb-line:#fbf3dc;
  --nb-shadow-color:#fbf3dc;--nb-focus:#8db4ff;--nb-danger:#ff9b8f;color-scheme:dark}
/* More contrast requested: secondary text turns full ink */
@media (prefers-contrast:more){:root,[data-nb]:is([data-nb],:has(.nb-theme-input:checked)){--nb-muted:var(--nb-ink);--nb-on-fill-muted:var(--nb-on-fill)}}
:root,[data-nb]{
  --nb-border:var(--nb-bw) solid var(--nb-line);
  --nb-shadow:var(--nb-shadow-x) var(--nb-shadow-y) 0 0 var(--nb-shadow-color);
  --nb-shadow-sm:calc(var(--nb-shadow-x)*.5) calc(var(--nb-shadow-y)*.5) 0 0 var(--nb-shadow-color);
  --nb-shadow-lg:calc(var(--nb-shadow-x)*1.75) calc(var(--nb-shadow-y)*1.75) 0 0 var(--nb-shadow-color);
  --nb-shadow-hover:calc(var(--nb-shadow-x) + 2px) calc(var(--nb-shadow-y) + 2px) 0 0 var(--nb-shadow-color);
  --nb-press:var(--nb-shadow-x) var(--nb-shadow-y);                       /* translate for a pressed control */
  --nb-press-sm:calc(var(--nb-shadow-x)*.5) calc(var(--nb-shadow-y)*.5);  /* …for one with the small shadow */
}
[data-nb]{background:var(--nb-paper);color:var(--nb-ink);font-family:var(--nb-font)}
/* Bootstrap's own variables mapped onto the kit tokens */
:root,[data-nb]{--bs-body-bg:var(--nb-paper);--bs-body-color:var(--nb-ink);--bs-body-font-family:var(--nb-font);--bs-emphasis-color:var(--nb-ink);
  --bs-heading-color:var(--nb-ink);--bs-secondary-color:var(--nb-muted);--bs-tertiary-color:var(--nb-muted);
  --bs-border-color:var(--nb-line);--bs-border-width:var(--nb-bw);--bs-border-radius:var(--nb-radius-sm);--bs-border-radius-lg:var(--nb-radius);
  --bs-focus-ring-color:var(--nb-focus)}
/* Components */
.nb-ico{width:20px;height:20px;flex:none}
.nb-display{font-family:var(--nb-font-display);font-weight:900;letter-spacing:-.01em;line-height:1.05}
.nb-link{color:inherit;font-weight:700;text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}
.nb-link:hover{color:inherit;text-decoration-thickness:4px}
.nb-link:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:3px;border-radius:2px}
/* Buttons: Bootstrap .btn with a .btn-nb variant set through --bs-btn-* variables.
   Hover lifts it, pressing (or a checked .btn-check) moves it into its shadow */
.btn-nb{--nb-fill:var(--nb-surface);--nb-text:var(--nb-ink);--nb-btn-shadow:var(--nb-shadow);
  --bs-btn-padding-x:1.2rem;--bs-btn-padding-y:.6rem;--bs-btn-font-family:var(--nb-font);--bs-btn-font-size:1rem;--bs-btn-font-weight:700;--bs-btn-line-height:1.2;
  --bs-btn-border-width:var(--nb-bw);--bs-btn-border-radius:var(--nb-radius-sm);
  --bs-btn-bg:var(--nb-fill);--bs-btn-color:var(--nb-text);--bs-btn-border-color:var(--nb-line);
  --bs-btn-hover-bg:var(--nb-fill);--bs-btn-hover-color:var(--nb-text);--bs-btn-hover-border-color:var(--nb-line);
  --bs-btn-active-bg:var(--nb-fill);--bs-btn-active-color:var(--nb-text);--bs-btn-active-border-color:var(--nb-line);
  --bs-btn-disabled-bg:var(--nb-paper);--bs-btn-disabled-color:var(--nb-muted);--bs-btn-disabled-border-color:var(--nb-line);--bs-btn-disabled-opacity:1;
  --bs-btn-focus-box-shadow:var(--nb-btn-shadow);
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:46px;box-shadow:var(--nb-btn-shadow);transition:translate .12s,box-shadow .12s}
.btn-nb:hover{translate:-2px -2px;--nb-btn-shadow:var(--nb-shadow-hover)}
.btn-nb:active{translate:var(--nb-press);--nb-btn-shadow:none}
.btn-nb:focus-visible,.btn-check:focus-visible+.btn-nb{outline:3px dashed var(--nb-focus);outline-offset:5px;box-shadow:var(--nb-btn-shadow)}
.btn-nb-lemon{--nb-fill:var(--nb-lemon);--nb-text:var(--nb-on-fill)}
.btn-nb-pink{--nb-fill:var(--nb-pink);--nb-text:var(--nb-on-fill)}
.btn-nb-cyan{--nb-fill:var(--nb-cyan);--nb-text:var(--nb-on-fill)}
.btn-nb-lime{--nb-fill:var(--nb-lime);--nb-text:var(--nb-on-fill)}
.btn-nb-red{--nb-fill:var(--nb-red);--nb-text:var(--nb-on-fill)}
.btn-nb-blue{--nb-fill:var(--nb-blue);--nb-text:var(--nb-on-blue)}
.btn-nb-ink{--nb-fill:var(--nb-ink);--nb-text:var(--nb-paper)}
.btn-nb.btn-sm{--bs-btn-padding-x:.85rem;--bs-btn-padding-y:.4rem;--bs-btn-font-size:.875rem;--bs-btn-border-radius:var(--nb-radius-sm);min-height:38px}
.btn-nb.btn-lg{--bs-btn-padding-x:1.6rem;--bs-btn-padding-y:.8rem;--bs-btn-font-size:1.15rem;--bs-btn-border-radius:var(--nb-radius-sm);min-height:56px}
.btn-nb-icon{--bs-btn-padding-x:0;--bs-btn-padding-y:0;width:48px;height:48px;min-height:0}
.btn-nb-icon-sm{width:38px;height:38px;--nb-btn-shadow:var(--nb-shadow-sm)}
.btn-nb-icon-sm:hover{--nb-btn-shadow:var(--nb-shadow)}
.btn-nb-icon-sm:active{translate:var(--nb-press-sm)}
.btn-nb.rounded-circle{border-radius:50%}
.btn-nb:disabled{border-style:dashed;--nb-btn-shadow:none;translate:none}
.nb-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:18px}
.nb-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:20px}
.nb-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));gap:28px;align-items:start}
.nb-stack{display:grid;gap:1.25rem}
/* Alerts: Bootstrap .alert; the type is named by an icon, a bold title and hidden text, never by colour alone */
.alert.nb-alert{--bs-alert-bg:var(--nb-tone,var(--nb-cyan));--bs-alert-color:var(--nb-on-fill);--bs-alert-border-color:var(--nb-line);--bs-alert-border:var(--nb-border);
  --bs-alert-border-radius:var(--nb-radius);--bs-alert-padding-x:1.1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:0;--bs-alert-link-color:var(--nb-on-fill);
  display:flex;align-items:flex-start;gap:.85rem;box-shadow:var(--nb-shadow);font-family:var(--nb-font)}
.nb-alert-success{--nb-tone:var(--nb-lime)}.nb-alert-warning{--nb-tone:var(--nb-lemon)}.nb-alert-error{--nb-tone:var(--nb-red)}
.nb-alert__icon{display:grid;place-items:center;flex:none;width:38px;height:38px;border-radius:50%;background:var(--nb-on-fill);color:var(--nb-tone,var(--nb-cyan))}
.nb-alert__body{flex:1;min-width:0}
.nb-alert__title{margin:0;font-weight:800}
.nb-alert__body p+p{margin:.15rem 0 0}
.nb-alert .alert-link{font-weight:800;text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}
.nb-alert .alert-link:focus-visible{outline:3px dashed var(--nb-on-fill);outline-offset:3px}
/* Toasts: Bootstrap .toast in a polite live region, each with its own close button */
.nb-toasts{display:grid;gap:1rem;max-width:400px}
.toast.nb-toast{--bs-toast-max-width:100%;--bs-toast-bg:var(--nb-surface);--bs-toast-color:var(--nb-ink);--bs-toast-border-width:var(--nb-bw);--bs-toast-border-color:var(--nb-line);
  --bs-toast-border-radius:var(--nb-radius);--bs-toast-box-shadow:var(--nb-shadow-lg);--bs-toast-font-size:1rem;width:100%;font-family:var(--nb-font)}
.nb-toast .toast-body{display:flex;align-items:center;gap:.8rem;padding:.8rem .9rem}
.nb-toast__icon{display:grid;place-items:center;flex:none;width:38px;height:38px;border:var(--nb-border);border-radius:8px;background:var(--nb-lime);color:var(--nb-on-fill);rotate:-5deg}
.nb-toast__icon-cyan{background:var(--nb-cyan)}
.nb-toast__body{flex:1;min-width:0;line-height:1.35}
.nb-toast__title{display:block;font-weight:800}
.nb-toast__text{font-size:.9rem;color:var(--nb-muted)}
.nb-toast__action{padding:.2rem .1rem;border:0;background:none;color:var(--nb-ink);font:800 .9rem/1.2 var(--nb-font);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px;cursor:pointer}
.nb-toast__action:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:3px}
/* Tooltips: shown on hover and keyboard focus, tied to the trigger with aria-describedby, hidden again with Escape */
.nb-tip{position:relative;display:inline-flex}
.nb-tip__bubble{position:absolute;bottom:calc(100% + 14px);left:50%;z-index:5;width:max-content;max-width:220px;padding:.45rem .7rem;border:var(--nb-border);border-radius:var(--nb-radius-sm);
  background:var(--nb-lemon);color:var(--nb-on-fill);font:700 .85rem/1.3 var(--nb-font);box-shadow:var(--nb-shadow-sm);translate:-50% 0;visibility:hidden;opacity:0;transition:opacity .12s,visibility .12s}
.nb-tip__bubble::after{content:"";position:absolute;top:100%;left:50%;width:12px;height:12px;margin:-5px 0 0 -6px;border:solid var(--nb-line);border-width:0 var(--nb-bw) var(--nb-bw) 0;background:var(--nb-lemon);rotate:45deg}
.nb-tip:hover .nb-tip__bubble,.nb-tip:focus-within .nb-tip__bubble,.nb-tip--open .nb-tip__bubble{visibility:visible;opacity:1}
.nb-tip.is-dismissed .nb-tip__bubble{visibility:hidden;opacity:0}
.nb-tip--start .nb-tip__bubble{left:0;translate:none}
.nb-tip--start .nb-tip__bubble::after{left:24px}
.nb-tip--right .nb-tip__bubble{bottom:auto;top:50%;left:calc(100% + 14px);translate:0 -50%}
.nb-tip--right .nb-tip__bubble::after{top:50%;left:0;margin:-6px 0 0 -5px;border-width:0 0 var(--nb-bw) var(--nb-bw)}
@media (max-width:600px){.nb-tip--right .nb-tip__bubble{top:auto;bottom:calc(100% + 14px);left:50%;translate:-50% 0}.nb-tip--right .nb-tip__bubble::after{top:100%;left:50%;margin:-5px 0 0 -6px;border-width:0 var(--nb-bw) var(--nb-bw) 0}}
/* Dropdown: Bootstrap .dropdown-menu restyled through --bs-dropdown-*; Escape or a click outside closes it */
.nb-dd .dropdown-toggle::after{display:none}
.nb-dd .btn-nb.show{translate:var(--nb-press);--nb-btn-shadow:none}
.nb-dd .btn-nb .nb-ico:last-child{transition:rotate .12s}
.nb-dd .btn-nb.show .nb-ico:last-child{rotate:180deg}
.nb-dd .dropdown-menu{--bs-dropdown-min-width:230px;--bs-dropdown-padding-x:.4rem;--bs-dropdown-padding-y:.4rem;--bs-dropdown-spacer:12px;--bs-dropdown-bg:var(--nb-surface);
  --bs-dropdown-border-color:var(--nb-line);--bs-dropdown-border-width:var(--nb-bw);--bs-dropdown-border-radius:var(--nb-radius);--bs-dropdown-box-shadow:var(--nb-shadow-lg);
  --bs-dropdown-link-color:var(--nb-ink);--bs-dropdown-link-hover-color:var(--nb-on-fill);--bs-dropdown-link-hover-bg:var(--nb-lemon);--bs-dropdown-link-active-color:var(--nb-on-fill);--bs-dropdown-link-active-bg:var(--nb-lemon);
  --bs-dropdown-item-padding-x:.65rem;--bs-dropdown-item-padding-y:.5rem;--bs-dropdown-item-border-radius:6px;--bs-dropdown-divider-bg:var(--nb-line);--bs-dropdown-divider-margin-y:.3rem;
  box-shadow:var(--bs-dropdown-box-shadow)}
.nb-dd .dropdown-menu>li+li{margin-top:2px}
.nb-dd .dropdown-item{display:flex;align-items:center;gap:.65rem;border:2px solid transparent;font:700 .95rem/1.2 var(--nb-font)}
.nb-dd .dropdown-item kbd{margin-left:auto;padding:0 .35rem;border:2px solid currentColor;border-radius:4px;background:none;color:inherit;font:700 .72rem/1.4 var(--nb-font)}
.nb-dd .dropdown-item:hover{border-color:var(--nb-line)}
.nb-dd .dropdown-item:focus-visible{outline:3px dashed var(--nb-focus);outline-offset:1px}
.nb-dd .dropdown-item.nb-danger{color:var(--nb-danger)}
.nb-dd .dropdown-item.nb-danger:hover,.nb-dd .dropdown-item.nb-danger:focus{background:var(--nb-red);color:var(--nb-on-fill)}
.nb-dd .dropdown-divider{border-top-width:var(--nb-bw);opacity:1}
/* Modal: the native <dialog>. showModal() traps focus, makes the page inert and closes on Escape;
   buttons inside <form method="dialog"> close it without script */
.nb-dialog{width:min(100% - 32px,460px);padding:0;border:var(--nb-border);border-radius:var(--nb-radius);background:var(--nb-surface);color:var(--nb-ink);
  box-shadow:calc(var(--nb-shadow-x)*2.5) calc(var(--nb-shadow-y)*2.5) 0 0 var(--nb-shadow-color);font-family:var(--nb-font);overflow:visible}
.nb-dialog::backdrop{background:rgba(17,17,17,.6)}
.nb-dialog[open]{animation:nb-drop .18s ease-out}
@keyframes nb-drop{from{translate:0 -14px;opacity:0}}
.nb-dialog form{margin:0}
.nb-dialog__head{display:flex;align-items:center;gap:.8rem;padding:1rem 1.2rem;border-bottom:var(--nb-border);border-radius:calc(var(--nb-radius) - var(--nb-bw)) calc(var(--nb-radius) - var(--nb-bw)) 0 0;background:var(--nb-pink);color:var(--nb-on-fill)}
.nb-dialog__title{flex:1;margin:0;font-size:1.3rem}
.nb-dialog__head .nb-btn{--nb-fill:var(--nb-surface);--nb-text:var(--nb-ink)}
.nb-dialog__body{padding:1.2rem 1.2rem .4rem}
.nb-dialog__body p{margin:0 0 .8rem}
.nb-dialog__foot{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:14px;padding:.8rem 1.2rem 1.3rem}
@media (prefers-reduced-motion:reduce){[class*="nb-"],[class*="nb-"]::before,[class*="nb-"]::after{transition:none!important;animation:none!important}}
JavaScript
// Modal: any button with data-nb-open="dialog-id" opens that <dialog>; focus returns to the button on close
document.querySelectorAll('[data-nb-open]').forEach(function (btn) {
  var dialog = document.getElementById(btn.getAttribute('data-nb-open'));
  if (!dialog) return;
  btn.addEventListener('click', function () {
    dialog.showModal();
    dialog.addEventListener('close', function () { btn.focus(); }, { once: true });
  });
  dialog.addEventListener('click', function (e) { if (e.target === dialog) dialog.close(); }); // backdrop click
});
// Tooltips: Escape hides the visible tooltip until the pointer or focus leaves it
document.addEventListener('keydown', function (e) {
  if (e.key !== 'Escape') return;
  document.querySelectorAll('[data-nb-tip]').forEach(function (t) { if (t.matches(':hover, :focus-within')) t.classList.add('is-dismissed'); });
});
document.querySelectorAll('[data-nb-tip]').forEach(function (t) {
  ['mouseleave', 'focusout'].forEach(function (ev) { t.addEventListener(ev, function () { t.classList.remove('is-dismissed'); }); });
});
// Dropdown: create the instance now, so a menu that starts open also closes on an outside click
document.querySelectorAll('[data-bs-toggle="dropdown"]').forEach(function (el) { bootstrap.Dropdown.getOrCreateInstance(el); });

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="nb-i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v6M12 7.5h.01"/></symbol>
  <symbol id="nb-i-success" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m7.5 12.5 3 3 6-6.5"/></symbol>
  <symbol id="nb-i-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5 2.5 20h19z"/><path d="M12 10v4.5M12 17.5h.01"/></symbol>
  <symbol id="nb-i-error" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m8.5 8.5 7 7M15.5 8.5l-7 7"/></symbol>
  <symbol id="nb-i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m4.5 12.5 5 5L19.5 7"/></symbol>
  <symbol id="nb-i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6l12 12M18 6 6 18"/></symbol>
  <symbol id="nb-i-clock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/></symbol>
  <symbol id="nb-i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15V4M7.5 8.5 12 4l4.5 4.5M5 13v6.5h14V13"/></symbol>
  <symbol id="nb-i-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M4.5 19.5h15"/></symbol>
  <symbol id="nb-i-chev-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="nb-i-edit" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h4.5L19.5 9 15 4.5 4 15.5z"/><path d="m12.5 7 4.5 4.5"/></symbol>
  <symbol id="nb-i-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><rect x="8.5" y="8.5" width="12" height="12" rx="1.5"/><path d="M15.5 8.5V4.5a1 1 0 0 0-1-1h-10a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h4"/></symbol>
  <symbol id="nb-i-trash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6.5h16M9 6.5V4h6v2.5M6 6.5l1 14h10l1-14M10 10.5v6M14 10.5v6"/></symbol>
</svg>
<section><span class="mb-[18px] block text-[.72rem] font-extrabold tracking-[.12em] text-nb-muted uppercase">Alerts · the type is in the icon, the title and hidden text</span><div class="grid gap-5">
<div class="flex items-start gap-[.85rem] border-(length:--nb-bw) border-nb-line rounded-nb px-[1.1rem] py-4 font-nb text-nb-on-fill shadow-nb bg-nb-cyan" role="note"><span class="grid size-[38px] flex-none place-items-center rounded-full bg-nb-on-fill text-nb-cyan"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-info"/></svg></span><div class="min-w-0 flex-1"><p class="m-0 font-extrabold"><span class="sr-only">Information: </span>Payouts move to Fridays</p><p class="m-0 mt-[.15rem]">From 1 November, earnings are paid every Friday instead of on the first of the month.</p></div></div>
<div class="flex items-start gap-[.85rem] border-(length:--nb-bw) border-nb-line rounded-nb px-[1.1rem] py-4 font-nb text-nb-on-fill shadow-nb bg-nb-lime" role="note"><span class="grid size-[38px] flex-none place-items-center rounded-full bg-nb-on-fill text-nb-lime"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-success"/></svg></span><div class="min-w-0 flex-1"><p class="m-0 font-extrabold"><span class="sr-only">Success: </span>Post published</p><p class="m-0 mt-[.15rem]">It is live, and 12,480 subscribers were emailed. <a class="font-extrabold text-inherit underline decoration-2 underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[3px] focus-visible:outline-nb-on-fill" href="#">View post</a></p></div></div>
<div class="flex items-start gap-[.85rem] border-(length:--nb-bw) border-nb-line rounded-nb px-[1.1rem] py-4 font-nb text-nb-on-fill shadow-nb bg-nb-lemon" role="note"><span class="grid size-[38px] flex-none place-items-center rounded-full bg-nb-on-fill text-nb-lemon"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-alert"/></svg></span><div class="min-w-0 flex-1"><p class="m-0 font-extrabold"><span class="sr-only">Warning: </span>Storage almost full</p><p class="m-0 mt-[.15rem]">You have used 9.2 GB of 10 GB. New episodes may fail to upload.</p></div></div>
<div class="flex items-start gap-[.85rem] border-(length:--nb-bw) border-nb-line rounded-nb px-[1.1rem] py-4 font-nb text-nb-on-fill shadow-nb bg-nb-red" role="note"><span class="grid size-[38px] flex-none place-items-center rounded-full bg-nb-on-fill text-nb-red"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-error"/></svg></span><div class="min-w-0 flex-1"><p class="m-0 font-extrabold"><span class="sr-only">Error: </span>Payment failed</p><p class="m-0 mt-[.15rem]">We could not charge the card ending 4242. <a class="font-extrabold text-inherit underline decoration-2 underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[3px] focus-visible:outline-nb-on-fill" href="#">Update your card</a> by 20 October.</p></div></div>
</div></section>
<div class="grid grid-cols-1 gap-14 md:grid-cols-2">
<section><span class="mb-[18px] block text-[.72rem] font-extrabold tracking-[.12em] text-nb-muted uppercase">Toasts · in a polite live region</span><div class="grid max-w-[400px] gap-4" role="status" aria-live="polite">
<div class="flex items-center gap-[.8rem] border-(length:--nb-bw) border-nb-line rounded-nb bg-nb-surface px-[.9rem] py-[.8rem] font-nb text-nb-ink shadow-nb-lg" data-nb-toast><span class="grid size-[38px] flex-none -rotate-5 place-items-center border-(length:--nb-bw) border-nb-line rounded-lg text-nb-on-fill bg-nb-lime"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-check"/></svg></span><div class="min-w-0 flex-1 leading-[1.35]"><strong class="block font-extrabold">Link copied</strong><span class="text-[.9rem] text-nb-muted">loudhaus.com/mira/ep-42</span></div><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] size-[38px] rounded-nb-sm shadow-nb-sm transition-[translate,box-shadow] duration-[120ms] motion-reduce:transition-none hover:[translate:-2px_-2px] hover:shadow-nb active:[translate:var(--nb-press-sm)] active:shadow-none bg-nb-surface text-nb-ink" type="button" aria-label="Dismiss" data-nb-dismiss><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
<div class="flex items-center gap-[.8rem] border-(length:--nb-bw) border-nb-line rounded-nb bg-nb-surface px-[.9rem] py-[.8rem] font-nb text-nb-ink shadow-nb-lg" data-nb-toast><span class="grid size-[38px] flex-none -rotate-5 place-items-center border-(length:--nb-bw) border-nb-line rounded-lg text-nb-on-fill bg-nb-cyan"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-clock"/></svg></span><div class="min-w-0 flex-1 leading-[1.35]"><strong class="block font-extrabold">Post scheduled</strong><span class="text-[.9rem] text-nb-muted">Goes live Fri 23 Oct, 9:00</span></div><button class="cursor-pointer border-0 bg-transparent px-[.1rem] py-[.2rem] font-nb text-[.9rem] leading-[1.2] font-extrabold text-nb-ink underline decoration-2 underline-offset-[3px] focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[3px] focus-visible:outline-nb-focus" type="button">Undo</button><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] size-[38px] rounded-nb-sm shadow-nb-sm transition-[translate,box-shadow] duration-[120ms] motion-reduce:transition-none hover:[translate:-2px_-2px] hover:shadow-nb active:[translate:var(--nb-press-sm)] active:shadow-none bg-nb-surface text-nb-ink" type="button" aria-label="Dismiss" data-nb-dismiss><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
</div></section>
<section><span class="mb-[18px] block text-[.72rem] font-extrabold tracking-[.12em] text-nb-muted uppercase">Tooltips · hover or focus, Escape hides</span><div class="flex flex-wrap items-center gap-[18px] pt-16">
<span class="group/tip relative inline-flex is-open" data-nb-tip><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none size-12 rounded-full bg-nb-surface text-nb-ink" type="button" aria-label="Share" aria-describedby="tip-share"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-share"/></svg></button><span class="invisible absolute bottom-[calc(100%+14px)] left-0 z-5 w-max max-w-[220px] border-(length:--nb-bw) border-nb-line rounded-nb-sm bg-nb-lemon px-[.7rem] py-[.45rem] font-nb text-[.85rem] leading-[1.3] font-bold text-nb-on-fill opacity-0 shadow-nb-sm transition-[opacity,visibility] duration-[120ms] motion-reduce:transition-none group-hover/tip:visible group-hover/tip:opacity-100 group-focus-within/tip:visible group-focus-within/tip:opacity-100 group-[.is-open]/tip:visible group-[.is-open]/tip:opacity-100 group-[.is-dismissed]/tip:invisible group-[.is-dismissed]/tip:opacity-0 after:absolute after:top-full after:left-6 after:-mt-[5px] after:-ml-[6px] after:size-3 after:rotate-45 after:border-r-(length:--nb-bw) after:border-b-(length:--nb-bw) after:border-nb-line after:bg-nb-lemon after:content-['']" role="tooltip" id="tip-share">Copy a share link</span></span>
<span class="group/tip relative inline-flex" data-nb-tip><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none size-12 rounded-nb-sm bg-nb-surface text-nb-ink" type="button" aria-label="Download" aria-describedby="tip-dl"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-download"/></svg></button><span class="invisible absolute bottom-[calc(100%+14px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 border-(length:--nb-bw) border-nb-line rounded-nb-sm bg-nb-lemon px-[.7rem] py-[.45rem] font-nb text-[.85rem] leading-[1.3] font-bold text-nb-on-fill opacity-0 shadow-nb-sm transition-[opacity,visibility] duration-[120ms] motion-reduce:transition-none group-hover/tip:visible group-hover/tip:opacity-100 group-focus-within/tip:visible group-focus-within/tip:opacity-100 group-[.is-open]/tip:visible group-[.is-open]/tip:opacity-100 group-[.is-dismissed]/tip:invisible group-[.is-dismissed]/tip:opacity-0 after:absolute after:top-full after:left-1/2 after:-mt-[5px] after:-ml-[6px] after:size-3 after:rotate-45 after:border-r-(length:--nb-bw) after:border-b-(length:--nb-bw) after:border-nb-line after:bg-nb-lemon after:content-['']" role="tooltip" id="tip-dl">MP3, 42 MB</span></span>
<span class="group/tip relative inline-flex" data-nb-tip><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none rounded-nb-sm min-h-[38px] px-[.85rem] py-[.4rem] text-[.875rem] bg-nb-surface text-nb-ink" type="button" aria-describedby="tip-fee"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-info"/></svg>Fees</button><span class="invisible absolute bottom-[calc(100%+14px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 border-(length:--nb-bw) border-nb-line rounded-nb-sm bg-nb-lemon px-[.7rem] py-[.45rem] font-nb text-[.85rem] leading-[1.3] font-bold text-nb-on-fill opacity-0 shadow-nb-sm transition-[opacity,visibility] duration-[120ms] motion-reduce:transition-none group-hover/tip:visible group-hover/tip:opacity-100 group-focus-within/tip:visible group-focus-within/tip:opacity-100 group-[.is-open]/tip:visible group-[.is-open]/tip:opacity-100 group-[.is-dismissed]/tip:invisible group-[.is-dismissed]/tip:opacity-0 after:absolute after:top-full after:left-1/2 after:-mt-[5px] after:-ml-[6px] after:size-3 after:rotate-45 after:border-r-(length:--nb-bw) after:border-b-(length:--nb-bw) after:border-nb-line after:bg-nb-lemon after:content-[''] min-[601px]:top-1/2 min-[601px]:bottom-auto min-[601px]:left-[calc(100%+14px)] min-[601px]:translate-x-0 min-[601px]:-translate-y-1/2 min-[601px]:after:top-1/2 min-[601px]:after:left-0 min-[601px]:after:-mt-[6px] min-[601px]:after:-ml-[5px] min-[601px]:after:border-r-0 min-[601px]:after:border-l-(length:--nb-bw)" role="tooltip" id="tip-fee">5% per sale, card costs included</span></span>
</div></section>
</div>
<div class="grid grid-cols-1 gap-14 md:grid-cols-2">
<section><span class="mb-[18px] block text-[.72rem] font-extrabold tracking-[.12em] text-nb-muted uppercase">Dropdown · Escape or a click outside closes it</span><div class="min-h-[300px]">
<div class="relative inline-block"><button class="group/dd inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none rounded-nb-sm min-h-[46px] px-[1.2rem] py-[.6rem] text-base bg-nb-surface text-nb-ink aria-expanded:[translate:var(--nb-press)] aria-expanded:shadow-none" type="button" aria-expanded="true" aria-controls="dd-episode" data-nb-dropdown>Episode actions<svg class="size-5 shrink-0 transition-[rotate] duration-[120ms] motion-reduce:transition-none group-aria-expanded/dd:rotate-180" aria-hidden="true" focusable="false"><use href="#nb-i-chev-down"/></svg></button>
<ul class="absolute top-[calc(100%+12px)] left-0 z-10 m-0 grid min-w-[230px] list-none gap-[2px] border-(length:--nb-bw) border-nb-line rounded-nb bg-nb-surface p-[.4rem] shadow-nb-lg" id="dd-episode">
<li><button class="flex w-full cursor-pointer items-center gap-[.65rem] rounded-md border-2 border-transparent bg-transparent px-[.65rem] py-2 text-left font-nb text-[.95rem] leading-[1.2] font-bold text-nb-ink hover:border-nb-line hover:bg-nb-lemon hover:text-nb-on-fill focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-1 focus-visible:outline-nb-focus" type="button"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-edit"/></svg>Edit details<kbd class="ml-auto rounded-[4px] border-2 border-current px-[.35rem] font-nb text-[.72rem] leading-[1.4] font-bold">E</kbd></button></li>
<li><button class="flex w-full cursor-pointer items-center gap-[.65rem] rounded-md border-2 border-transparent bg-transparent px-[.65rem] py-2 text-left font-nb text-[.95rem] leading-[1.2] font-bold text-nb-ink hover:border-nb-line hover:bg-nb-lemon hover:text-nb-on-fill focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-1 focus-visible:outline-nb-focus" type="button"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-copy"/></svg>Duplicate<kbd class="ml-auto rounded-[4px] border-2 border-current px-[.35rem] font-nb text-[.72rem] leading-[1.4] font-bold">D</kbd></button></li>
<li><button class="flex w-full cursor-pointer items-center gap-[.65rem] rounded-md border-2 border-transparent bg-transparent px-[.65rem] py-2 text-left font-nb text-[.95rem] leading-[1.2] font-bold text-nb-ink hover:border-nb-line hover:bg-nb-lemon hover:text-nb-on-fill focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-1 focus-visible:outline-nb-focus" type="button"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-download"/></svg>Download audio</button></li>
<li class="my-[.3rem] h-0 border-t-(length:--nb-bw) border-nb-line" aria-hidden="true"></li>
<li><button class="flex w-full cursor-pointer items-center gap-[.65rem] rounded-md border-2 border-transparent bg-transparent px-[.65rem] py-2 text-left font-nb text-[.95rem] leading-[1.2] font-bold text-nb-danger hover:border-nb-line hover:bg-nb-red hover:text-nb-on-fill focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-1 focus-visible:outline-nb-focus" type="button"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode</button></li>
</ul></div></div></section>
<section><span class="mb-[18px] block text-[.72rem] font-extrabold tracking-[.12em] text-nb-muted uppercase">Modal · the native dialog</span>
<button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none rounded-nb-sm min-h-[46px] px-[1.2rem] py-[.6rem] text-base bg-nb-red text-nb-on-fill" type="button" aria-haspopup="dialog" data-nb-open="dlg-delete"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode…</button>
<dialog class="m-auto w-[min(100%-32px,460px)] overflow-visible border-(length:--nb-bw) border-nb-line rounded-nb bg-nb-surface p-0 font-nb text-nb-ink shadow-[calc(var(--nb-shadow-x)*2.5)_calc(var(--nb-shadow-y)*2.5)_0_0_var(--nb-shadow-color)] backdrop:bg-[rgba(17,17,17,.6)]" id="dlg-delete" aria-labelledby="dlg-delete-title" aria-describedby="dlg-delete-desc"><form class="m-0" method="dialog">
<div class="flex items-center gap-[.8rem] rounded-t-[calc(var(--nb-radius)-var(--nb-bw))] border-b-(length:--nb-bw) border-nb-line bg-nb-pink px-[1.2rem] py-4 text-nb-on-fill"><h2 class="m-0 flex-1 text-[1.3rem] font-nb-display font-black tracking-[-.01em] leading-[1.05]" id="dlg-delete-title">Delete episode 42?</h2><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] size-[38px] rounded-nb-sm shadow-nb-sm transition-[translate,box-shadow] duration-[120ms] motion-reduce:transition-none hover:[translate:-2px_-2px] hover:shadow-nb active:[translate:var(--nb-press-sm)] active:shadow-none bg-nb-surface text-nb-ink" type="submit" value="close" aria-label="Close"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-x"/></svg></button></div>
<div class="px-[1.2rem] pt-[1.2rem] pb-[.4rem] [&_p]:m-0 [&_p]:mb-[.8rem]"><p id="dlg-delete-desc">“How we print 500 zines in a weekend” and its 38 comments are removed for good. Members who downloaded it keep their copy.</p></div>
<div class="flex flex-wrap justify-end gap-3.5 px-[1.2rem] pt-[.8rem] pb-[1.3rem]"><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none rounded-nb-sm min-h-[46px] px-[1.2rem] py-[.6rem] text-base bg-nb-surface text-nb-ink" type="submit" value="cancel">Keep it</button><button class="inline-flex items-center justify-center gap-2 border-(length:--nb-bw) border-nb-line font-nb font-bold leading-[1.2] no-underline cursor-pointer focus-visible:outline-3 focus-visible:outline-dashed focus-visible:outline-offset-[5px] focus-visible:outline-nb-focus disabled:cursor-not-allowed disabled:border-dashed disabled:bg-nb-paper disabled:text-nb-muted disabled:shadow-none disabled:[translate:none] shadow-nb transition-[translate,box-shadow] duration-[120ms] hover:[translate:-2px_-2px] hover:shadow-nb-hover active:[translate:var(--nb-press)] active:shadow-none motion-reduce:transition-none rounded-nb-sm min-h-[46px] px-[1.2rem] py-[.6rem] text-base bg-nb-red text-nb-on-fill" type="submit" value="delete"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#nb-i-trash"/></svg>Delete episode</button></div>
</form></dialog></section>
</div>
CSS
/* ── Neobrutalism UI kit tokens (uiCookies) — identical in every set ─────────────
   Thick ink borders, hard offset shadows and flat saturated fills on cream paper.
   Change a token and the whole kit follows; the border and shadow recipes below are built from them. */
:root{
  --nb-paper:#fff6e0;        /* page background, cream */
  --nb-surface:#ffffff;      /* card, field and button faces */
  --nb-ink:#111111;          /* text, 17.5:1 on paper */
  --nb-muted:#454036;        /* secondary text, 9.6:1 on paper */
  --nb-line:#111111;         /* border colour */
  --nb-bw:3px;               /* border width */
  --nb-shadow-x:4px;         /* hard shadow offset; pressed controls move this far into it */
  --nb-shadow-y:4px;
  --nb-shadow-color:#111111;
  --nb-radius:12px;          /* cards and panels */
  --nb-radius-sm:8px;        /* buttons and fields */
  --nb-focus:#1d4ed8;        /* dashed focus outline, 6.2:1 on paper, never the shadow */
  --nb-on-fill:#111111;      /* text on every palette fill below, 6.8:1 or more */
  --nb-on-fill-muted:#2b2822;/* secondary text on fills, 5.2:1 or more */
  --nb-lemon:#ffe14d;--nb-pink:#ff90d0;--nb-cyan:#62e2e8;--nb-lime:#b6f36a;
  --nb-orange:#ffa94d;--nb-violet:#b9a3ff;--nb-red:#ff6b6b;
  --nb-blue:#2448e0;--nb-on-blue:#ffffff; /* the only fill that takes white text, 6.8:1 */
  --nb-danger:#b42318;       /* destructive text, 6.1:1 on paper */
  --nb-font:"Space Grotesk","Archivo","Helvetica Neue",Arial,system-ui,sans-serif;
  --nb-font-display:"Archivo Black","Arial Black","Helvetica Neue",Arial,sans-serif;
}
/* Dark brutalism: data-nb="dark" on any wrapper, or a checked .nb-theme-input inside a [data-nb] element.
   :is() is a forgiving list, so browsers without :has() still apply data-nb="dark". Fills keep dark text. */
[data-nb]:is([data-nb="dark"],:has(.nb-theme-input:checked)){
  --nb-paper:#17150f;--nb-surface:#25221b;--nb-ink:#fbf3dc;--nb-muted:#d6ccb2;--nb-line:#fbf3dc;
  --nb-shadow-color:#fbf3dc;--nb-focus:#8db4ff;--nb-danger:#ff9b8f;color-scheme:dark}
/* More contrast requested: secondary text turns full ink */
@media (prefers-contrast:more){:root,[data-nb]:is([data-nb],:has(.nb-theme-input:checked)){--nb-muted:var(--nb-ink);--nb-on-fill-muted:var(--nb-on-fill)}}
:root,[data-nb]{
  --nb-border:var(--nb-bw) solid var(--nb-line);
  --nb-shadow:var(--nb-shadow-x) var(--nb-shadow-y) 0 0 var(--nb-shadow-color);
  --nb-shadow-sm:calc(var(--nb-shadow-x)*.5) calc(var(--nb-shadow-y)*.5) 0 0 var(--nb-shadow-color);
  --nb-shadow-lg:calc(var(--nb-shadow-x)*1.75) calc(var(--nb-shadow-y)*1.75) 0 0 var(--nb-shadow-color);
  --nb-shadow-hover:calc(var(--nb-shadow-x) + 2px) calc(var(--nb-shadow-y) + 2px) 0 0 var(--nb-shadow-color);
  --nb-press:var(--nb-shadow-x) var(--nb-shadow-y);                       /* translate for a pressed control */
  --nb-press-sm:calc(var(--nb-shadow-x)*.5) calc(var(--nb-shadow-y)*.5);  /* …for one with the small shadow */
}
[data-nb]{background:var(--nb-paper);color:var(--nb-ink);font-family:var(--nb-font)}
/* The tokens above, exposed as Tailwind utilities: bg-nb-paper, bg-nb-lemon, text-nb-ink, border-nb-line,
   shadow-nb, shadow-nb-sm, shadow-nb-lg, rounded-nb, rounded-nb-sm, font-nb, font-nb-display, outline-nb-focus… */
@theme inline {
  --color-nb-paper: var(--nb-paper); --color-nb-surface: var(--nb-surface); --color-nb-ink: var(--nb-ink);
  --color-nb-muted: var(--nb-muted); --color-nb-line: var(--nb-line); --color-nb-focus: var(--nb-focus);
  --color-nb-on-fill: var(--nb-on-fill); --color-nb-on-fill-muted: var(--nb-on-fill-muted);
  --color-nb-lemon: var(--nb-lemon); --color-nb-pink: var(--nb-pink); --color-nb-cyan: var(--nb-cyan); --color-nb-lime: var(--nb-lime);
  --color-nb-orange: var(--nb-orange); --color-nb-violet: var(--nb-violet); --color-nb-red: var(--nb-red);
  --color-nb-blue: var(--nb-blue); --color-nb-on-blue: var(--nb-on-blue); --color-nb-danger: var(--nb-danger);
  --shadow-nb: var(--nb-shadow); --shadow-nb-sm: var(--nb-shadow-sm); --shadow-nb-lg: var(--nb-shadow-lg); --shadow-nb-hover: var(--nb-shadow-hover);
  --radius-nb: var(--nb-radius); --radius-nb-sm: var(--nb-radius-sm);
  --font-nb: var(--nb-font); --font-nb-display: var(--nb-font-display);
}
/* Starburst sticker outline (Tailwind has no clip-path utility) */
@utility clip-nb-burst {
  clip-path: polygon(50% 0%,59.1% 16.1%,75% 6.7%,74.8% 25.2%,93.3% 25%,83.9% 40.9%,100% 50%,83.9% 59.1%,93.3% 75%,74.8% 74.8%,75% 93.3%,59.1% 83.9%,50% 100%,40.9% 83.9%,25% 93.3%,25.2% 74.8%,6.7% 75%,16.1% 59.1%,0% 50%,16.1% 40.9%,6.7% 25%,25.2% 25.2%,25% 6.7%,40.9% 16.1%);
}
JavaScript
// Modal: any button with data-nb-open="dialog-id" opens that <dialog>; focus returns to the button on close
document.querySelectorAll('[data-nb-open]').forEach(function (btn) {
  var dialog = document.getElementById(btn.getAttribute('data-nb-open'));
  if (!dialog) return;
  btn.addEventListener('click', function () {
    dialog.showModal();
    dialog.addEventListener('close', function () { btn.focus(); }, { once: true });
  });
  dialog.addEventListener('click', function (e) { if (e.target === dialog) dialog.close(); }); // backdrop click
});
// Tooltips: Escape hides the visible tooltip until the pointer or focus leaves it
document.addEventListener('keydown', function (e) {
  if (e.key !== 'Escape') return;
  document.querySelectorAll('[data-nb-tip]').forEach(function (t) { if (t.matches(':hover, :focus-within')) t.classList.add('is-dismissed'); });
});
document.querySelectorAll('[data-nb-tip]').forEach(function (t) {
  ['mouseleave', 'focusout'].forEach(function (ev) { t.addEventListener(ev, function () { t.classList.remove('is-dismissed'); }); });
});
// Toasts: a close button removes its toast
document.querySelectorAll('[data-nb-dismiss]').forEach(function (b) {
  b.addEventListener('click', function () { b.closest('[data-nb-toast]').hidden = true; });
});
// Dropdown: toggle on click; Escape (focus back to the button) or a click outside closes it
document.querySelectorAll('[data-nb-dropdown]').forEach(function (btn) {
  var menu = document.getElementById(btn.getAttribute('aria-controls'));
  function set(open) { btn.setAttribute('aria-expanded', open); menu.hidden = !open; }
  btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
  document.addEventListener('click', function (e) { if (!btn.parentNode.contains(e.target)) set(false); });
  btn.parentNode.addEventListener('keydown', function (e) { if (e.key === 'Escape' && btn.getAttribute('aria-expanded') === 'true') { set(false); btn.focus(); } });
});

About this set

Feedback and overlay components with thick borders and hard shadows. Four alerts for information, success, a warning and an error fill cyan, lime, lemon and red, and carry their type in a round icon, a bold title and hidden text such as Warning:, so colour is never the only signal; links inside them are underlined. Two toasts sit in a polite live region, one with an Undo action, and each closes with its own button. Tooltips are lemon bubbles with an arrow that appear above or beside their trigger on hover and keyboard focus, are tied to it with aria-describedby and hide again with Escape; the first is pinned open in the preview. A dropdown of episode actions presses its button into its shadow while open and lists items with keyboard hints, a divider and a red Delete episode. The modal is the native dialog element with a pink header and an extra-deep shadow: showModal() traps focus, makes the page behind inert and closes on Escape, and its buttons close it through a form with method dialog. A short script opens it, returns focus to the button, and runs the toasts and dropdown. Bootstrap uses .alert, .toast and .dropdown with its own plugins.

What’s included

  • Native dialog with focus trap, Escape to close and focus return
  • Alerts that state their type in an icon, a title and hidden text
  • Toasts in a polite live region with working close buttons
  • Tooltips on hover and focus that hide with Escape
  • Dropdown that closes on Escape or an outside click

Accessibility

The dialog has aria-labelledby and aria-describedby and its trigger says aria-haspopup="dialog". Toasts are announced politely, tooltips use role="tooltip" and aria-describedby, and the dropdown button reports aria-expanded. Every control shows a 3px dashed focus outline. Animations and transitions stop under prefers-reduced-motion.

Customise it

Change the palette tokens for the alert tones (--nb-cyan, --nb-lime, --nb-lemon, --nb-red) and --nb-danger for the destructive menu item. Bootstrap maps the tokens onto --bs-alert-*, --bs-toast-* and --bs-dropdown-*; Tailwind uses bg-nb-red, shadow-nb-lg and a backdrop: utility on the dialog.