/* Blogger Zia - public stylesheet.
   One file for the whole public site (blog, archives, search, tool pages, the
   community page and the confirm page). Every colour, size and radius reads
   from the tokens in :root.

   SELECTOR POLICY. Authored content is styled by element, scoped to where it
   lives: h1-h6, p, ul, table, dl, details... inside .bz-content or
   .bz-main > article, so an editor never has to add a class for it to look
   right. A class is used only where a component has its own design (buttons,
   the drawer, the tool controls) or where the editor deliberately writes a
   modifier (.bz-align-*, .bz-text-*, .bz-hl-*, .bz-btn, .is-block).

   Long-form design history lives in README.md, not here: this file is
   render-blocking on every page, so it carries only the "why" a maintainer
   needs next to the rule. */

/* Tokens */

:root {
    --bz-pad: clamp(15px, 6vw, 96px);
    --bz-fs-sm:   14px;
    --bz-fs-md:   16px;
    --bz-fs-body: 18px;
    --bz-fs-lg:   20px;
    --bz-fs-xs:   12px;
    --bz-lh-prose: 2;
    --bz-gap: 1.75em;
    --bz-bg: #fff;
    --bz-primary: #212121;
    --bz-primary-h: #121212;
    --bz-cta-h: 83px;
    --bz-muted: #555555;
    --bz-surface: #f5f5f5;
    --bz-line: #dddddd;
    --bz-border: 1px solid var(--bz-line);
    --bz-link: #1557b0;
    --bz-link-h: #0d3c7d;
    --bz-radius: 6px; /* the one corner radius: every box, field, button, image and tile reads it; only true circles use 50% */
    --bz-radius-in: calc(var(--bz-radius) - 1px); /* a child that sits inside a 1px border of a --bz-radius box */
    --bz-fs-h2: calc(var(--bz-fs-lg) * 1.25);
    /* A button's top/bottom padding, by size. A button is as tall as its label plus this, and the
       three sizes are the three places buttons appear (see the Buttons note further down): a
       lone button, one of a pair, and a full-width one. Each is a clamp() on the viewport, so a
       phone gets the small end and a desktop the large one. */
    --bz-btn-py-s: clamp(8px, 1.8vw, 10px);
    --bz-btn-py-m: clamp(10px, 2.4vw, 13px);
    --bz-btn-py-l: clamp(13px, 3vw, 16px);
    --bz-btn-h-l: calc(1.3 * var(--bz-fs-md) + 2 * var(--bz-btn-py-l)); /* a large button's height, for what sits beside one */
    --bz-transition: 0.18s ease; /* the one hover/focus feedback speed; slower motion (drawer slide, image zoom) keeps its own */
    --bz-danger: #d32f2f;
    --bz-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell,
               "Kohinoor Bangla", "Nirmala UI", "Vrinda", "Hind Siliguri", "Noto Sans Bengali", "Mukti", "Lohit Bengali",
               "Geeza Pro", "Arabic Typesetting", "Noto Sans Arabic", "Scheherazade New",
               sans-serif;
    --bz-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

/* Bangla and Arabic system fonts are shrunk a little (size-adjust) so their
      glyphs sit at the same visual size as the Latin text around them. */

@font-face { font-family: "Nirmala UI";        src: local("Nirmala UI");        size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Vrinda";            src: local("Vrinda");            size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Hind Siliguri";     src: local("Hind Siliguri");     size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Kohinoor Bangla";   src: local("Kohinoor Bangla");   size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Noto Sans Bengali"; src: local("Noto Sans Bengali"); size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Mukti";             src: local("Mukti");             size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Lohit Bengali";     src: local("Lohit Bengali");     size-adjust: 90%; unicode-range: U+0980-09FF; }

@font-face { font-family: "Geeza Pro";          src: local("Geeza Pro");          size-adjust: 85%; unicode-range: U+0600-06FF; }

@font-face { font-family: "Noto Sans Arabic";   src: local("Noto Sans Arabic");   size-adjust: 85%; unicode-range: U+0600-06FF; }

@font-face { font-family: "Arabic Typesetting"; src: local("Arabic Typesetting"); size-adjust: 85%; unicode-range: U+0600-06FF; }

@font-face { font-family: "Scheherazade New";   src: local("Scheherazade New");   size-adjust: 85%; unicode-range: U+0600-06FF; }

/* Reset and base */

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

ul, ol { list-style: none; }

/* Default-tag resets: elements that carry their own UA styling and are used
   bare (no .bz- class) in places like tool-option fieldsets - a fieldset
   with no class must look like plain flow content, not a boxed browser
   widget. Anything that DOES want a border/box is a class (.bz-seg,
   .bz-msg, etc.), never the bare element. */
fieldset { border: none; min-width: 0; }

legend { padding: 0; }

button, input, select, textarea, optgroup { font: inherit; color: inherit; }

body {
    margin: 0;
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
    font-family: var(--bz-font);
    font-size: var(--bz-fs-body);
    color: var(--bz-primary);
    background: var(--bz-bg);
}

.bz-skip-link {
    position: absolute;
    top: -100px;
    left: 0;
    z-index: 999;
    padding: 10px 18px;
    background: var(--bz-primary);
    color: var(--bz-bg);
    font-size: var(--bz-fs-sm);
    font-weight: 600;
    text-decoration: none;
    transition: top 0.15s ease;
}

.bz-skip-link:focus { top: 0; }

.bz-drawer-divider > span,
.bz-signup-or {
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    color: var(--bz-muted);
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.bz-sep-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

.bz-sep-row span[aria-hidden] {
    margin-inline: 8px;
    color: var(--bz-line);
}

/* Utilities */

.bz-hidden { display: none !important; }
/* Hidden on screen, still read by assistive tech. Not display:none / visibility:hidden,
   which would remove the element from the accessibility tree. */
.bz-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    border: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.bz-offscreen {
    position: absolute;
    left: -9999px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.bz-text-sm { font-size: var(--bz-fs-sm); color: var(--bz-muted); }

.bz-text-xs { font-size: var(--bz-fs-xs); color: var(--bz-muted); }

/* Icons. Each .bz-icon-* only names its shape (--bz-icon); the mask and the
   size live once on .bz-icon, and the colour is currentColor. */

.bz-icon,
.bz-row::after {
    display: inline-block;
    vertical-align: middle;
    width: 10px;
    height: 10px;
    background-color: currentColor;
    flex-shrink: 0;
    mask: var(--bz-icon) center / contain no-repeat;
}

.bz-icon-chevron,
.bz-row::after { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 6 15 12 9 18'/%3E%3C/svg%3E"); }

.bz-icon-search { width: 16px; height: 16px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E"); }

.bz-icon-mail { width: 18px; height: 18px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m22 7-10 5L2 7'/%3E%3C/svg%3E"); }

.bz-icon-fb { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M24 12.073C24 5.405 18.627 0 12 0S0 5.405 0 12.073C0 18.1 4.388 23.094 10.125 24v-8.437H7.078v-3.49h3.047V9.41c0-3.025 1.792-4.697 4.533-4.697 1.312 0 2.686.236 2.686.236v2.97h-1.513c-1.491 0-1.956.93-1.956 1.886v2.268h3.328l-.532 3.49h-2.796V24C19.612 23.094 24 18.1 24 12.073z'/%3E%3C/svg%3E"); }

.bz-icon-yt { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E"); }

.bz-icon-ig { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5zm5 5.8A4.2 4.2 0 1 0 16.2 12 4.2 4.2 0 0 0 12 7.8zm6.4-1.9a1 1 0 1 0 1 1 1 1 0 0 0-1-1z'/%3E%3C/svg%3E"); }

.bz-icon-tt { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z'/%3E%3C/svg%3E"); }

.bz-icon-wa { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.5 3.5A11.8 11.8 0 0 0 12 0C5.4 0 .1 5.3.1 11.9c0 2.1.6 4.2 1.7 6L0 24l6.3-1.7c1.8 1 3.8 1.5 5.8 1.5 6.6 0 11.9-5.3 11.9-11.9 0-3.2-1.3-6.2-3.5-8.4zM12 21.3c-1.8 0-3.6-.5-5.1-1.4l-.4-.2-3.7 1 1-3.6-.2-.4A9.4 9.4 0 1 1 21.4 12 9.4 9.4 0 0 1 12 21.3z'/%3E%3Cpath d='M17 14.6c-.3-.2-1.7-.8-2-1s-.5-.2-.7.1-.8 1-1 1.2-.4.2-.7.1a6.7 6.7 0 0 1-2.1-1.3 8 8 0 0 1-1.4-1.7c-.2-.3 0-.5.1-.7l.5-.6c.2-.2.2-.4.3-.6.1-.2 0-.4 0-.6s-.7-1.7-1-2.3c-.3-.6-.6-.5-.8-.5h-.7c-.2 0-.6.1-.9.4s-1.1 1.1-1.1 2.7 1.1 3.2 1.3 3.5c.2.3 2.2 3.3 5.3 4.6.7.3 1.3.5 1.7.6.7.2 1.4.2 1.9.1.6-.1 1.7-.7 1.9-1.4.2-.7.2-1.3.1-1.4-.1-.2-.3-.3-.6-.5z'/%3E%3C/svg%3E"); }

.bz-icon-key { width: 20px; height: 20px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='7.5' cy='15.5' r='4.5'/%3E%3Cpath d='m10.7 12.3 9.8-9.8M16 7l3 3M14 9l2 2'/%3E%3C/svg%3E"); }

.bz-icon-image { width: 20px; height: 20px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Ccircle cx='8.5' cy='9.5' r='1.5'/%3E%3Cpath d='m21 15-5-5-9 9'/%3E%3C/svg%3E"); }

.bz-icon-pdf { width: 20px; height: 20px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='8' y1='13' x2='16' y2='13'/%3E%3Cline x1='8' y1='17' x2='13' y2='17'/%3E%3C/svg%3E"); }

.bz-icon-trophy { width: 20px; height: 20px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 4h10v4a5 5 0 0 1-10 0z'/%3E%3Cpath d='M7 5H4a1 1 0 0 0-1 1c0 3 2 5 4 5'/%3E%3Cpath d='M17 5h3a1 1 0 0 1 1 1c0 3-2 5-4 5'/%3E%3Cpath d='M8 21h8M12 17v4'/%3E%3C/svg%3E"); }

.bz-icon-upload { width: 20px; height: 20px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 16V4M7 9l5-5 5 5M4 16v3a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-3'/%3E%3C/svg%3E"); }

/* Header */

.bz-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-inline: var(--bz-pad);
    padding-block: 14px;
    border-bottom: var(--bz-border);
    background: var(--bz-bg);
    position: sticky;
    top: 0;
    z-index: 200;
}

/* .bz-brand takes all the leftover space via margin-inline-end: auto, which
   keeps every sibling that follows (subscribe, menu) grouped together at the
   trailing edge with the header's own gap between them - the same result
   .bz-header's old justify-content: space-between gave for two children,
   but one that still works now that there are three. */
.bz-brand {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--bz-primary);
    text-decoration: none;
    white-space: nowrap;
    margin-inline-end: auto;
}

.bz-brand:hover { color: var(--bz-muted); }

/* Title Case comes from text-transform, not from rewriting SITE_TAGLINE's
   case in .env - capitalize() fixes it however the value is typed there.
   Size + tracking are both nudged up together so the line's rendered width
   sits close to BLOGGER ZIA's above it, rather than reading as an
   afterthought under the much heavier brand wordmark. */
.bz-tagline {
    font-size: var(--bz-fs-xs);
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: capitalize;
    color: var(--bz-muted);
}

/* Doubled with .bz-btn on purpose: the shared .bz-btn (padding, font-size,
   min-width) is defined far below this rule with the same specificity, so a
   bare .bz-btn-community lost to it and rendered at body size, 10px padding and
   a 9rem floor even in the icon-only layout. */
.bz-btn.bz-btn-community {
    height: 40px;
    padding-inline: 16px;
    font-size: var(--bz-fs-sm);
    text-transform: uppercase;
    flex-shrink: 0;
}

/* Sticky header, so the icon-only fallback (no extra row, no lost width)
   stays out of the way on every scroll position rather than just once. */
@media ( max-width: 600px ) {
    .bz-btn-community-label { display: none; }
    /* min-width: 0 - the site-wide .bz-btn floor (9rem) would otherwise beat this
       40px and stretch the icon-only button. */
    .bz-btn.bz-btn-community { width: 40px; min-width: 0; padding-inline: 0; }
}

.bz-btn-menu {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    flex-shrink: 0;
}

.bz-btn-menu span {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--bz-primary);
    border-radius: var(--bz-radius);
    box-shadow: 0 -7px 0 var(--bz-primary), 0 7px 0 var(--bz-primary);
}

/* Nav drawer (right-side slide-in). Closed = inert + off-canvas; script.js toggles .is-open. */

.bz-drawer-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
    z-index: 500;
}

.bz-drawer-overlay.is-open {
    opacity: 1;
    pointer-events: auto;
}

.bz-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 320px;
    max-width: 85vw;
    background: var(--bz-bg);
    border-left: var(--bz-border);
    transform: translateX(100%);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
    z-index: 501;
    display: flex;
    flex-direction: column;
}

.bz-drawer.is-open { transform: translateX(0); box-shadow: -8px 0 24px rgba(0, 0, 0, 0.12); }

.bz-no-scroll { overflow: hidden; }

.bz-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-inline: 24px;
    padding-block: 14px;
    border-bottom: var(--bz-border);
}

.bz-drawer-head strong { font-size: var(--bz-fs-body); }

.bz-btn-close {
    width: 32px;
    height: 32px;
    border: none;
    background: none;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    color: var(--bz-primary);
}

.bz-drawer-body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.bz-drawer-body > * { flex-shrink: 0; }

.bz-drawer-footer {
    position: sticky;
    bottom: 0;
    z-index: 2;
    padding: 15px 20px;
    background: var(--bz-bg);
    border-top: var(--bz-border);
}

.bz-drawer-divider {
    position: relative;
    border-top: var(--bz-border);
}

.bz-drawer-divider > span {
    position: absolute;
    top: 0;
    left: 12px;
    transform: translateY(-50%);
    padding: 0 8px;
    background: var(--bz-bg);
}

.bz-drawer-footer + .bz-drawer-divider { margin-top: 14px; }

/* "View all" sits on the divider line, opposite the label: same knockout
   background so the line breaks around it, same 12px inset as the label. */
.bz-drawer-divider > a {
    position: absolute;
    top: 0;
    right: 12px;
    transform: translateY(-50%);
    padding: 0 8px;
    background: var(--bz-bg);
    font-size: var(--bz-fs-xs);
    line-height: 1;
    color: var(--bz-muted);
    text-decoration: none;
    transition: color var(--bz-transition);
}

.bz-drawer-divider > a:hover { color: var(--bz-primary); }

.bz-drawer-divider > a:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: 2px; }

/* Chrome buttons (header + drawer Subscribe) are uppercase like the brand and
   Prev/Next; content buttons ("Visit site") stay sentence case. */
.bz-drawer-footer .bz-btn { text-transform: uppercase; }

.bz-drawer-main {
    --bz-drawer-gap: 64px; /* above every group divider and above the sticky footer */
    min-height: calc(100% - var(--bz-cta-h));
    padding: 20px 20px var(--bz-drawer-gap);
}

/* Drawer menu. The nav groups run edge to edge (the negative margin cancels
   .bz-drawer-main's padding), so each label-on-the-line divider and each row's
   hover is a nudge (see below), not a surface. Rows are separated by a hairline that stops at
   the 20px padding (36px, the text indent, inside a submenu), drawn as a ::before
   so the row can stay full width; the last row of a list has none.
   The dividers separate the groups (a big gap above, a small one below, so a
   label reads as belonging to the list under it). Only an entry with children
   (Tools) gets .bz-drawer-toggle, a chevron button at the row's end: the link
   takes the rest of the row and the chevron only expands. Hover moves the label
   4px right and darkens it; there is no background. */

.bz-drawer-navs { margin-inline: -20px; margin-top: 4px; }

.bz-drawer-navs .bz-drawer-divider { margin-top: var(--bz-drawer-gap); }

.bz-drawer-list { list-style: none; margin: 0; padding: 12px 0 0; }

.bz-drawer-list li { position: relative; }

.bz-drawer-list li + li::before,
.bz-drawer-list .bz-drawer-sub li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 20px;
    right: 20px;
    height: 1px;
    background: var(--bz-line);
    pointer-events: none;
}

.bz-drawer-list .bz-drawer-sub li::before { left: 36px; }

/* The line above the FIRST submenu item is the parent row's bottom line, so it
   keeps the parent's 20px inset; only the lines between submenu items indent. */
.bz-drawer-list .bz-drawer-sub li:first-child::before { left: 20px; }

.bz-drawer-list a {
    display: block;
    padding: 13px 20px;
    font-size: var(--bz-fs-md);
    font-weight: 400;
    line-height: 1.4;
    color: var(--bz-primary);
    text-decoration: none;
    transition: padding-left var(--bz-transition), color var(--bz-transition);
}

.bz-drawer-list a:hover { padding-left: 24px; color: var(--bz-primary-h); }

.bz-drawer-list a:focus-visible,
.bz-drawer-toggle:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: -2px; }

.bz-drawer-list a[aria-current="page"] {
    color: var(--bz-primary);
    font-weight: 700;
    box-shadow: inset 3px 0 0 var(--bz-primary);
}

/* A compact group (This site) sets its links in two columns and drops the
   per-row hairlines, which would otherwise be drawn across the top of the
   second column. */
.bz-drawer-list.is-compact { display: grid; grid-template-columns: 1fr 1fr; }

.bz-drawer-list.is-compact li + li::before { content: none; }

.bz-drawer-list.is-compact a { padding: 11px 20px; font-size: var(--bz-fs-sm); font-weight: 400; }

.bz-drawer-list.is-compact a:hover { padding-left: 24px; }

.bz-drawer-row { display: flex; align-items: stretch; }

.bz-drawer-row > a { flex: 1 1 auto; }

.bz-drawer-toggle {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    border: 0;
    background: none;
    color: var(--bz-muted);
    cursor: pointer;
    transition: color var(--bz-transition);
}

.bz-drawer-toggle:hover { color: var(--bz-primary); }

/* The shared chevron points right; closed = down, open = up. */
.bz-drawer-toggle .bz-icon { width: 14px; height: 14px; transform: rotate(90deg); transition: transform 0.25s ease; }

.is-open > .bz-drawer-row .bz-drawer-toggle .bz-icon { transform: rotate(-90deg); }

/* Height animates through the grid row (0fr -> 1fr). A collapsed list is
   visibility:hidden, so its links are not tabbable. */
.bz-drawer-sub { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.25s ease; }

.is-open > .bz-drawer-sub { grid-template-rows: 1fr; }

.bz-drawer-sub > ul {
    list-style: none;
    min-height: 0;
    overflow: hidden;
    visibility: hidden;
    transition: visibility 0s linear 0.25s;
}

.is-open > .bz-drawer-sub > ul { visibility: visible; transition-delay: 0s; }

.bz-drawer-sub a { padding: 11px 20px 11px 36px; font-size: var(--bz-fs-sm); font-weight: 400; }

.bz-drawer-sub a:hover { padding-left: 40px; }

.bz-drawer-sub a[aria-current="page"] { font-weight: 600; }

/* Page shell */

.bz-main {
    flex: 1 0 auto;
    width: 100%;
    max-width: calc(650px + var(--bz-pad) * 2);
    margin-inline: auto;
    padding-inline: var(--bz-pad);
    padding-block: clamp(32px, 6vw, 64px);
}

/* Every public page is one 650px column: the width is on <main> itself, so an article,
   a list page, a breadcrumb and the post navigation need no width of their own. The
   rhythm below is one top margin between <main>'s direct children (the page head and
   the content under it, with no <article> wrapper on the list pages). */
.bz-main > * + * { margin-top: var(--bz-gap); }

:is(.bz-main > article > h1, .bz-page-head h1) {
    font-size: clamp(calc(var(--bz-fs-lg) * 1.6), 4vw, calc(var(--bz-fs-lg) * 1.8));
    font-weight: 700;
    line-height: 1.6;
    margin: 0;
    text-box-trim: trim-start;
    text-box-edge: cap alphabetic;
}

/* Header-internal flow (h1, optional intro, meta pills):
   same single-direction, top-margin-only pattern as everywhere else, one level
   deeper again. h1 is always first, so it carries no margin of its own either -
   whichever of these blocks is actually present picks up its own margin-top
   from whichever block ends up before it, so removing any one of them (say,
   a post with no intro) never leaves a stray double-gap or a missing one. */
.bz-page-head > * + * { margin-top: 1.25rem; }

/* Was .bz-intro - it only ever appeared inside a .bz-page-head, so scoping
   by tag instead removes a class name the parent selector already implied.
   Plain body font/color, no muted override - it's page-head's own summary
   text, not secondary metadata. */
.bz-page-head p {
    font-size: var(--bz-fs-body);
    line-height: 1.6;
}

/* The breadcrumb (alone, or in its row with the language toggle) is a direct child
   of <main>, outside the article, right before the article or the page head: the
   one gap between them, overriding the container's own top-margin rhythm. */
.bz-main > :is(.bz-breadcrumb, .bz-split-row) + * { margin-top: 1rem; }

/* Breadcrumb (left) and language toggle (right) share one line at every
   width: the breadcrumb truncates (its crumbs shrink), the toggle never
   wraps or shrinks. */
/* Text on the left, one control on the right: the breadcrumb and its language toggle, a page title
   and its filter button. */
.bz-split-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.bz-split-row :is(.bz-breadcrumb, h1) { min-width: 0; }
.bz-split-row .bz-lang-toggle { flex-shrink: 0; }

/* Language toggle (front/single.php): one bordered box on the breadcrumb's row
   (.bz-split-row), shown only when a Bangla version exists: [ English | Bangla ]. It is a
   control, not a fact, so it is kept out of the meta strip. One --bz-border box with the
   default --bz-radius and a divider between the segments, so there is no border inside a
   border. The current language is the segment on a --bz-surface fill with --bz-primary text;
   the other is a link in --bz-muted. No weight change: bold Bangla looks heavy beside regular
   English. English is always the first segment, so nothing moves when the reader switches. It
   sits outside the article, so the content link rule never reaches it. */
.bz-lang-toggle {
    display: inline-flex;
    align-items: stretch;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    font-size: var(--bz-fs-sm);
    line-height: 1.3;
}

.bz-lang-toggle > * {
    padding: 0.2em 0.75em;
    text-decoration: none;
    white-space: nowrap;
}

/* The segments carry the box's inner radius themselves (no overflow:hidden, which would clip
   the link's tap area below). */
.bz-lang-toggle > :first-child { border-radius: var(--bz-radius-in) 0 0 var(--bz-radius-in); }

.bz-lang-toggle > :last-child  { border-radius: 0 var(--bz-radius-in) var(--bz-radius-in) 0; }

.bz-lang-toggle > * + * { border-left: var(--bz-border); }

.bz-lang-toggle a {
    position: relative;
    color: var(--bz-muted);
    transition: color var(--bz-transition);
}

/* The box is small, so the link's tap area is stretched 6px up and down with an
   invisible pseudo-element - the visible size stays put. */
.bz-lang-toggle a::after { content: ""; position: absolute; inset: -6px 0; }

.bz-lang-toggle a:hover { color: var(--bz-primary); }

.bz-lang-toggle [aria-current] {
    background: var(--bz-surface);
    color: var(--bz-primary);
}

.bz-lang-toggle a:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: 2px; }

/* Plain text, not a pill: a breadcrumb is orientation (how you got here),
   never an action, so it must not read as a clickable chip like the real
   chips (.bz-affiliate-note). Sits above the title. */
.bz-breadcrumb {
    display: flex;
    flex-wrap: nowrap; /* overrides .bz-sep-row's wrap: one line, the tail truncates */
    white-space: nowrap;
    align-items: center;
    gap: 0.4em;
    margin: 0;
    font-size: var(--bz-fs-sm);
    color: var(--bz-muted);
    max-width: 100%;
}

.bz-breadcrumb a {
    color: inherit;
    text-decoration: none;
    flex-shrink: 0;
}

.bz-breadcrumb a:hover { text-decoration: underline; }

/* The shared separator colour (--bz-line) is what a divider wants, but on a
   pill's own grey fill it all but vanishes; inside a pill it takes the
   text's muted colour, and the pill's gap does the spacing. */
.bz-breadcrumb.bz-sep-row span[aria-hidden] { margin-inline: 0; color: var(--bz-muted); }

.bz-breadcrumb .bz-crumb-tail {
    flex-shrink: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* The current page repeats the <h1> right below, so on wide screens it is
   capped instead of showing the whole title; on narrow ones flex-shrink above
   truncates it to whatever room the row has left. */
.bz-breadcrumb [aria-current] { max-width: 32ch; }

/* Meta strip - the one facts row under a page head (post, directory entry,
   tool): small muted text, each item an optional leading icon. The two
   hairlines above and below are what separate the head from the content, so
   nothing else has to. Plain wrapping row; at most three items keeps it to a
   single line. */
.bz-meta-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 22px;
    padding-block: 11px;
    border-block: var(--bz-border);
    font-size: var(--bz-fs-sm);
    line-height: 1.5;
    color: var(--bz-muted);
}
.bz-meta-strip > span { display: inline-flex; align-items: center; gap: 6px; }
.bz-meta-strip .bz-icon { width: 15px; height: 15px; }

/* Links in the strip (a post's tags) read as the strip's muted text, like the breadcrumb's:
   no underline until hover. */
.bz-meta-strip a { color: inherit; text-decoration: none; }
.bz-meta-strip a:hover { text-decoration: underline; text-underline-offset: 2px; }

/* Article column and vertical rhythm.
   The article itself is .bz-content on posts, so it also holds the breadcrumb, the
   pager and the gallery: rules that select descendants (links, lists) carry a
   :not() opt-out for those components. */

.bz-content {
    font-size: var(--bz-fs-body);
    line-height: var(--bz-lh-prose);
    color: var(--bz-primary);
    text-box-trim: trim-end;
    text-box-edge: text alphabetic;
}

.bz-main > article > * + * { margin-top: var(--bz-gap); }

.bz-main > article > * + h2 { margin-top: 2.5em; }

.bz-main > article > * + h3 { margin-top: 2em; }

/* Tool pages wrap their controls in a <form> (front/tools/*.php) - the rule
   above only spans DIRECT children of <article>, so without this, everything
   inside that <form> (drop zone, table, fieldset, buttons) sits flush against
   its neighbour with no gap at all. Same one-value, top-margin-only pattern,
   just scoped one level deeper. The site search box (.bz-search) is exempt: it is a
   single flex row, and a top margin on its button pushed the button out of the box
   on the 404 page, the one place the box sits inside an <article>. */
.bz-main > article form:not(.bz-search) > * + *, #bz-rwp-results-section > * + * { margin-top: var(--bz-gap); }

.bz-content > * + * { margin-top: var(--bz-gap); }

.bz-content > * + h2 { margin-top: 2.5em; }

.bz-content > * + h3 { margin-top: 2em; }

.bz-main > article > * + .bz-content > h2:first-child { margin-top: 2.5em; }

.bz-main > article > * + .bz-content > h3:first-child { margin-top: 2em; }

/* Headings are typed per article, prose or not (FAQ and tool-page headings included). */

.bz-main > article h2 { font-size: var(--bz-fs-h2); font-weight: 700; line-height: 1.45; }

.bz-main > article h3 { font-size: var(--bz-fs-lg); font-weight: 700; line-height: 1.45; }

.bz-main > article h4 { font-size: var(--bz-fs-body); font-weight: 700; line-height: 1.45; }

.bz-main > article h5 { font-size: var(--bz-fs-body); font-weight: 600; line-height: 1.45; }

.bz-main > article h6 {
    font-size: var(--bz-fs-sm);
    font-weight: 600;
    line-height: 1.4;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--bz-muted);
}

/* Lists, links, quotes, code, media, tables */

.bz-content ul:not(.bz-gallery-grid, .bz-list, .bz-files) {
    list-style-type: disc;
    padding-left: 1.6em;
}

.bz-content ol {
    list-style-type: decimal;
    padding-left: 1.6em;
}

.bz-content ul ul,
.bz-content ol ul {
    list-style-type: circle;
}

.bz-content ul:not(.bz-gallery-grid, .bz-list, .bz-files) li + li,
.bz-content ol li + li,
.bz-content li > ul,
.bz-content li > ol {
    margin-top: 1em;
}

/* ONE LINK RULE for content: --bz-link, no underline; on hover --bz-link-h and an underline.
   Opt-outs keep their own style: buttons, list rows, the pager, and the meta strip (muted, below).
   The header, drawers and footer are outside .bz-content and have their own rules. */
.bz-content a:not(.bz-btn, .bz-row a, .bz-pager a, .bz-meta-strip a) {
    color: var(--bz-link);
    text-decoration: none;
    transition: color var(--bz-transition);
}
.bz-content a:not(.bz-btn, .bz-row a, .bz-pager a, .bz-meta-strip a):hover {
    color: var(--bz-link-h);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.bz-content blockquote {
    padding: 0.65rem 1.25rem;
    border-left: 3px solid var(--bz-link);
    background: #f3f6fe;
    color: var(--bz-primary);
    font-style: italic;
}

.bz-content blockquote > :first-child { margin-top: 0; }

.bz-content blockquote > * + * { margin-top: var(--bz-gap); }

.bz-content pre {
    padding: 1rem 1.15rem;
    background: #14161a;
    color: #e6e8eb;
    border-radius: var(--bz-radius);
    overflow-x: auto;
    font-family: var(--bz-font-mono);
    font-size: var(--bz-fs-sm);
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
}

.bz-content code {
    font-family: var(--bz-font-mono);
    font-size: 0.88em;
    background: var(--bz-surface);
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    padding: 0.15em 0.4em;
}

.bz-content pre code {
    background: none;
    border: none;
    padding: 0;
    font-size: inherit;
    color: inherit;
}

.bz-content img {
    max-width: 100%;
    height: auto;
    border-radius: var(--bz-radius);
}

.bz-content figcaption {
    font-size: var(--bz-fs-sm);
    color: var(--bz-muted);
    text-align: center;
    margin-top: 0.5em;
}

/* Editor-written modifiers: alignment, text colour, highlight (allowlisted in post-sanitize.php) */

.bz-content .bz-align-left    { text-align: left; }

.bz-content .bz-align-center  { text-align: center; }

.bz-content .bz-align-right   { text-align: right; }

.bz-content .bz-align-justify { text-align: justify; }

.bz-content .bz-text-red    { color: #c0392b; }

.bz-content .bz-text-orange { color: #b45309; }

.bz-content .bz-text-green  { color: #15803d; }

.bz-content .bz-text-blue   { color: var(--bz-link); }

.bz-content .bz-text-purple { color: #7e22ce; }

.bz-content .bz-text-teal   { color: #0f766e; }

.bz-content .bz-text-gray   { color: var(--bz-muted); }

.bz-content .bz-text-white  { color: #ffffff; }

.bz-content .bz-hl-yellow { background: #fef3c7; }

.bz-content .bz-hl-green  { background: #d1fae5; }

.bz-content .bz-hl-blue   { background: #dbeafe; }

.bz-content .bz-hl-pink   { background: #fce7f3; }

.bz-content .bz-hl-orange { background: #ffedd5; }

.bz-content .bz-hl-purple { background: #f3e8ff; }

.bz-content .bz-hl-gray   { background: var(--bz-surface); }

/* Solid background, not a pastel tint -- this is the site's actual
   primary color (--bz-primary, a near-black), not --bz-link. It used to
   read var(--bz-link) here, which meant picking "Primary" in the editor's
   Highlight swatch silently rendered as blue instead of the site's real
   brand color -- an old naming mix-up (see admin-editor.js's HL_COLORS
   comment, fixed alongside this). White text is baked into the rule
   itself rather than left to a separately-applied bz-text-white, since a
   solid dark block needs light text to be readable regardless of what
   text color (if any) the author also picked. */
.bz-content .bz-hl-primary { background: var(--bz-primary); color: var(--bz-bg); }

/* A common "warning/danger" callout tint, added alongside the palette
   trim above -- same pastel family as yellow/green/blue/pink/orange/
   purple, not a saturated red (which would fight with .bz-text-red used
   inside it). */
.bz-content .bz-hl-red    { background: #fee2e2; }

.bz-content [class*="bz-hl-"] { padding: 0.05em 0.15em; border-radius: var(--bz-radius); }

/* Superscript/subscript -- the browser default renders these at full
   line-height, which pushes the line apart wherever one appears. This is
   the standard fix (used by most CSS resets): shrink the glyph and pull
   it off the baseline via position, not vertical-align, so line-height
   stays untouched. */
.bz-content sup, .bz-content sub {
    font-size: 0.75em;
    line-height: 0;
    position: relative;
    vertical-align: baseline;
}
.bz-content sup { top: -0.5em; }
.bz-content sub { bottom: -0.25em; }

/* Other content elements: rule, footer note, featured image, tables, and the dl quick-facts list */

.bz-content hr { border: none; border-top: var(--bz-border); }

.bz-content footer {
    color: var(--bz-muted);
    font-style: italic;
}

.bz-featured-image {
    display: block;
    width: 100%;
    height: auto;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
}

.bz-content table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--bz-fs-sm);
}

.bz-content th, .bz-content td {
    text-align: left;
    padding: 0.55rem 0.75rem;
    border: var(--bz-border);
}

.bz-content th { background: var(--bz-surface); font-weight: 600; }

/* The dl quick-facts list: a bordered, rounded box whose rows alternate --bz-surface and
   white (a row is a dt + dd pair, so the odd dt and the odd dd share the grey). Label and
   value are the same size and colour; the label is semibold, the value regular, so the two read
   apart without a size change (and share a baseline side by side). The rows' fill reaches
   the box edge, hence the side padding on the cells and overflow:hidden for the corners.
   Under 600px the value drops under its label (one column, same styles). */
.bz-content dl {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    overflow: hidden;
    line-height: 1.7;
}

.bz-content dl dt,
.bz-content dl dd {
    padding-block: 0.75rem;
}

.bz-content dl dt {
    padding-left: 1rem;
    padding-right: clamp(1rem, 5vw, 3rem);
    font-weight: 600;
}

.bz-content dl dd {
    padding-right: 1rem;
    overflow-wrap: break-word;
}

.bz-content dl dt:nth-of-type(odd),
.bz-content dl dd:nth-of-type(odd) {
    background: var(--bz-surface);
}

@media ( max-width: 600px ) {
    .bz-content dl { grid-template-columns: minmax(0, 1fr); }
    .bz-content dl dt { padding-block: 0.75rem 0; padding-right: 1rem; }
    .bz-content dl dd { padding: 0 1rem 0.75rem; }
}

/* Editor-inserted embeds. Responsive without a wrapper: aspect-ratio + width:100%. */

.bz-content audio {
    display: block;
    width: 100%;
    margin-top: var(--bz-gap);
}

.bz-content iframe.bz-embed-yt {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    height: auto;
    margin-top: var(--bz-gap);
    border: 0;
    border-radius: var(--bz-radius);
}

/* FAQ / accordion: native <details>, styled by element so any <details> in an
   article looks right whether or not the editor wrote a class. ONE look everywhere:
   service pages (inside a <section>), tool pages and posts/products (children of
   .bz-content). Items get a uniform 16px rhythm, so the flow gap is reset between two
   of them.

   Two things used to make a post's accordion roomier than a service page's:
   1. .bz-content sets line-height: var(--bz-lh-prose) (2). The row is a flex line
      sized by its tallest child, and the +/- sign is 1.3em, so at line-height 2 the sign
      alone was ~47px tall. The row now sets its own line-height, so the surrounding
      prose setting no longer reaches it.
   2. The flow rule .bz-content > * + * puts 1.75em above the first item, while a service
      page puts 1rem under its heading. The heading-to-list gap is now 1rem everywhere.
   The answer keeps the prose line-height on purpose: it is reading text.

   The sign is generated content, which some screen readers speak ("plus"). The second
   content declaration gives it an empty alternative text; a browser that does not know that
   syntax drops it and keeps the first, so the sign never disappears. */

.bz-main > article details { border-bottom: var(--bz-border); padding: 16px 0; }
.bz-main > article details + details { margin-top: 0; }
/* Top hairline on the first item of every run of items, not just the first <details> of the parent. */
.bz-main > article details:not(details + details) { border-top: var(--bz-border); }
.bz-main > article :is(h2, h3, h4) + details { margin-top: 1rem; }
.bz-main > article summary {
    cursor: pointer; font-weight: 600; list-style: none; line-height: 1.4;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.bz-main > article summary::-webkit-details-marker { display: none; }
.bz-main > article summary::after {
    content: '+'; content: '+' / ''; flex-shrink: 0; font-weight: 400; font-size: 1.3em; color: var(--bz-muted);
}
.bz-main > article details[open] summary::after { content: '\2212'; content: '\2212' / ''; }
.bz-main > article details p { margin-top: 10px; line-height: var(--bz-lh-prose); }

/* End of a post (partials/post-nav.php): previous / next as a pair of rows, then
   "More in {category}" with a link to the whole archive and the related entries as
   more rows. All of it is .bz-list / .bz-row, so a related entry looks exactly like
   it does on the archive page. */

.bz-post-nav {
    display: grid;
    gap: clamp(40px, 6vw, 56px);
}

.bz-post-nav,
.bz-main > .bz-related { margin-top: clamp(40px, 6vw, 56px); }

.bz-related { display: grid; gap: 24px; }

.bz-related > header { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }

.bz-related h2 { font-size: var(--bz-fs-lg); line-height: 1.3; }

.bz-related > header a { flex-shrink: 0; font-size: var(--bz-fs-sm); color: var(--bz-muted); text-decoration: none; }

.bz-related > header a:hover { color: var(--bz-primary); }

/* Footer and social row */

.bz-footer {
    padding-inline: var(--bz-pad);
    padding-block: 18px;
    border-top: var(--bz-border);
    text-align: center;
    font-size: var(--bz-fs-sm);
    color: var(--bz-muted);
}

.bz-footer a { color: var(--bz-primary); text-decoration: none; }

.bz-footer a:hover { text-decoration: underline; }

.bz-social-row {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 20px calc(16px + env(safe-area-inset-bottom));
}

.bz-social-row a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    color: #6b7280;
    transition: background var(--bz-transition);
}

.bz-social-row a:hover { background: var(--bz-surface); }

.bz-social-row a:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: 1px; }

.bz-social-row .bz-icon { width: 14px; height: 14px; transition: opacity var(--bz-transition); }

.bz-social-row a:hover .bz-icon { opacity: 0.7; }

/* Reduced motion */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Pagination (partials/pagination.php), styled by the markup it already carries:
   links are <a>, the current page is [aria-current], the ellipsis is [aria-hidden],
   the previous link is [rel=prev]. */

.bz-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 4px;
    margin-block-start: 28px;
}
.bz-pager > :is(a, [aria-current]) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    min-height: 36px;
    padding-inline: 8px;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    color: var(--bz-primary);
    text-decoration: none;
    font-size: var(--bz-fs-sm);
    font-variant-numeric: tabular-nums;
}
.bz-pager > a:hover { background: var(--bz-surface); border-color: #bbb; }
.bz-pager .bz-icon { width: 16px; height: 16px; }

.bz-pager [rel="prev"] .bz-icon { rotate: 180deg; }
.bz-pager > [aria-current] {
    background: var(--bz-surface);
    border-color: #bbb;
    cursor: default;
}
.bz-pager > [aria-hidden] {
    padding-inline: 4px;
    opacity: 0.6;
}

/* Empty state and focus ring (:focus-visible, so keyboard users get it and mouse clicks do not) */

.bz-empty {
    padding: 24px;
    text-align: center;
    opacity: 0.7;
}

:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* Listings: page head, search bar, card grid (search results; category pages are .bz-list rows, below) */

/* No margin-bottom here on purpose - see the single-direction margin note at
   .bz-main > * + * / .bz-main > article > * + *. Spacing to whatever follows
   (grid, form, article content) is that block's own margin-top, not this
   header pushing down from above it. */

/* Icon page-heads - an icon tile beside the title (tool pages, front/tools/
   *.php) and a directory section's own single-post page (front/directory-
   single.php - Vault today, any future section named in
   BZ_DIRECTORY_CATEGORY_SLUGS next). Same shape both times: icon left,
   title+tagline as one text block on the right, meta pills spanning the
   full width on their own line below - so one modifier now covers both
   instead of a grid version (.is-tool) and a flex version (.bz-vault-head)
   doing the same job two different ways.

   gap does the spacing here, not margin - .bz-page-head's own top-margin
   rhythm is turned off below so it doesn't stack on top of gap. */
.bz-page-head.is-icon {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 16px;
}

.bz-page-head.is-icon > * + * { margin-top: 0; }

/* The title+tagline block. It wraps as one unit on narrow screens (the icon
   stays put, this drops below it) rather than the tagline running under
   the title at icon width. Its own children get a small, tight gap of
   their own - see the note below on why they can't rely on the h1 rule's
   margin: 0 the way a direct-child page-head h1 does. */
.bz-head-text { flex: 1 1 220px; min-width: 0; }
.bz-head-text > * { margin: 0; }
.bz-head-text > * + * { margin-top: 0.35rem; }

/* flex-basis: 100% forces the meta strip onto its own wrapped line under the
   icon+title row instead of trailing beside them. */
.bz-page-head.is-icon > .bz-meta-strip { flex-basis: 100%; }

/* Icon tile - one square component shared by the tool hub list + tool page header
   (.is-glyph: a fixed brand-color tile carrying one white line-icon) and a directory
   entry's rows + page header (an uploaded logo or cover; an entry with none gets a
   .is-letter tile, its title's first letter - see bz_directory_icon_tile()).

   A tile is always a square: width AND height are fixed, and an image is cropped to fill
   it (object-fit: cover), so whatever ratio an uploaded image has, every row in a list is
   the same height. (Before v137 the height was auto, and a tall image made its row tall.) */
.bz-icon-tile {
    flex-shrink: 0;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--bz-radius);
    overflow: hidden;
}
.bz-icon-tile img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.bz-icon-tile.is-glyph { background: var(--bz-primary); }
.bz-icon-tile.is-glyph .bz-icon { background-color: var(--bz-bg); }

/* Letter tile: a directory entry with no logo. Same primary fill as .is-glyph, one
   letter in the body colour. One colour for every entry on purpose - the letter
   tells rows apart, a hue per title would only add noise. */
.bz-icon-tile.is-letter { background: var(--bz-primary); color: var(--bz-bg); font-size: 1.125rem; font-weight: 600; line-height: 1; }
.bz-icon-tile.is-lg.is-letter { font-size: 1.5rem; }

/* One shared "large" size for page-head use (tool pages + a directory entry's page):
   one modifier, one number. */
.bz-icon-tile.is-lg { width: 56px; height: 56px; }
.bz-icon-tile.is-lg.is-glyph .bz-icon { width: 24px; height: 24px; }

/* List rows: the one design for every vertical list of links - the tool hub and
   "Explore More Tools", every category page (sub-categories or posts), related entries, and previous /
   next. <li class="bz-row"> holds an optional .bz-icon-tile, then a plain <div>: the
   title link and an optional <small> line. The chevron is the row's own ::after. The
   title link is stretched over the whole row, so the row is one big target. A catalog row
   with a link (.has-btn) ends in an icon-only .bz-btn.is-icon instead of the chevron, lifted
   above the stretched link as a second, independent link: a 40px square, so a narrow
   phone never squeezes the title into a sliver.
   .is-pair on the list sets previous / next side by side; they stack when there is
   no room, without a media query. */

/* minmax(0, 1fr), not the implicit auto track: an auto track grows to its widest row's
   unbreakable text (the nowrap <small> line), which pushed the whole list past the 650px
   column and cut the lines off mid-word instead of ending them with an ellipsis. */
.bz-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }

.bz-list.is-pair { grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--bz-cell, 15rem)), 1fr)); }

/* Wider cells: two to a row on a desktop instead of four (the homepage's service rows). */
.bz-list.is-lg { --bz-cell: 24rem; }

.bz-row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 20px;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    transition: border-color var(--bz-transition), transform var(--bz-transition);
}

.bz-row:hover,
.bz-product.is-link:hover { border-color: var(--bz-primary); transform: translateY(-2px); }

.bz-row::after { content: ""; align-self: center; width: 20px; height: 20px; color: var(--bz-muted); transition: translate var(--bz-transition); }

.bz-row:hover::after { translate: 3px; }

/* A row with an outbound button (.has-btn, a catalog row with a link) hands its right edge to
   the button; every other row, catalog or not, ends in the chevron. */
.bz-row.has-btn::after { display: none; }

.bz-row > div { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }

.bz-row a:not(.bz-btn) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    font-weight: 600;
    line-height: 1.6;
    color: inherit;
    text-decoration: none;
}

.bz-row a:not(.bz-btn)::after,
.bz-product.is-link h3 a::after { content: ""; position: absolute; inset: 0; }

/* The stretched link would ring only its own text; the row takes the ring instead. */
.bz-row a:not(.bz-btn):focus-visible { outline: none; }

.bz-row:has(a:not(.bz-btn):focus-visible) { outline: 2px solid currentColor; outline-offset: 2px; }

.bz-row small { font-size: var(--bz-fs-sm); line-height: 1.6; color: var(--bz-muted); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.bz-row .bz-btn { position: relative; z-index: 1; flex-shrink: 0; }

/* The section's name above a search result's title (partials/post-row.php, $bz_row_eyebrow): a
   label, not a second line of text - small, muted, one line, so it reads as "where this is from"
   and the title stays the first thing in the row. */
.bz-row-eyebrow { font-size: var(--bz-fs-xs); font-weight: 600; line-height: 1.6; letter-spacing: 0.04em; text-transform: uppercase; color: var(--bz-muted); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.bz-row.is-prev { flex-direction: row-reverse; }

.bz-row.is-prev::after { rotate: 180deg; }

.bz-row.is-prev:hover::after { translate: -3px; }

.bz-row.is-next > div { align-items: flex-end; text-align: right; }

/* Affiliate-disclosure note (partials/disclosure-note.php): small print in a
   dashed, square-cornered box with an info icon - deliberately unlike the
   pills (solid, fully rounded, filled) so it never reads as one more piece
   of metadata. Smallest type size on the scale. Selector is
   .bz-page-head p.bz-affiliate-note (0,2,1) so that it out-ranks, .bz-page-head p's body-size rule. */
.bz-page-head p.bz-affiliate-note {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 14px;
    border: 1px dashed var(--bz-line);
    border-radius: var(--bz-radius);
    font-size: var(--bz-fs-xs);
    line-height: 1.6;
    color: var(--bz-muted);
}
/* The visitor's keyword under the search page's title (front/search.php): their own text, of any
   length, so it breaks anywhere rather than push the column wider. Same (0,2,1) as above, to
   out-rank .bz-page-head p. */
.bz-page-head p.bz-search-query {
    font-size: var(--bz-fs-sm);
    color: var(--bz-muted);
    overflow-wrap: anywhere;
}
.bz-affiliate-note .bz-icon { width: 14px; height: 14px; margin-top: 2px; }
.bz-page-head.is-icon > .bz-affiliate-note { flex-basis: 100%; }
.bz-icon-info { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 16v-5'/%3E%3Cpath d='M12 8h.01'/%3E%3C/svg%3E"); }

/* Icons for the meta strip (same mask technique as above). */
.bz-icon-calendar { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E"); }
.bz-icon-edit { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z'/%3E%3C/svg%3E"); }
.bz-icon-clock { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E"); }
.bz-icon-tag { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.6 13.4l-7.2 7.2a2 2 0 0 1-2.8 0L2 12V2h10l8.6 8.6a2 2 0 0 1 0 2.8z'/%3E%3Cpath d='M7 7h.01'/%3E%3C/svg%3E"); }
.bz-icon-lock { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='5' y='11' width='14' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E"); }
.bz-icon-user-x { --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M18 8l5 5M23 8l-5 5'/%3E%3C/svg%3E"); }

/* The post's CTA button: the LAST thing in the article (front/single.php), a <p> holding one
   ordinary .bz-btn - the same button, and the same height, as one added in the editor - in two
   states. At rest - a post without "Sticky button" ticked, or a sticky one that has scrolled
   to its place at the end - it is the full width of the column, flat. While floating
   (.is-sticky, not yet .is-docked) it is a compact pill at the bottom of the screen: position:
   sticky keeps it there while the article is read and lets it rest at the article's end.
   script.js adds .is-docked when it arrives (it watches a zero-height marker it places right
   after the paragraph, .bz-cta-sentinel), and the pill widens into the column. Same height in
   both states, so nothing around it moves; only the width and the shadow change. Without
   script.js a sticky button just stays a pill. z-index sits under the header (200) and the
   drawer (500). The bottom offset clears the iPhone home bar; scroll-padding keeps a focused
   link from hiding behind it. Its top margin is the article's own flow rule
   (.bz-main > article > * + *), like every block. The disclosure is NOT here: it is the note
   under the head. */
.bz-cta-bar .bz-btn { display: flex; width: 100%; padding-block: var(--bz-btn-py-l); }
.bz-cta-bar.is-sticky {
    position: sticky;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    z-index: 100;
}
/* max-width, not width, is what changes: it animates between two lengths in every browser. */
.bz-cta-bar.is-sticky .bz-btn {
    max-width: 22rem;
    margin-inline: auto;
    box-shadow: 0 4px 16px rgb(0 0 0 / 0.18);
    transition: max-width 0.25s ease, box-shadow 0.25s ease, transform var(--bz-transition), background var(--bz-transition), color var(--bz-transition);
}
.bz-cta-bar.is-sticky.is-docked .bz-btn { max-width: 100%; box-shadow: none; }
/* No margin: the article's flow rule would otherwise push this marker 28px down and leave a gap. */
.bz-main > article > .bz-cta-sentinel { height: 0; margin: 0; }
html:has(.bz-cta-bar.is-sticky) { scroll-padding-bottom: 6rem; }
@media (prefers-reduced-motion: reduce) {
    .bz-cta-bar.is-sticky .bz-btn { transition: none; }
}

/* Buttons (shared: editor CTA, tool actions, signup form). .is-block is the full-width
   action button: a <button> does not stretch on its own, so it carries the width.

   Size: three heights, because a button's height has to fit its width. A lone button (the base
   rule: it stands in for a link inside a list or a long article, so it is compact, left-aligned
   and does not shout) is the smallest; one of a pair is taller; a full-width button - .is-block,
   the post's CTA, a product's buy button - is the tallest, because a wide button in a thin
   bar looks like a stripe. The padding is a clamp() per size (--bz-btn-py-*), and min-width keeps
   a short label ("Visit site") from reading as a cramped chip - min-width, not more padding, so
   every button looks like one family. Weight 500: the white-on-dark label is already
   high-contrast, and a heavier one makes Bangla (which systems draw bold from 600) shout.
   Feedback: a 1px lift and a soft shadow on hover - the same small movement a list row makes -
   pressed back flat on :active; the global focus ring is currentColor, which on this white-on-dark
   button is white, so the ring is drawn in the primary colour instead. */

.bz-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    min-width: 10rem;
    padding: var(--bz-btn-py-s) clamp(18px, 1.5em, 28px);
    background: var(--bz-primary); color: var(--bz-bg);
    font-size: var(--bz-fs-md); font-weight: 500; font-family: inherit; line-height: 1.3;
    letter-spacing: 0.01em;
    text-align: center; text-decoration: none;
    border: none; border-radius: var(--bz-radius); cursor: pointer;
    transition: background var(--bz-transition), color var(--bz-transition), box-shadow var(--bz-transition), transform var(--bz-transition);
}

.bz-btn:hover    { background: var(--bz-primary-h); transform: translateY(-1px); box-shadow: 0 4px 12px rgb(0 0 0 / 0.16); }

.bz-btn:active   { transform: none; box-shadow: none; }

@media (prefers-reduced-motion: reduce) {
    .bz-btn:hover { transform: none; }
}

/* Site-wide "this opens in a new tab" cue: any .bz-btn whose link has
   target="_blank" gets an outbound-arrow icon, in every template (the CTA
   partial, tool pages, in-content buttons) - nothing per-template to
   remember. A mask on currentColor, same technique as .bz-icon, so it
   follows the button's own text colour. */
.bz-btn[target="_blank"]::after,
.bz-content a[target="_blank"]:not(.bz-btn, .bz-row a, .bz-pager a, .bz-meta-strip a)::after {
    content: "";
    flex-shrink: 0;
    background-color: currentColor;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 4h6v6'/%3E%3Cpath d='M20 4l-9 9'/%3E%3Cpath d='M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5'/%3E%3C/svg%3E") center / contain no-repeat;
}

.bz-btn[target="_blank"]::after { width: 14px; height: 14px; }

/* The same cue on a plain content link (not a button, row, pager or meta link): a small
   outbound arrow after the text, in the link's own colour. */
.bz-content a[target="_blank"]:not(.bz-btn, .bz-row a, .bz-pager a, .bz-meta-strip a)::after {
    display: inline-block;
    width: 0.7em;
    height: 0.7em;
    margin-inline-start: 0.25em;
}

.bz-btn:disabled { cursor: not-allowed; opacity: .6; transform: none; box-shadow: none; }

/* The global ring is currentColor, which on this white-on-dark button is white: invisible. */
.bz-btn:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: 2px; }

.bz-btn.is-block { display: flex; width: 100%; padding-block: var(--bz-btn-py-l); }

/* Two buttons in one paragraph sit side by side as equal halves; the 650px article column has
   room for no more, and the editor puts a third button in a paragraph of its own. Under 480px
   they stack, each the full width. A single button keeps its own width.
   Each button is placed in row 1 by hand, and every later row is 0 high: a contenteditable puts a
   &nbsp; between two inline elements, and a grid would otherwise give that character a row of its
   own - a blank line between the buttons once they stack. */
.bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto;
    grid-auto-rows: 0;
    column-gap: 12px;
}
.bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) > .bz-btn { grid-row: 1; padding-block: var(--bz-btn-py-m); }
.bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) > .bz-btn:first-child { grid-column: 1; }
.bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) > .bz-btn:last-child { grid-column: 2; }
@media ( max-width: 480px ) {
    /* Stacked, each is a full-width button, so it takes the full-width height. */
    .bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto; }
    .bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) > .bz-btn { padding-block: var(--bz-btn-py-l); }
    .bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) > .bz-btn:first-child { grid-column: 1; margin-bottom: 12px; }
    .bz-content p:has(> .bz-btn:first-child:nth-last-child(2)) > .bz-btn:last-child { grid-column: 1; grid-row: 2; }
}

/* Outline variant: body-color background, primary text, and a primary border
   drawn as an inset shadow so it stays exactly as tall as the solid button
   beside it. On hover the background AND the border go to --bz-primary-h and
   the text flips to the body color, so an outline button lands on exactly the
   solid button's hover state. Its transitions come from .bz-btn. Used by the
   subscribe form's secondary action and the header's Community link. */
.bz-btn.is-outline {
    background: var(--bz-bg);
    color: var(--bz-primary);
    box-shadow: inset 0 0 0 1px var(--bz-primary);
}

.bz-btn.is-outline:hover { background: var(--bz-primary-h); color: var(--bz-bg); box-shadow: inset 0 0 0 1px var(--bz-primary-h); }

/* Icon-only variant (a directory row's outbound button): a 40px square with no label -
   the outbound arrow the [target="_blank"] rule above draws, enlarged a little, is the
   whole button. 40px keeps a comfortable touch target. The accessible name is
   an aria-label set in partials/post-cta.php. */
.bz-btn.is-icon { width: 40px; height: 40px; min-width: 0; padding: 0; }
.bz-btn.is-icon[target="_blank"]::after { width: 18px; height: 18px; }

/* Messages: subscribe form/pages and the tool pages' status line share this one
   component - is-error / is-success / is-warn give it its colour. No width of its own:
   a message is as wide as the column it sits in. */

.bz-msg {
    display: block;
    padding: 12px 14px;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    background: var(--bz-surface);
    font-size: var(--bz-fs-md);
    text-align: center;
}

.bz-msg.is-error   { border-color: var(--bz-danger); color: #991b1b; background: #fef2f2; }

.bz-msg.is-success { border-color: #16a34a; color: #14532d; background: #f0fdf4; }

.bz-msg.is-warn     { color: #b30000; background: #fff4f4; border-color: #ffcccc; }

/* Signup form (partials/signup-form.php). A flex column, so every control fills the form
   without a width of its own and `gap` is the only spacing. The buttons are the site's
   .bz-btn.is-block, with .is-outline for the secondary action. */

.bz-signup {
    display: flex;
    flex-direction: column;
    gap: 16px;
    line-height: 1.6;
}

/* The gap does the spacing here, not .is-block's flow margin - nor the article rule that
   puts a top margin on every form child (`.bz-main > article form > * + *`), which on
   this page doubled the gap. Same specificity as that rule and later in the file. */
.bz-signup .bz-btn,
.bz-main > article form.bz-signup > * + * { margin-top: 0; }

.bz-signup-or {
    display: flex;
    align-items: center;
    gap: 12px;
}

.bz-signup-or::before,
.bz-signup-or::after { content: ""; flex: 1; border-top: 1px solid var(--bz-line); }

/* The email field is .bz-field.is-lg - see the shared field styles below - so its height
   matches a large button's (--bz-btn-h-l) without a rule of its own. */

/* The submit button and the note under it are one group: tight to each other, the form's
   gap away from everything else. */
.bz-signup-submit {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.bz-signup-note {
    display: block;
    color: var(--bz-muted);
    font-size: var(--bz-fs-sm);
    line-height: 1.5;
    text-align: center;
}

/* The small outlined status label under the confirm card's title ("One last step"): muted,
   with a dot. Beats the article's flow margin (.bz-main > article > * + *) on specificity,
   so it sits close under the heading. */
.bz-community > .bz-status {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 0.75rem;
    padding: 3px 12px;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
    font-size: var(--bz-fs-sm);
    font-weight: 600;
    color: var(--bz-muted);
}

.bz-community > .bz-status::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.bz-google-mark {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23EA4335' d='M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z'/%3E%3Cpath fill='%234285F4' d='M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z'/%3E%3Cpath fill='%23FBBC05' d='M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z'/%3E%3Cpath fill='%2334A853' d='M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z'/%3E%3C/svg%3E");
}

/* Confirmation card on /community/ (front/pages/page-community.php). Lives here, not in an inline <style>: the CSP is style-src 'self'. */

.bz-community form { margin: 1.5rem 0; }

/* The three rows on /community/ (what the emails are, what members get, what unsubscribing
   means): hairline-separated, a bold term over a muted line. Styled by element, scoped to the
   page - the .bz-content dl above is the editor's quick-facts box and is not used here. */
.bz-community dl { border-top: 1px solid var(--bz-line); }

.bz-community dl > div { padding: 16px 0; border-bottom: 1px solid var(--bz-line); }

.bz-community dt { font-weight: 600; }

.bz-community dd { color: var(--bz-muted); font-size: var(--bz-fs-md); line-height: 1.6; }

/* The "if you unsubscribe" row for a signed-in subscriber: tinted so the warning stands out, but the
   same term and line type as every other row - the box does the emphasising, not the type. */
.bz-community dl > .bz-warn-row { margin-top: 1rem; padding: 16px; border: 1px solid #f0d78a; border-radius: var(--bz-radius); background: #fff8e1; }

.bz-community .bz-warn-row dd { color: #5c4a00; }

/* The signed-in box on /community/, in place of the join form: who is signed in, what that gets them,
   and Sign out. A quiet bordered block - it is a status, not a call to action. */
.bz-member { margin: 1.5rem 0; padding: 20px; border: var(--bz-border); border-radius: var(--bz-radius); }

.bz-member > * { margin: 0; }

.bz-member > * + * { margin-top: 0.5rem; }

.bz-member-label { font-size: var(--bz-fs-sm); font-weight: 600; color: var(--bz-muted); }

.bz-member-email { font-weight: 600; overflow-wrap: anywhere; }

.bz-member-status { color: var(--bz-muted); font-size: var(--bz-fs-md); line-height: 1.6; }

.bz-community .bz-member-out { margin: 1rem 0 0; }

/* TOOL PAGES (front/tools/*.php). Same tokens as everything above.
   Buttons and .bz-text-* are shared with posts (editor CTA button, small print). */

/* Button rows, text buttons, stepper buttons */

.bz-btn-row { display: flex; gap: 1rem; margin-top: 20px; flex-wrap: wrap; }

.bz-btn-row > .bz-btn { flex: 1; padding-block: var(--bz-btn-py-m); }

@media ( max-width: 600px ) { .bz-btn-row { flex-direction: column; } }

.bz-btn-link {
    display: inline-block; width: fit-content;
    background: none; border: none; padding: 0; margin: 0;
    font-family: inherit; line-height: inherit;
    font-size: var(--bz-fs-md); font-weight: 500; text-align: left;
    color: var(--bz-link); cursor: pointer; text-decoration: none;
}

.bz-btn-link:hover,
.bz-btn-link:focus-visible { text-decoration: underline; }

.bz-qty-btn {
    background: none; border: none; cursor: pointer;
    padding: 0; line-height: 1; width: 34px; font-size: 20px; flex-shrink: 0;
    color: var(--bz-primary);
    transition: background var(--bz-transition);
}

.bz-qty-btn:hover    { background: var(--bz-surface); }

.bz-qty-btn:disabled { opacity: .35; cursor: not-allowed; }

/* Site search box - the one search component. Rendered by partials/search-form.php
   in the menu drawer, the 404 page, a category page and the results page, so all four
   look alike. Field and button live inside ONE bordered container: the field is
   borderless, the container takes the border and the focus ring, and the icon button
   sits inside it. That is what keeps the two from drifting apart in height or
   alignment, which separate boxes (v146 and before) did. Icon only - the button's
   name is its aria-label. .is-sm is the 44px size the drawer uses. min-width: 0 on the
   field lets it shrink inside the drawer's narrow column. */
.bz-search {
    display: flex; align-items: center; gap: 4px;
    width: 100%; height: 48px; padding: 0 6px 0 16px;
    background: var(--bz-bg);
    border: var(--bz-border); border-radius: var(--bz-radius);
    transition: border-color var(--bz-transition), box-shadow var(--bz-transition);
}

.bz-search:hover { border-color: var(--bz-primary); }

.bz-search:focus-within {
    border-color: var(--bz-primary);
    box-shadow: 0 0 0 3px rgba(33, 33, 33, 0.12);
}

.bz-search-input {
    flex: 1 1 auto; min-width: 0; height: 100%; padding: 0;
    border: 0; background: transparent; outline: none;
    color: var(--bz-primary); font: inherit; font-size: var(--bz-fs-md);
    -webkit-appearance: none; appearance: none;
}

.bz-search-input::placeholder { color: var(--bz-muted); opacity: 0.8; }

/* The browser's own clear (x) on type="search", redrawn to match the icon set. */
.bz-search-input::-webkit-search-cancel-button {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px; margin: 0 4px 0 0; cursor: pointer;
    background-color: var(--bz-muted);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3C/svg%3E") center / contain no-repeat;
}

.bz-search-btn {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; padding: 0;
    border: 0; border-radius: var(--bz-radius);
    background: var(--bz-primary); color: var(--bz-bg); cursor: pointer;
    transition: background var(--bz-transition);
}

.bz-search-btn:hover { background: var(--bz-primary-h); }

.bz-search-btn:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: 2px; }

.bz-search-btn .bz-icon { width: 18px; height: 18px; }

.bz-search.is-sm { height: 44px; padding-left: 14px; }

.bz-search.is-sm .bz-search-btn { width: 32px; height: 32px; }

/* Form fields and controls */

/* Shared control for every single-line field on the site: text/email/search inputs
   and selects, one default height/border/radius. .is-lg matches the buttons'
   height (--bz-btn-h-l), for a field that sits beside a full-width button (the subscribe form). A
   <select> gets its chevron and cursor from the element selector, not an extra class. */
.bz-field {
    display: block; width: 100%; height: 40px; padding: 0 12px;
    border: var(--bz-border); border-radius: var(--bz-radius);
    background: var(--bz-bg); color: var(--bz-primary);
    font: inherit; font-size: var(--bz-fs-md);
    transition: border-color var(--bz-transition);
}

.bz-field:hover, .bz-field:focus { border-color: var(--bz-primary); outline: none; }

.bz-field::placeholder { color: var(--bz-muted); opacity: 0.8; }

select.bz-field {
    padding-right: 32px; cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23555' stroke-width='1.5' fill='none'/%3E%3C/svg%3E") no-repeat right 10px center;
    -webkit-appearance: none; appearance: none;
}

.bz-field.is-lg { height: var(--bz-btn-h-l); padding-inline: 16px; }

.bz-slider { flex: 1; cursor: pointer; accent-color: var(--bz-primary); }

.bz-opt-group {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px 16px;
    border: none; padding: 0;
}

.bz-opt-group > legend { font-weight: 600; margin-bottom: 4px; }

/* Four short toggles (a-z A-Z 0-9 !@#$) always share one row; mono, so each
   label reads as a sample of the characters it switches on. */
.bz-opt-group.is-compact { grid-template-columns: repeat(4, 1fr); gap: 12px; font-family: var(--bz-font-mono); }

/* Segmented choice: the one control for "pick one of 2-3 short options"
   (radios underneath, so keyboard and form behaviour are native). */
.bz-seg {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 3px;
    padding: 3px; background: var(--bz-surface);
    border: var(--bz-border); border-radius: var(--bz-radius);
}

.bz-seg label {
    position: relative; display: grid; place-items: center;
    min-height: 32px; padding: 0 6px; border-radius: var(--bz-radius);
    font-size: var(--bz-fs-md); line-height: 1.5;
    color: var(--bz-muted); text-align: center; cursor: pointer;
    transition: background var(--bz-transition), color var(--bz-transition);
}

.bz-seg input { position: absolute; opacity: 0; }

.bz-seg label:has(input:checked) { background: var(--bz-bg); color: var(--bz-primary); font-weight: 600; box-shadow: 0 0 0 1px var(--bz-line); }

.bz-seg label:has(input:focus-visible) { outline: 2px solid var(--bz-primary); }

.bz-chk-lbl {
    position: relative; display: block;
    padding-left: 30px; line-height: 1.5;
    cursor: pointer; user-select: none;
}

.bz-chk-lbl input { position: absolute; opacity: 0; }

.bz-chk-lbl .bz-text-sm { display: block; }

.bz-chk {
    position: absolute; top: 3px; left: 0;
    width: 19px; height: 19px;
    border: var(--bz-border); border-radius: var(--bz-radius); background: var(--bz-bg);
    transition: background var(--bz-transition), border-color var(--bz-transition);
}

.bz-chk::after {
    content: ""; position: absolute; display: none;
    left: 6px; top: 2px; width: 5px; height: 9px;
    border: solid var(--bz-bg); border-width: 0 2px 2px 0; transform: rotate(45deg);
}

.bz-chk-lbl input:checked + .bz-chk { background: var(--bz-primary); border-color: var(--bz-primary); }

.bz-chk-lbl input:checked + .bz-chk::after { display: block; }

.bz-ctrl-set { border: none; padding: 0; }

.bz-ctrl-row {
    display: grid; grid-template-columns: 110px 1fr;
    align-items: center; gap: 16px;
}

/* Rows within one fieldset are a tighter unit than the page's block flow, so
   they get their own (smaller) top-margin scale - still top-only, still an
   owl selector, just one level of nesting deeper. No margin-bottom, so the
   last row never leaks space into whatever follows the fieldset. */
.bz-ctrl-row + :is(.bz-ctrl-row, .bz-opt-group) { margin-top: 16px; }

.bz-ctrl-lbl { font-weight: 600; }

:where(.bz-ctrl-row) > div { display: flex; align-items: center; gap: 12px; }


.bz-ctrl-stack { flex-direction: column; align-items: stretch; gap: 6px; }

.bz-ctrl-row:has( .bz-ctrl-stack ) { align-items: start; }

@media ( max-width: 600px ) {
    .bz-ctrl-row { grid-template-columns: 1fr; }
}

.bz-slider-group {
    display: flex; align-items: stretch; gap: 0; height: 40px;
    border: var(--bz-border); border-radius: var(--bz-radius); overflow: hidden;
    background: var(--bz-bg); transition: border-color var(--bz-transition);
}

.bz-slider-group:hover { border-color: var(--bz-primary); }

.bz-slider-group .bz-qty-btn:first-child { border-right: 1px solid var(--bz-line); }

.bz-slider-group .bz-qty-btn:last-child  { border-left:  1px solid var(--bz-line); }

.bz-slider-group .bz-qty-btn:first-child:hover:not( :disabled ) { border-right-color: var(--bz-primary); }

.bz-slider-group .bz-qty-btn:last-child:hover:not( :disabled )  { border-left-color:  var(--bz-primary); }

.bz-slider-group:has( .bz-slider:disabled ) { background: var(--bz-surface); opacity: .55; }

.bz-slider-group:has( .bz-slider:disabled ) .bz-slider { cursor: not-allowed; }

.bz-slider-group:has( .bz-slider:disabled ) .bz-qty-btn:disabled { opacity: 1; }

.bz-slider-wrap { flex: 1; min-width: 0; display: flex; align-items: stretch; }

.bz-slider-wrap .bz-slider { flex: 1; min-width: 0; margin-inline: 14px; }

.bz-slider-val {
    display: grid; place-items: center; min-width: 3.6em; padding-inline: 6px;
    border-left: var(--bz-border);
    font-weight: 700; font-size: var(--bz-fs-sm); font-variant-numeric: tabular-nums;
}

/* Touch screens: every control reaches a 44px target. */
@media ( pointer: coarse ) {
    .bz-btn, .bz-field, .bz-seg label { min-height: 44px; }
    .bz-slider-group { height: 44px; }
    .bz-qty-btn { width: 44px; }
    .bz-chk-lbl { padding-block: 8px; }
    .bz-chk { top: 11px; }
}

.bz-drop-zone {
    min-height: 220px; padding: 36px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    border: 2px dashed var(--bz-line); border-radius: var(--bz-radius);
    background: var(--bz-bg); text-align: center; cursor: pointer;
    transition: border-color var(--bz-transition), background var(--bz-transition);
}

.bz-drop-zone:hover,
.bz-drop-zone.dragging { border-color: var(--bz-primary); background: var(--bz-surface); }

.bz-drop-zone .bz-icon { width: 32px; height: 32px; margin-bottom: 8px; background-color: var(--bz-muted); }

/* Drop zone shrinks to a slim "add more" bar once files exist. */
.bz-drop-zone.is-compact { min-height: 0; padding: 14px; flex-direction: row; gap: 10px; font-size: var(--bz-fs-md); }

.bz-drop-zone.is-compact .bz-icon { margin: 0; width: 20px; height: 20px; }

.bz-drop-zone.is-compact .bz-text-sm { display: none; }

/* File list: one row shape for every file tool (image, and PDF). */
.bz-files { border: var(--bz-border); border-radius: var(--bz-radius); }

.bz-files > li { padding: 12px 14px; }

.bz-files > li + li { border-top: var(--bz-border); }

.bz-media-cell { display: flex; align-items: center; gap: 12px; }

.bz-media-cell > :last-child { flex: 1; min-width: 0; }

.bz-file-info { word-break: break-word; }

.bz-file-name + .bz-text-xs { margin-top: 4px; }

.bz-text-xs .bz-btn-link { font-size: inherit; }

.bz-thumb {
    width: 64px; height: 64px; flex-shrink: 0;
    object-fit: cover; border-radius: var(--bz-radius); border: var(--bz-border);
    background: var(--bz-surface);
}

/* Result box: the output is the product, so it is a bordered strip with its
   own Copy button. Used by the password generator. Its one-line height
   matches the full-width .bz-btn.is-block action under the controls. */
.bz-result { display: flex; align-items: stretch; min-height: var(--bz-btn-h-l); border: 1px solid var(--bz-primary); border-radius: var(--bz-radius); }

.bz-result output {
    flex: 1; min-width: 0; display: flex; align-items: center; padding: 8px 16px;
    font-family: var(--bz-font-mono); font-size: var(--bz-fs-lg); line-height: 1.5; overflow-wrap: anywhere;
}

.bz-result .bz-btn { align-self: stretch; border-radius: 0 var(--bz-radius-in) var(--bz-radius-in) 0; min-width: 6.5rem; }

/* Inside the result strip the button is part of the box, so it does not lift out of it on hover. */
.bz-result .bz-btn:hover { transform: none; box-shadow: none; }

.bz-result.is-error { border-color: var(--bz-danger); color: var(--bz-danger); }

.bz-ok  { color: #2e7d32; }

.bz-bad { color: #b71c1c; }

.bz-ta-wrap {
    border: var(--bz-border); border-radius: var(--bz-radius);
    background: var(--bz-bg); overflow: hidden;
}

.bz-ta-wrap:hover, .bz-ta-wrap:focus { border-color: var(--bz-primary); outline: none; }

.bz-ta-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }

.bz-ta-head label { font-weight: 600; }

.bz-ta-head .bz-chk-lbl { font-weight: 400; }

#bz-rwp-input-label { cursor: text; }

.bz-gutter-wrap { display: flex; }

#bz-rwp-line-numbers {
    flex: 0 0 auto; min-width: 32px;
    padding: 8px 5px 20px; text-align: right; white-space: pre;
    background: var(--bz-surface); border-right: var(--bz-border);
    color: var(--bz-muted); pointer-events: none; user-select: none; overflow: hidden;
}

#bz-rwp-input {
    flex: 1 1 0%; padding: 10px;
    background: transparent; border: none; outline: none;
    white-space: nowrap; overflow-x: auto; resize: vertical;
}

#bz-rwp-input::placeholder { white-space: pre-wrap; word-break: break-word; }

#bz-rwp-form .bz-sep-row, #bz-rwp-results-section .bz-sep-row { gap: 4px 14px; }

.bz-ta-head + .bz-ta-wrap, .bz-ta-wrap + .bz-sep-row { margin-top: 8px; }

.bz-btn-more {
    display: block; width: 100%; padding: 12px; margin-top: 12px;
    background: var(--bz-surface); color: var(--bz-primary);
    font-family: inherit; font-size: var(--bz-fs-md); font-weight: 600;
    border: var(--bz-border); border-radius: var(--bz-radius); cursor: pointer;
    transition: border-color var(--bz-transition);
}

.bz-btn-more:hover:not( :disabled ) { border-color: var(--bz-primary); }

.bz-btn-more:disabled { cursor: not-allowed; opacity: .6; }

.bz-result-text {
    position: relative; display: inline-block;
    white-space: pre-wrap; word-break: break-word; overflow-wrap: break-word;
}

.bz-row-blur .bz-result-text::after {
    content: ''; position: absolute; inset: 0 25%;
    background: linear-gradient(to right, rgba(255,255,255,.2), rgba(255,255,255,.8), rgba(255,255,255,.2));
    backdrop-filter: blur(3px); pointer-events: none;
}

/* Post gallery (partials/post-gallery.php). Sits outside the prose rules on purpose.
   No thumbnail size: the grid shows the same file the lightbox opens, cropped to 4:3.
   Always three columns (about 210px each in the 650px column; 12 per page fills four full
   rows). auto-fit stretched the tiles of a short last row to fill it, so one or two
   leftover images came out larger than the rest. A fixed track keeps every tile one size. */

.bz-gallery-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    /* Arriving by #gallery puts the grid's top edge at the top of the window, where the
       sticky header (about 80px) would cover it. The pager links keep #gallery on purpose:
       it is what moves the visitor to the grid, with no script involved. */
    scroll-margin-top: 96px;
    margin: clamp(36px, 6vw, 56px) 0 0;
    padding: 0;
}

.bz-gallery-grid a {
    display: block;
    overflow: hidden;
    border-radius: var(--bz-radius);
}

.bz-gallery-grid img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    background: var(--bz-surface);
    transition: transform 0.35s ease;
}

.bz-gallery-grid a:hover img,
.bz-gallery-grid a:focus-visible img {
    transform: scale(1.04);
}


/* Gallery lightbox: a native <dialog> built by script.js on first click (Escape,
   focus trap and focus return are the browser's). The dialog is the full-viewport
   surface, so a click on it (not on the image or a button) closes it. */

.bz-lightbox {
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: #fff;
}

.bz-lightbox[open] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
}

.bz-lightbox::backdrop { background: rgba(17, 20, 26, 0.92); }

.bz-lightbox img {
    max-width: calc(100vw - 32px);
    max-height: calc(100vh - 140px);
    object-fit: contain;
}
.bz-lightbox p {
    max-width: min(90vw, 650px);
    min-height: 1.4em;
    margin: 0;
    text-align: center;
    font-size: var(--bz-fs-sm);
}
.bz-lightbox span {
    font-size: var(--bz-fs-xs);
    font-variant-numeric: tabular-nums;
    opacity: 0.75;
}
.bz-lightbox button {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 44px minimum tap target */
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 28px;
    line-height: 1;
    cursor: pointer;
}
.bz-lightbox button:hover { background: rgba(255, 255, 255, 0.28); }
.bz-lightbox button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.bz-lightbox-close { top: 12px; right: 12px; }

.bz-lightbox-prev  { left: 12px;  top: 50%; transform: translateY(-50%); }

.bz-lightbox-next  { right: 12px; top: 50%; transform: translateY(-50%); }

/* A one-line muted note in a page head (the diary entry's admin "Edit entry" link). */

/* -- Tag filter (partials/tag-filter.php) ---------------------------------------------
   A button at the right of the page title that opens a drawer (the nav drawer's own
   .bz-drawer styles), and a chip under the header for the tag in use. One tag at a time,
   so every row is a link drawn as a radio dot. Flat and quiet, like the rest. */
.bz-icon-filter { width: 16px; height: 16px; --bz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6h10M18 6h2M4 12h4M12 12h8M4 18h12M20 18h0'/%3E%3Ccircle cx='16' cy='6' r='2'/%3E%3Ccircle cx='10' cy='12' r='2'/%3E%3Ccircle cx='18' cy='18' r='2'/%3E%3C/svg%3E"); }
.bz-tf-btn {
    flex-shrink: 0; width: 40px; height: 40px;
    display: inline-flex; align-items: center; justify-content: center;
    border: var(--bz-border); border-radius: var(--bz-radius); background: transparent;
    color: var(--bz-primary); cursor: pointer; transition: border-color var(--bz-transition);
}
.bz-tf-btn[hidden] { display: none; }
.bz-tf-btn:hover { border-color: var(--bz-primary); }
.bz-tf-btn:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: 2px; }
.bz-tf-btn .bz-icon { width: 18px; height: 18px; }
.bz-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px; border: var(--bz-border); border-radius: var(--bz-radius);
    font-size: var(--bz-fs-sm); line-height: 1.5; color: var(--bz-primary);
    background: transparent; text-decoration: none; cursor: pointer;
    transition: border-color var(--bz-transition), background var(--bz-transition);
}
.bz-chip:hover { border-color: var(--bz-primary); }
.bz-chip.is-on { background: var(--bz-primary); border-color: var(--bz-primary); color: var(--bz-bg); }
.bz-tf-panel { padding: 8px 0 24px; }
/* The find box is the site's .bz-search.is-sm without its button, so the right padding that
   the button would have used is restored. width: auto lets the side margins size it; the
   [hidden] rule is needed because .bz-search's display: flex would otherwise win over it. */
.bz-tf-find { width: auto; margin: 12px 20px 4px; padding-right: 14px; }
.bz-tf-find[hidden] { display: none; }
.bz-tf-list { list-style: none; margin: 12px 0 0; padding: 0; }
.bz-tf-opt {
    display: flex; align-items: center; gap: 12px; padding: 11px 20px;
    font-size: var(--bz-fs-sm); color: var(--bz-primary); text-decoration: none;
    transition: background var(--bz-transition);
}
.bz-tf-opt::before {
    content: ""; flex-shrink: 0; width: 16px; height: 16px; box-sizing: border-box;
    border: 1.5px solid var(--bz-muted); border-radius: 50%;
}
.bz-tf-opt[aria-current="true"]::before {
    border-color: var(--bz-primary);
    background: radial-gradient(circle, var(--bz-primary) 0 4px, transparent 5px);
}
.bz-tf-opt[aria-current="true"] { font-weight: 600; }
.bz-tf-opt:hover { background: var(--bz-surface); }
.bz-tf-opt:focus-visible { outline: 2px solid var(--bz-primary); outline-offset: -2px; }
.bz-tf-opt span { flex: 1; }
.bz-tf-opt small { color: var(--bz-muted); font-weight: 400; }
.bz-tf-none { margin: 12px 20px 0; font-size: var(--bz-fs-sm); color: var(--bz-muted); }

/* The page head of every archive (front/archive.php, front/archive-product.php): the title on the
   left, the search box and the filter button at the right end of the same row; the intro, the
   active-tag chip and the disclosure note each take a full row under it. No media query: the row
   wraps by itself. The search box and the filter button are ONE flex item (.bz-archive-tools), so
   they wrap together: when the title and the tools' basis (200px, 260px with a filter button: a search box
   of at least 200px) do not fit, the whole tools row drops under the title and takes the full
   width (up to 360px). A short title such as Blog keeps the box
   beside it on most phones. Inside, the box takes what the button leaves (up to 300px). Markup
   order is h1, tools, intro, so the tab order is the reading order. A `hidden` or missing filter
   button leaves no gap: the 12px is a flex gap, which skips what is not displayed. The drawer and
   its overlay are position: fixed and take no space. .bz-page-head > * + * would put a top margin on
   every child, so it is reset here. The h1 is trimmed at both ends (the page-head rule trims only the
   top, and its :is() selector out-ranks a single class, hence .bz-page-head.bz-archive-head), so its
   box is the letters and the row centres them on the search box. */
.bz-archive-head { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem 12px; }
.bz-archive-head > * { margin-top: 0; }
.bz-page-head.bz-archive-head > h1 { text-box-trim: trim-both; }
.bz-archive-tools { display: flex; justify-content: flex-end; gap: 12px; flex: 1 1 200px; min-width: 0; max-width: 360px; margin-left: auto; }
.bz-archive-tools:has(> .bz-tf-btn) { flex-basis: 260px; }
.bz-archive-tools > .bz-search { flex: 1 1 0; min-width: 0; max-width: 300px; }
.bz-archive-tools > .bz-tf-btn { width: 48px; height: 48px; }
.bz-archive-head > p { flex-basis: 100%; }

/* Homepage (front/home.php). The only page wider than the 650px column: the
   is-wide modifier on <main> lifts it to 1100px. It reuses the site's own parts
   (.bz-page-head, .bz-list/.bz-row, .bz-btn-row, .bz-btn, .bz-text-sm/xs) and
   adds only what none of them covers. Scoped to .bz-home, .bz-hero, .bz-product. */

.bz-main.is-wide { max-width: calc(1100px + var(--bz-pad) * 2); }

.bz-home { display: flex; flex-direction: column; gap: clamp(56px, 9vw, 96px); }

.bz-home h1,
.bz-home h2 { font-size: var(--bz-fs-h2); font-weight: 700; line-height: 1.45; text-wrap: balance; }

.bz-home p { text-wrap: pretty; }

/* Section headings: the same size and weight as an article's h2. */

.bz-home-section > * + * { margin-top: 1.5rem; }

/* A section's heading sits closer to its intro than the hero's does. */
.bz-home-section > .bz-page-head > * + * { margin-top: .5rem; }

/* A sticky header covers the top of a section the page scrolls to. */
.bz-home-section { scroll-margin-top: 88px; }
.bz-home-section:focus { outline: none; }

/* Hero: text left, portrait right; one centred column on a phone. */
.bz-hero {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: clamp(24px, 5vw, 64px);
}

.bz-hero-photo {
    grid-column: 2;
    grid-row: 1;
    width: clamp(120px, 22vw, 240px);
    height: auto;
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--bz-surface);
}

.bz-hero .bz-page-head { grid-column: 1; grid-row: 1; }

.bz-hero .bz-page-head p { max-width: 34em; }

/* .bz-btn-row stretches its buttons to fill the row; in a hero that would be two huge bars. */
.bz-hero .bz-btn-row { max-width: 26rem; margin-top: 1.75rem; }

/* Service rows without a link (a page not published yet) carry information only: no chevron, no hover lift, a description that
   wraps (a .bz-row line is a single truncated line otherwise). */
.bz-row.is-info:not(:has(a))::after { display: none; }
.bz-row.is-info:not(:has(a)):hover { border-color: var(--bz-line); transform: none; }
.bz-row.is-info { align-items: flex-start; }
.bz-row.is-info > div { gap: 4px; }
.bz-row.is-info strong { font-weight: 600; line-height: 1.6; }
.bz-row.is-info small { white-space: normal; overflow: visible; }
.bz-row.is-info .bz-home-tool { margin-top: 6px; }

/* Product tile: a square cover over the title, so a portrait book cover, a square pack image
   and a PDF preview all fit (object-fit: cover once real images replace the placeholder). */
.bz-product {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: 12px 12px 16px;
    border: var(--bz-border);
    border-radius: var(--bz-radius);
}

.bz-product h3 { padding-inline: 8px; font-size: var(--bz-fs-body); font-weight: 600; line-height: 1.5; text-wrap: balance; }

.bz-product p { padding-inline: 8px; }

.bz-product-cover {
    align-self: stretch;
    display: grid;
    place-items: center;
    aspect-ratio: 1;
    position: relative;
    border-radius: var(--bz-radius);
    background: var(--bz-surface);
    font-size: var(--bz-fs-sm);
    font-weight: 600;
    line-height: 1.5;
    text-align: center;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--bz-muted);
}

/* ---- Products (front/archive-product.php, front/single-product.php, partials/product-card.php) ----
   Both pages are WIDE: they set $main_class = 'is-wide' (header.php), so <main> is the homepage's
   1100px (.bz-main.is-wide above). The homepage's own .bz-product tile is a separate, simpler
   thing and is not changed here; what follows is the product section's own markup (.bz-pcard,
   .bz-pgrid, .bz-pa-*, .bz-pp-*) and the cover helpers they share with the tile. */

/* A card's cover: a square tile with the image CONTAINED in it (a portrait, a square and a banner
   all show whole), lifted off the tile by a shadow that follows the picture's own edge. */
.bz-product-cover img {
    position: absolute; inset: 12px;
    width: calc(100% - 24px); height: calc(100% - 24px);
    object-fit: contain;
    filter: drop-shadow(0 0 0.5px rgb(0 0 0 / .35)) drop-shadow(0 6px 10px rgb(0 0 0 / .16));
}

/* Not on sale yet: a badge in the corner of a real cover. With no cover the placeholder text
   says it already (the homepage's demo tiles). A sale puts its percentage in the same corner. */
.bz-product-badge {
    position: absolute; top: 8px; left: 8px;
    padding: 2px 10px;
    border-radius: var(--bz-radius);
    background: var(--bz-primary); color: var(--bz-bg);
    font-size: var(--bz-fs-xs); font-weight: 600; line-height: 1.6;
    letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;
}
.bz-product-badge.is-sale { background: var(--bz-danger); color: #fff; letter-spacing: 0; text-transform: none; }

/* On sale with no cover: the title's first letter, big. */
.bz-product-cover.is-letter { font-size: 3rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--bz-primary); }

/* The price, on a card and on a product's page. A sale puts the regular price, crossed out and
   quieter, before it. "Coming soon" replaces it on a card. */
.bz-price { font-weight: 700; }
.bz-price del { margin-inline-end: .35em; font-weight: 500; color: var(--bz-muted); }
.bz-price.is-soon { font-size: var(--bz-fs-sm); font-weight: 600; color: var(--bz-muted); }

/* The grid: two columns on a phone, three from 640px, four from 900px. Used by a product section's
   page and by "More products". */
.bz-pgrid { list-style: none; margin-inline: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media ( min-width: 640px ) { .bz-pgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; } }
@media ( min-width: 900px ) { .bz-pgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; } }

/* A card: a border, the cover tile flush at the top, the text under it. The title link is stretched
   over the whole card, like a .bz-row. */
.bz-pcard {
    position: relative; display: flex; flex-direction: column; min-width: 0;
    border: var(--bz-border); border-radius: var(--bz-radius); overflow: hidden; background: var(--bz-bg);
    transition: border-color var(--bz-transition), transform var(--bz-transition);
}
.bz-pcard:hover { border-color: var(--bz-primary); transform: translateY(-2px); }
.bz-pcard:has(h3 a:focus-visible) { outline: 2px solid currentColor; outline-offset: 2px; }
.bz-pcard > .bz-product-cover { border-radius: 0; border-bottom: var(--bz-border); }
.bz-pcard-body { flex: 1; display: flex; flex-direction: column; gap: 6px; padding: 14px 16px 16px; }
.bz-pcard-tags { font-size: var(--bz-fs-xs); font-weight: 600; line-height: 1.5; letter-spacing: 0.06em; text-transform: uppercase; color: var(--bz-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bz-pcard h3 {
    font-size: var(--bz-fs-md); font-weight: 600; line-height: 1.4; text-wrap: balance;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.bz-pcard h3 a { color: inherit; text-decoration: none; }
.bz-pcard h3 a::after { content: ""; position: absolute; inset: 0; }
.bz-pcard h3 a:focus-visible { outline: none; }
.bz-pcard-line {
    font-size: var(--bz-fs-sm); line-height: 1.6; color: var(--bz-muted);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.bz-pcard-foot { margin-top: auto; padding-top: 8px; }

/* Phone: tighter, and no intro line, so two cards fit and stay the same height. */
@media ( max-width: 519px ) {
    .bz-pcard-body { gap: 4px; padding: 10px 12px 12px; }
    .bz-pcard h3 { font-size: var(--bz-fs-sm); }
    .bz-pcard-line { display: none; }
    .bz-product-badge { top: 4px; left: 4px; padding: 0 7px; font-size: 10px; }
}

.bz-pa-soon { margin-top: clamp(40px, 6vw, 56px); font-size: var(--bz-fs-lg); line-height: 1.3; }
.bz-pa-soon + .bz-pgrid { margin-top: 1rem; }

/* A product's page: HERO. Two columns from 760px, one below it (the cover first). */
.bz-pp-hero { display: grid; gap: clamp(24px, 5vw, 64px); align-items: center; }
@media ( min-width: 760px ) {
    .bz-pp-hero { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .bz-pp-hero .bz-pp-stage { aspect-ratio: 1; }
    .bz-pp-hero .bz-pp-stage img { max-height: clamp(260px, 36vw, 420px); }
}
.bz-pp-info > * + * { margin-top: 28px; }

/* The cover floats in a light panel, whole, in the same frame whatever its shape. */
.bz-pp-stage {
    display: grid; place-items: center;
    margin: 0; padding: clamp(20px, 5vw, 36px) clamp(16px, 4vw, 28px);
    border-radius: var(--bz-radius);
    background: linear-gradient(180deg, color-mix(in srgb, var(--bz-surface) 55%, #fff) 0%, var(--bz-surface) 100%);
}
.bz-pp-stage img {
    display: block; width: auto; height: auto; max-width: 100%; max-height: clamp(210px, 50vw, 340px);
    object-fit: contain; border-radius: var(--bz-radius);
    box-shadow: 0 0 0 1px rgb(0 0 0 / .07), 0 14px 32px -8px rgb(0 0 0 / .22), 0 3px 8px rgb(0 0 0 / .08);
}
/* No cover: a plain tile with the title's first letter. */
.bz-pp-ph {
    display: grid; place-items: center; width: clamp(120px, 28vw, 170px); aspect-ratio: 3 / 4;
    border-radius: var(--bz-radius); background: var(--bz-bg);
    font-size: clamp(3rem, 8vw, 4rem); font-weight: 600; color: var(--bz-primary);
    box-shadow: 0 0 0 1px rgb(0 0 0 / .07), 0 14px 32px -8px rgb(0 0 0 / .22);
}

/* Price and button on one line, over the full width of the column, with no box around them; with
   no price the button takes the line. A sale puts what it saves under the price. */
.bz-pp-buyrow { display: flex; align-items: center; gap: 20px; }
.bz-pp-pricebox { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.bz-pp-buyrow .bz-price { font-size: clamp(30px, 6vw, 34px); line-height: 1; letter-spacing: -.01em; }
.bz-pp-buyrow del { font-size: .55em; letter-spacing: 0; }
.bz-pp-buyrow .bz-btn { flex: 1; padding-block: var(--bz-btn-py-l); }
.bz-pp-save {
    padding: 1px 8px; border-radius: var(--bz-radius);
    background: color-mix(in srgb, var(--bz-danger) 10%, transparent); color: var(--bz-danger);
    font-size: var(--bz-fs-xs); font-weight: 600; line-height: 1.6;
}
.bz-pp-note { margin-top: 12px; font-size: var(--bz-fs-sm); line-height: 1.7; color: var(--bz-muted); }
.bz-pp-note a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.bz-pp-note a:hover { color: var(--bz-primary); }

/* REST: a centred 650px reading column under one hairline, the width of a post. The three of
   its parts, "Look inside" and the write-up, are set apart. The article's own flow rule is
   one specificity step below the first selector, so it does not undo the margin. */
.bz-main > .bz-pp > .bz-pp-rest { margin-top: clamp(40px, 6vw, 64px); padding-top: clamp(32px, 5vw, 48px); border-top: var(--bz-border); }
.bz-pp-rest > * { max-width: 650px; margin-inline: auto; }
.bz-pp-rest > * + * { margin-top: clamp(40px, 7vw, 56px); }

/* Look inside: the post's gallery as a strip you swipe, four sample pages across on a desktop. It keeps
   .bz-gallery-grid (script.js's lightbox finds its links by that class) and overrides its layout. */
.bz-gallery-grid.bz-pp-strip {
    display: flex; gap: 10px; margin: 18px 0 0; padding: 0; list-style: none;
    overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
}
.bz-pp-strip::-webkit-scrollbar { display: none; }
.bz-pp-strip li { flex: 0 0 calc((100% - 30px) / 4); scroll-snap-align: start; margin: 0; padding: 0; }
.bz-pp-strip li::before { content: none; }
.bz-pp-strip a { border: var(--bz-border); border-radius: var(--bz-radius); background: var(--bz-surface); transition: border-color var(--bz-transition); }
.bz-pp-strip a:hover { border-color: var(--bz-primary); }
.bz-gallery-grid.bz-pp-strip img { aspect-ratio: 3 / 4; }

@media ( max-width: 639px ) {
    /* The strip runs to the screen's edges, thumbnails 38% wide so the next one peeks. */
    .bz-gallery-grid.bz-pp-strip { margin-inline: calc(var(--bz-pad) * -1); padding-inline: var(--bz-pad); scroll-padding-inline: var(--bz-pad); }
    .bz-pp-strip li { flex-basis: 38%; }
}

/* The buy bar: fixed across the bottom, shown by script.js (.is-on) once the hero's button has gone
   above the screen and stays to the end of the page, where script.js lifts it (inline bottom) so it docks
   on top of the footer instead of covering it. It is hidden with visibility, so its link is not
   in the tab order while it is away. z-index sits under the header (200) and the drawers (500). The
   bottom padding clears the iPhone home bar. A phone drops the title and gives the button the room. */
.bz-pp-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 150; margin: 0;
    padding: 10px var(--bz-pad) calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--bz-bg); border-top: var(--bz-border); box-shadow: 0 -6px 20px rgb(0 0 0 / .08);
    transform: translateY(100%); visibility: hidden;
    transition: transform .25s ease, visibility 0s linear .25s;
}
/* The docked bar sits over the foot of <main>; this room lets the last cards scroll clear of it. */
.bz-main:has(> .bz-pp-bar) { padding-bottom: 120px; }
.bz-pp-bar.is-on { transform: none; visibility: visible; transition-delay: 0s; }
.bz-pp-bar-in { max-width: 1100px; margin-inline: auto; display: flex; align-items: center; gap: 20px; }
.bz-pp-bar-title { flex: 1; min-width: 0; margin: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bz-pp-bar .bz-pp-buyrow { flex: 0 0 auto; gap: 16px; }
.bz-pp-bar .bz-pp-buyrow .bz-price { font-size: var(--bz-fs-lg); }
.bz-pp-bar .bz-pp-buyrow .bz-btn { flex: 0 0 auto; padding-block: var(--bz-btn-py-m); padding-inline: 28px; }
@media ( max-width: 639px ) {
    .bz-pp-bar-title { display: none; }
    .bz-pp-bar .bz-pp-buyrow { flex: 1; }
    .bz-pp-bar .bz-pp-buyrow .bz-btn { flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .bz-pp-bar { transition: none; }
}

/* Closing contact line: flat and centred under a rule, not a box. */
.bz-home-end { padding-top: clamp(40px, 6vw, 64px); border-top: var(--bz-border); text-align: center; }

.bz-home-end > * + * { margin-top: 1rem; }

.bz-home-end p { max-width: 32em; margin-inline: auto; }

.bz-home-end .bz-btn { margin-top: 1rem; padding: 16px 28px; }

/* Phone: one product per row, laid out as cover left, text right, so four square covers
   do not become four full-width squares. */
@media ( max-width: 600px ) {
    .bz-home .bz-product { display: grid; grid-template-columns: 104px minmax(0, 1fr); column-gap: 12px; row-gap: 4px; align-content: start; padding: 12px; }
    .bz-home .bz-product-cover { grid-row: 1 / span 2; align-self: start; }
    .bz-home .bz-product > :not(.bz-product-cover) { grid-column: 2; padding-inline: 0; }

    .bz-hero { grid-template-columns: 1fr; justify-items: center; text-align: center; }
    .bz-hero-photo, .bz-hero .bz-page-head { grid-column: 1; }
    .bz-hero-photo { grid-row: 1; width: 128px; }
    .bz-hero .bz-page-head { grid-row: 2; }
    .bz-hero .bz-page-head p { margin-inline: auto; }
    .bz-hero .bz-btn-row { margin-inline: auto; width: 100%; }
}

/* ==== Service pages (front/services/, one 650px column) ==================================
   Reuses .bz-page-head, .bz-pp-buyrow / .bz-pp-note / .bz-pp-bar (the product page's buy row and
   bar), .bz-seg, .bz-home-end and .bz-related. Only the parts a service needs are new, and every
   one is scoped to .bz-svc. The demo is an illustration, so it sits in a frame and is aria-labelled. */
.bz-main > .bz-svc > * + * { margin-top: clamp(40px, 7vw, 56px); }
.bz-main > .bz-svc > header + .bz-facts { margin-top: 28px; }
.bz-main > .bz-svc > [data-bz-buy] { margin-top: 32px; }
/* The last question already ends in a hairline, so the closing section adds none of its own. */
.bz-svc .bz-home-end { padding-top: 0; border-top: 0; }
.bz-main > .bz-svc > header + .bz-facts li { padding-block: 10px; }
.bz-svc .bz-pp-note { margin-top: 12px; }
.bz-svc section > h2 + * { margin-top: 1rem; }
.bz-price small { margin-inline-start: 8px; font-size: var(--bz-fs-sm); font-weight: 400; letter-spacing: 0; color: var(--bz-muted); }

/* What is set up / how it works / what you need: hairline lists, title over one line. */
.bz-facts { list-style: none; margin: 0; padding: 0; border-top: var(--bz-border); }
.bz-facts li { display: grid; gap: 2px; padding: 14px 0; border-bottom: var(--bz-border); line-height: 1.6; }
.bz-facts li b { font-weight: 600; }
.bz-facts li span { font-size: var(--bz-fs-md); color: var(--bz-muted); }
ol.bz-facts { counter-reset: bz-step; }
ol.bz-facts li { counter-increment: bz-step; grid-template-columns: 2rem 1fr; column-gap: 8px; }
ol.bz-facts li::before { content: counter(bz-step); grid-row: span 2; font-weight: 600; color: var(--bz-muted); }
ol.bz-facts li:not(:has(span))::before { grid-row: auto; }
.bz-svc-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
.bz-svc-two h3 { margin-bottom: .5rem; font-size: var(--bz-fs-md); }
.bz-svc-two .bz-facts li { font-size: var(--bz-fs-md); color: var(--bz-muted); }
.bz-svc-two + .bz-text-sm { margin-top: 1.25rem; }
@media (max-width: 560px) { .bz-svc-two { grid-template-columns: 1fr; } }

.bz-svc-who { display: grid; grid-template-columns: 56px 1fr; gap: 16px; align-items: center; }
.bz-svc-who img { width: 56px; height: 56px; border-radius: 50%; background: var(--bz-surface); }
.bz-svc-who p { margin: 0; font-weight: 600; }

/* The demo: header (title and the switch), a browser-like frame, one line of caption. */
.bz-demo > header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.bz-demo > header h2 { margin: 0; }
.bz-demo [hidden] { display: none; }
.bz-demo > .bz-text-xs { margin-top: .75rem; }
.bz-demo-frame { border: var(--bz-border); border-radius: var(--bz-radius); background: var(--bz-bg); overflow: hidden; }
.bz-demo-bar { padding: 8px 12px; background: var(--bz-surface); border-bottom: var(--bz-border); font-size: var(--bz-fs-xs); color: var(--bz-muted); }
.bz-demo-body { position: relative; min-height: 300px; padding: 20px; }
.bz-demo-page > * + * { margin-top: 10px; }
.bz-demo-page i { display: block; height: 10px; border-radius: var(--bz-radius); background: var(--bz-surface); }
.bz-demo-page i:nth-child(2n) { width: 80%; }
.bz-demo-page i:nth-child(3n) { width: 60%; }
.bz-toast { position: absolute; top: 16px; right: 16px; display: grid; grid-template-columns: 28px 1fr; column-gap: 10px; row-gap: 2px; max-width: min(300px, calc(100% - 32px)); padding: 12px; background: var(--bz-bg); border: var(--bz-border); border-radius: var(--bz-radius); box-shadow: 0 6px 20px rgb(0 0 0 / .1); font-size: var(--bz-fs-sm); line-height: 1.5; }
.bz-toast-icon { grid-row: span 3; display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--bz-radius); background: var(--bz-primary); color: var(--bz-bg); font-size: 10px; font-style: normal; font-weight: 700; }
.bz-toast small { font-size: var(--bz-fs-xs); color: var(--bz-muted); }
.bz-toast strong { font-weight: 600; }
.bz-toast span { color: var(--bz-muted); }
.bz-demo-rows > * + * { margin-top: 8px; }
.bz-demo-rows > * { display: flex; justify-content: space-between; gap: 12px; padding: 10px 12px; border: var(--bz-border); border-radius: var(--bz-radius); font-size: var(--bz-fs-sm); }
.bz-demo-body { font-size: var(--bz-fs-md); }
.bz-demo-tag { font-style: normal; padding: 0 8px; border: var(--bz-border); border-radius: var(--bz-radius); font-size: var(--bz-fs-xs); color: var(--bz-muted); }
.bz-demo-tag.is-on { background: var(--bz-primary); border-color: var(--bz-primary); color: var(--bz-bg); }
.bz-demo-form { max-width: 320px; margin-inline: auto; padding: 16px; border: var(--bz-border); border-radius: var(--bz-radius); font-size: var(--bz-fs-sm); }
.bz-demo-form > * + * { margin-top: 10px; }
.bz-demo-plain, .bz-demo-styled { display: grid; gap: 8px; }
.bz-demo-styled { padding: 16px; background: var(--bz-surface); border-radius: var(--bz-radius); }
.bz-demo-body ul { list-style: none; margin: 0; padding: 0; }
.bz-demo-shop > ul { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; }
.bz-demo-shop > ul > li { display: grid; gap: 4px; padding: 10px; border: var(--bz-border); border-radius: var(--bz-radius); font-size: var(--bz-fs-sm); }
.bz-demo-shop > ul > li i { display: block; aspect-ratio: 4 / 3; margin-bottom: 4px; border-radius: var(--bz-radius); background: var(--bz-surface); }
.bz-demo-shop > ul > li span { color: var(--bz-muted); }
.bz-demo-shop > ul > li b { margin-top: 4px; padding: 4px 0; border-radius: var(--bz-radius); background: var(--bz-primary); color: var(--bz-bg); font-size: var(--bz-fs-xs); font-weight: 600; text-align: center; }
.bz-demo-head { display: flex; justify-content: space-between; gap: 12px; margin: 0 0 12px; font-size: var(--bz-fs-sm); }
.bz-demo-head span { color: var(--bz-muted); }
.bz-demo-rows li small { flex-basis: 100%; color: var(--bz-muted); font-size: var(--bz-fs-xs); }
.bz-demo-rows li { flex-wrap: wrap; align-items: center; }
.bz-demo-form { display: grid; }
.bz-demo-form span { padding: 8px 10px; border: var(--bz-border); border-radius: var(--bz-radius); color: var(--bz-muted); }
.bz-demo-form b { padding: 8px 0; border-radius: var(--bz-radius); background: var(--bz-primary); color: var(--bz-bg); text-align: center; font-weight: 600; }
.bz-demo-form + .bz-demo-rows, .bz-demo-form + ul { margin-top: 16px; }
.bz-demo-styled ul { display: grid; gap: 10px; }
.bz-demo-styled li { display: grid; gap: 2px; padding: 12px; background: var(--bz-bg); border-radius: var(--bz-radius); font-size: var(--bz-fs-sm); }
.bz-demo-styled li i { width: 24px; height: 4px; background: var(--bz-primary); border-radius: var(--bz-radius); }
.bz-demo-styled li span { color: var(--bz-muted); }
.bz-svc .bz-page-head > .bz-row-eyebrow + h1 { margin-top: .5rem; }
@media (prefers-reduced-motion: no-preference) {
    .bz-demo-body .is-in { animation: bz-demo-in .35s ease both; }
    @keyframes bz-demo-in { from { opacity: 0; transform: translateY(6px); } }
}

/* ==========================================================================================
   Vault and Deals entries (front/single-directory.php, content/content-deals.php)
   ONE state class does the work for Deals: .bz-deal.is-open | .is-soon | .is-ended is on the article and
   on the buy bar (set on the server, corrected by script.js feature 9). Every wording that depends on it
   is in the HTML in all its versions; these rules show one, so a cached page never states a stale fact.
   ========================================================================================== */
.bz-deal.is-open .bz-s-soon, .bz-deal.is-open .bz-s-ended,
.bz-deal.is-soon .bz-s-open, .bz-deal.is-soon .bz-s-ended,
.bz-deal.is-ended .bz-s-open, .bz-deal.is-ended .bz-s-soon { display: none; }
.bz-deal:not(.is-ended) .bz-over, .bz-deal.is-ended .bz-live { display: none; }

/* The deal row: status, dated price and a note on the left, the button on the right (full width on a phone). */
.bz-dealrow {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
    padding-top: 18px; border-top: var(--bz-border);
}
.bz-dealrow-l { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.bz-dealrow-l small { font-size: var(--bz-fs-sm); line-height: 1.5; color: var(--bz-muted); }
.bz-dealst { display: inline-flex; align-items: center; gap: 8px; font-size: var(--bz-fs-md); font-weight: 600; line-height: 1.4; }
.bz-dealst i { width: 9px; height: 9px; border-radius: 50%; flex: none; background: #2e7d32; }
.bz-deal.is-soon .bz-dealst i { background: #b26a00; }
.bz-deal.is-ended .bz-dealst i { background: var(--bz-bg); box-shadow: inset 0 0 0 2px #888; }
.bz-dealprice { font-size: 22px; font-weight: 700; line-height: 1.3; }
.bz-dealprice small, .bz-pp-bar-title small small { font-weight: 400; font-size: var(--bz-fs-sm); color: var(--bz-muted); }
.bz-dealrow .bz-btn { flex: 0 0 auto; padding-block: var(--bz-btn-py-l); }
@media ( max-width: 560px ) {
    .bz-dealrow .bz-btn { flex: 1 1 100%; }
}

/* An ended deal's button keeps its link and only changes its look: the outline variant. */
.bz-deal.is-ended .bz-btn { background: var(--bz-bg); color: var(--bz-primary); box-shadow: inset 0 0 0 1px var(--bz-primary); }
.bz-deal.is-ended .bz-btn:hover { background: var(--bz-primary-h); color: var(--bz-bg); box-shadow: inset 0 0 0 1px var(--bz-primary-h); }

/* "Worth checking on the listing": a quiet box with empty check squares, no icons. */
.bz-byb { padding: 16px 18px; border: var(--bz-border); border-radius: var(--bz-radius); background: var(--bz-surface); }
.bz-byb h2 { margin: 0 0 .4rem; font-size: var(--bz-fs-md); line-height: 1.5; }
.bz-byb ul { margin: 0; padding: 0; list-style: none; }
.bz-byb li { position: relative; padding: 3px 0 3px 22px; font-size: var(--bz-fs-md); line-height: 1.7; }
.bz-byb li::before { content: ""; position: absolute; left: 2px; top: .72em; width: 8px; height: 8px; border: 1.5px solid #666; border-radius: 2px; }

/* The closing disclaimer line. */
.bz-content .bz-fine { font-size: var(--bz-fs-sm); line-height: 1.7; color: var(--bz-muted); }

/* The buy bar on these pages sits in the 650px column and carries a title and a second line. */
.bz-dir-bar .bz-pp-bar-in { max-width: 650px; gap: 14px; }
.bz-dir-bar .bz-pp-bar-title { display: block; font-weight: 400; }
.bz-dir-bar .bz-pp-bar-title b { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.bz-dir-bar .bz-pp-bar-title small { display: block; overflow: hidden; text-overflow: ellipsis; font-size: var(--bz-fs-xs); line-height: 1.4; color: var(--bz-muted); }
.bz-dir-bar .bz-btn { flex: 0 0 auto; padding-block: var(--bz-btn-py-m); padding-inline: 24px; }
@media ( max-width: 639px ) {
    .bz-dir-bar .bz-pp-bar-title { display: block; }
    .bz-dir-bar .bz-pp-bar-in .bz-btn { padding-inline: 16px; }
}
.bz-dir-bar .bz-pp-bar-title small small { display: inline; font-size: inherit; }
.bz-dir-bar .bz-pp-bar-title small b { font-size: var(--bz-fs-sm); color: var(--bz-primary); }

/* Notice line - the promotion above the sticky header (front/partials/notice-bar.php).
   Normal flow, not sticky: it scrolls away and .bz-header sticks to the top. Built only from
   the existing tokens, so it adds no colour of its own: a quiet grey bar, the link in the
   site's link blue. On a phone the sentence may take two lines; BZ_NOTICE_TEXT_MAX keeps it
   from taking three. */
.bz-notice {
    background: var(--bz-surface);
    border-bottom: var(--bz-border);
    padding-inline: var(--bz-pad);
    padding-block: 9px;
    font-size: var(--bz-fs-sm);
    line-height: 1.5;
    color: var(--bz-primary);
    text-align: center;
}

.bz-notice-text {
    margin: 0;
    max-width: none;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 2px 10px;
}

.bz-notice-tag {
    font-size: var(--bz-fs-xs);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bz-muted);
    border: var(--bz-border);
    border-radius: calc(var(--bz-radius) - 2px);
    padding: 0 6px;
    white-space: nowrap;
}

.bz-notice-link {
    color: var(--bz-link);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
    white-space: nowrap;
}

.bz-notice-link:hover { color: var(--bz-link-h); }
