        /* ------------------------------------------------------------ */
        /* Premium glass buttons — replaces flat solid-colour buttons.  */
        /* Scoped to the tool area, emitted after the tool CSS so it     */
        /* wins. Excludes the custom-select trigger and pure icon chips. */
        /* ------------------------------------------------------------ */
        :root { --gbtn-bg: rgba(255,255,255,0.55); --gbtn-brd: rgba(15,23,42,0.12); --gbtn-tint: 14, 116, 144; }
        :root.dark { --gbtn-bg: rgba(148,163,184,0.10); --gbtn-brd: rgba(148,197,255,0.18); --gbtn-tint: 34, 211, 238; }

        .tool-scope :is(button, .btn, a.btn, input[type="button"], input[type="submit"]):not(.rnd-select-btn):not(.rnd-select-opt) {
            background: var(--gbtn-bg) !important;
            -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
            border: 1px solid var(--gbtn-brd) !important;
            color: var(--text-main) !important;
            box-shadow: 0 1px 2px rgba(0,0,0,0.04) !important;
            transition: background .2s ease, border-color .2s ease, box-shadow .2s ease, transform .1s ease;
        }
        .tool-scope :is(button, .btn, a.btn):not(.rnd-select-btn):hover {
            background: rgba(var(--gbtn-tint), 0.16) !important;
            border-color: rgba(var(--gbtn-tint), 0.55) !important;
            box-shadow: 0 4px 16px rgba(var(--gbtn-tint), 0.18) !important;
        }
        .tool-scope :is(button, .btn):not(.rnd-select-btn):active { transform: translateY(1px); }
        .tool-scope :is(button, .btn):not(.rnd-select-btn):focus-visible {
            outline: 2px solid rgba(var(--gbtn-tint), 0.9); outline-offset: 2px;
        }
        /* Primary / call-to-action buttons keep an accent-tinted glass so the
           main action still stands out — just frosted, not a flat block. */
        .tool-scope :is(.btn-primary, .primary, [class*="download"], [class*="-primary"]):not(.rnd-select-btn) {
            background: linear-gradient(135deg, rgba(var(--gbtn-tint),0.28), rgba(var(--gbtn-tint),0.16)) !important;
            border-color: rgba(var(--gbtn-tint), 0.45) !important;
            color: var(--text-main) !important;
            font-weight: 700;
        }
        /* Icon-only chips (no text) shouldn't grow a heavy frame. */
        .tool-scope button:empty, .tool-scope button:has(> svg:only-child) {
            background: rgba(var(--gbtn-tint), 0.10) !important;
        }

        /* ============================================================ */
        /* Glassmorphism Forms & Controls (Manual Override)             */
        /* ============================================================ */
        
        :root {
            --ginput-bg: rgba(255,255,255,0.4);
            --ginput-brd: rgba(15,23,42,0.15);
            --ginput-focus: rgba(14,116,144,0.6);
            /* Opaque on purpose. This was rgba(...,0.85) and the !important below beat
               the page's own opaque `:root.dark .rnd-select-menu` rule, so an open
               dropdown showed the form behind it straight through the options -- the
               field label read through the list you were trying to pick from. A menu is
               the one surface that cannot be see-through; the frosting stays on the
               trigger, the border and the shadow. */
            --gmenu-bg: rgb(255,255,255);
        }
        :root.dark {
            --ginput-bg: rgba(15,23,42,0.4);
            --ginput-brd: rgba(148,197,255,0.25);
            --ginput-focus: rgba(34,211,238,0.8);
            --gmenu-bg: rgb(26,36,56);
        }

        /* Glass inputs, textareas, native selects */
        .tool-scope :is(input[type="text"], input[type="number"], input[type="password"], textarea:not(.rnd-hl-input):not(.panel-body textarea), select:not(.rnd-select-native)) {
            background: var(--ginput-bg) !important;
            -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
            border: 1px solid var(--ginput-brd) !important;
            border-radius: 0.5rem;
            color: var(--text-main) !important;
            box-shadow: inset 0 1px 3px rgba(0,0,0,0.05) !important;
            transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
        }

        .tool-scope :is(input[type="text"], input[type="number"], input[type="password"], textarea:not(.rnd-hl-input):not(.panel-body textarea), select:not(.rnd-select-native)):focus {
            outline: none;
            border-color: var(--ginput-focus) !important;
            box-shadow: 0 0 0 3px rgba(var(--gbtn-tint), 0.2), inset 0 1px 3px rgba(0,0,0,0.05) !important;
            background: rgba(255,255,255,0.6) !important;
        }
        :root.dark .tool-scope :is(input[type="text"], input[type="number"], input[type="password"], textarea:not(.rnd-hl-input):not(.panel-body textarea), select:not(.rnd-select-native)):focus {
            background: rgba(15,23,42,0.6) !important;
        }

        
        /* Custom Select / Dropdowns */
        .tool-scope .rnd-select-native {
            position: absolute !important; opacity: 0 !important; pointer-events: none !important;
            width: 1px !important; height: 1px !important; margin: 0 !important; padding: 0 !important; border: 0 !important;
            appearance: none !important; -webkit-appearance: none !important;
        }
        
        .tool-scope .rnd-select-btn {
            background: var(--ginput-bg) !important;
            -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
            border: 1px solid var(--ginput-brd) !important;
            border-radius: 0.5rem;
            color: var(--text-main) !important;
            box-shadow: inset 0 1px 3px rgba(0,0,0,0.05) !important;
            transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
        }
        
        .tool-scope .rnd-select.is-open .rnd-select-btn {
            border-color: var(--ginput-focus) !important;
            box-shadow: 0 0 0 3px rgba(var(--gbtn-tint), 0.2), inset 0 1px 3px rgba(0,0,0,0.05) !important;
        }
        
        .tool-scope .rnd-select-menu {
            background: var(--gmenu-bg) !important;
            -webkit-backdrop-filter: blur(16px);
            backdrop-filter: blur(16px);
            border: 1px solid var(--ginput-brd) !important;
            box-shadow: 0 10px 25px rgba(0,0,0,0.1) !important;
        }
        :root.dark .tool-scope .rnd-select-menu {
            box-shadow: 0 10px 25px rgba(0,0,0,0.4) !important;
        }

        /* Dropdown z-index fixes */
        .tool-scope .rnd-select {
            z-index: 20;
            width: 100%;
        }
        .tool-scope .rnd-select.is-open {
            z-index: 9999 !important;
        }
        .tool-scope .dropdown-content {
            z-index: 9999 !important;
        }

        /* Checkbox Glassmorphism */
        .tool-scope input[type="checkbox"]:not(.theme-switch) {
            appearance: none;
            width: 1.25rem;
            height: 1.25rem;
            background: var(--ginput-bg) !important;
            -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
            border: 1px solid var(--ginput-brd) !important;
            border-radius: 0.25rem;
            position: relative;
            cursor: pointer;
            transition: all 0.2s ease;
            display: inline-block;
            vertical-align: middle;
            margin-right: 0.5rem;
        }
        .tool-scope input[type="checkbox"]:not(.theme-switch):checked {
            background: rgba(var(--gbtn-tint), 0.8) !important;
            border-color: rgba(var(--gbtn-tint), 1) !important;
        }
        .tool-scope input[type="checkbox"]:not(.theme-switch):checked::after {
            content: '';
            position: absolute;
            left: 30%;
            top: 15%;
            width: 35%;
            height: 55%;
            border: solid white;
            border-width: 0 2px 2px 0;
            transform: rotate(45deg);
        }

        /* Colorful VS Code Editor text for highlighted code */
        /* Common editor highlighting classes */
        .tool-scope .hl-comment { color: #6a9955 !important; font-style: italic; }
        .tool-scope .hl-tag { color: #569cd6 !important; }
        .tool-scope .hl-attr { color: #9cdcfe !important; }
        .tool-scope .hl-val { color: #ce9178 !important; }
        .tool-scope .hl-keyword { color: #c586c0 !important; }
        .tool-scope .hl-string { color: #ce9178 !important; }
        .tool-scope .hl-number { color: #b5cea8 !important; }
        .tool-scope .hl-function { color: #dcdcaa !important; }
        .tool-scope .hl-property { color: #9cdcfe !important; }
        .tool-scope .hl-operator { color: #d4d4d4 !important; }
        
        /* Light mode variants for VS Code Light+ theme */
        :root:not(.dark) .tool-scope .hl-comment { color: #008000 !important; }
        :root:not(.dark) .tool-scope .hl-tag { color: #800000 !important; }
        :root:not(.dark) .tool-scope .hl-attr { color: #ff0000 !important; }
        :root:not(.dark) .tool-scope .hl-val { color: #0000ff !important; }
        :root:not(.dark) .tool-scope .hl-keyword { color: #0000ff !important; }
        :root:not(.dark) .tool-scope .hl-string { color: #a31515 !important; }
        :root:not(.dark) .tool-scope .hl-number { color: #098658 !important; }
        :root:not(.dark) .tool-scope .hl-function { color: #795e26 !important; }
        :root:not(.dark) .tool-scope .hl-property { color: #0451a5 !important; }
        :root:not(.dark) .tool-scope .hl-operator { color: #000000 !important; }

        .tool-scope textarea.code-input, .tool-scope .code-output {
            caret-color: var(--text-main) !important;
            color: var(--text-main) !important;
        }


/* Force transparency on editor components to ensure glassmorphism */
.tool-scope .panel,
.tool-scope .panel-body,
.tool-scope .rnd-hl-wrap,
.tool-scope .rnd-hl,
.tool-scope .rnd-hl-input,
.tool-scope textarea.rnd-hl-input {
    background: transparent !important;
}

/* Custom Glassmorphic Scrollbars */
.tool-scope ::-webkit-scrollbar {
    width: 8px !important;
    height: 8px !important;
}
.tool-scope ::-webkit-scrollbar-track {
    background: rgba(15, 23, 42, 0.2) !important;
    border-radius: 4px !important;
}
html:not(.dark) .tool-scope ::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.06) !important;
}
.tool-scope ::-webkit-scrollbar-thumb {
    background: rgba(34, 211, 238, 0.35) !important;
    border-radius: 4px !important;
}
html:not(.dark) .tool-scope ::-webkit-scrollbar-thumb {
    background: rgba(14, 116, 144, 0.35) !important;
}
.tool-scope ::-webkit-scrollbar-thumb:hover {
    background: var(--accent-cyan) !important;
}
.tool-scope * {
    scrollbar-width: thin !important;
    scrollbar-color: rgba(34, 211, 238, 0.35) rgba(15, 23, 42, 0.2) !important;
}

/* ============================================================ */
/* Open dropdown vs the fixed dock                              */
/* ============================================================ */
/* The dock sits at z-index 999 on <body>; the menu at z-index 60 inside main.tool-scope,
   whose backdrop-filter makes it a stacking context. A child cannot paint outside its
   own stacking context however high its z-index, so no z-index on the menu can ever put
   it above the dock -- measured with elementFromPoint, the dock was the topmost element
   over the menu's lower half. Standing the dock down while a menu is open is the only
   fix that does not involve moving the menu out of the tool area in JS, and it costs
   nothing: you are choosing from a list, not using the dock. */
body:has(.tool-scope .rnd-select.is-open) .mobile-dock {
    opacity: 0 !important;
    pointer-events: none !important;
}

/* ============================================================ */
/* Toasts                                                       */
/* ============================================================ */
/* csv-to-json and password-generator hide their toast by translating it off the top
   of the screen -- `top: 2rem; transform: translateY(-100px)` -- with no opacity or
   visibility involved. That only works while position:fixed means viewport-relative,
   and here it does not: main.tool-scope carries backdrop-filter, and a backdrop-filter
   makes an element the containing block for its fixed descendants. So `top: 2rem` is
   measured from the tool area (530px down the page) and the -100px never reaches the
   top of anything: 530 + 32 - 100 = 462, which is where the toast sat permanently,
   parked across the body copy reading "SUCCESS: JSON Copied to Clipboard!" before
   anything had been copied.
   Hiding by opacity and visibility cannot be undone by a containing block, so this
   holds whatever an ancestor does. */
.tool-scope .toast {
    transition: transform .5s cubic-bezier(.175,.885,.32,1.275), opacity .3s ease, visibility .3s ease;
}
.tool-scope .toast:not(.show) {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}

/* ============================================================ */
/* Mobile containment                                           */
/* ============================================================ */
/* Measured on base64-encoder-decoder at a 390px viewport: the page reported a
   scrollWidth of 837px -- more than twice the screen. The chain was a .tool-group
   at 475px holding a .rnd-select at 419px, neither of which had anything telling
   it to stop. A flex or grid child defaults to min-width:auto, so it refuses to
   shrink below its content and pushes the whole row off the screen instead. */
/* Confined to narrow screens, and !important because the page CSS it has to beat is
   itself !important: base64-encoder-decoder declares
   `.tool-scope .rnd-select { min-width: 270px !important }`, which is a reasonable
   desktop minimum and an impossible one on a 390px screen once a label sits beside it.
   Desktop keeps the 270px; only the phone gets to shrink it. */
@media (max-width: 640px) {
    /* The class names differ page to page for the same row of controls -- tool-group,
       toolbar-group, control-group and so on -- so the list is broad on purpose. A
       missing name shows up as a page wider than the screen: javascript-minifier
       reported 496px on a 390px viewport purely because .toolbar-group was absent
       from this list. */
    .tool-scope :is(.tool-group, .toolbar, .toolbar-group, .toolbar-row, .control-row,
                    .control-group, .controls, .options-row, .btn-group, .input-group,
                    .field-row, .cluster) {
        min-width: 0 !important;
        max-width: 100% !important;
        flex-wrap: wrap !important;
    }
    .tool-scope :is(.rnd-select, select.dropdown-ui) {
        min-width: 0 !important;
        max-width: 100% !important;
        width: 100% !important;
    }
    .tool-scope .rnd-select-btn {
        max-width: 100% !important;
        min-width: 0 !important;
    }
    /* The menu takes min-width:100% from its trigger; once the trigger is allowed to
       shrink this follows, but clamp it to the screen so a long option label cannot
       push it back off the right edge. */
    .tool-scope .rnd-select-menu {
        max-width: calc(100vw - 1.5rem) !important;
        /* Always drop downward on a phone. The select script flips the menu above the
           trigger when it will not fit below in the viewport, which was harmless while
           rows were 22px and the menu was 92px tall. At 44px rows it is 178px, so it
           started flipping -- and upward puts it inside .panel-scroll's overflow:auto,
           which clipped the first option clean off. Dropping downward may run past the
           fold, but .panel-scroll scrolls, so the options stay reachable; being clipped
           is not recoverable. !important is deliberate: it has to beat the inline top
           the script writes. */
        top: calc(100% + 0.35rem) !important;
        bottom: auto !important;
        max-height: min(50vh, 16rem) !important;
        overflow-y: auto !important;
        /* Anchor to the trigger's right edge rather than its left. A menu takes
           min-width:100% of its trigger, so a trigger sitting near the right of the
           screen pushed its menu past the edge -- javascript-formatter overflowed by
           21px this way. Triggers are full width on a phone, so for most selects the
           two anchors are identical and this only bites where it needs to. */
        left: auto !important;
        right: 0 !important;
    }
    /* Two-word labels were breaking across two lines inside 73-128px buttons --
       "Copy Output" and "Download .css" each became two lines, and so did the
       "Minified Output" tab. Keep the label on one line and let the row it sits in
       wrap instead; a button that no longer fits moves down at its natural width
       rather than being squeezed to breaking point. */
    .tool-scope :is(button, .btn, a.btn) {
        white-space: nowrap;
    }
    .tool-scope :is(.tabs, .tab-bar, .tab-strip, .btn-row, .button-row, .actions, .action-row) {
        flex-wrap: wrap !important;
        min-width: 0 !important;
    }
}
/* The trigger holds the selected label, which can be long ("Version 4 (Random) -
   Recommended"). Let it ellipsize rather than set the row's width. */
.tool-scope .rnd-select-value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* ============================================================ */
/* Touch targets                                                */
/* ============================================================ */
/* Only on coarse pointers: 44px is a finger minimum, and applying it to a mouse
   viewport just inflates compact desktop controls. */
/* A 22px option row is cramped with a mouse too, not just a thumb, so the comfortable
   floor is unconditional and the finger-sized one is layered on top below. */
.tool-scope .rnd-select-opt {
    min-height: 36px;
    display: flex;
    align-items: center;
}

/* Deliberately a media query LIST, which means OR. Scoping this to (pointer: coarse)
   alone was wrong: it only matches real touch hardware or an emulated device, so a
   desktop browser dragged narrow -- which is how these pages actually get checked --
   matched none of it and kept 22px rows and 42px buttons however narrow it got. */
@media (pointer: coarse), (max-width: 640px) {
    /* !important because pages set their own floors just under the mark and win on
       specificity -- base64-encoder-decoder pins #btnBrowse and #btnClear to
       min-height:42px from an id selector, which no amount of cascade order beats. */
    .tool-scope :is(button, .btn, a.btn, input[type="button"], input[type="submit"], .rnd-select-btn) {
        min-height: 44px !important;
    }
    .tool-scope .rnd-select-opt {
        min-height: 44px !important;
    }
    .tool-scope input[type="checkbox"]:not(.theme-switch) {
        width: 1.5rem;
        height: 1.5rem;
    }
    /* A checkbox is usually the smallest thing on the page and the label beside it
       is the obvious place to grow the hit area, since tapping it toggles anyway. */
    .tool-scope label:has(> input[type="checkbox"]) {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }
}

/* ============================================================ */

/* Highlighted editor (built by editor-enhance.js)              */

/* ============================================================ */

/* The overlay editor is a grid: a line-number gutter, a <pre> painting the coloured

   code, and the real <textarea> stacked on top with transparent text and a visible

   caret. Ten dev-tools pages had a bare textarea with nothing for CSS to colour; this

   is the layer that makes the script's output render. Taken from

   base64-encoder-decoder, which already had it working. */
        .tool-scope .rnd-hl-wrap {
            position: relative !important;
            display: grid !important;
            flex: 1 !important;
            height: 100% !important;
            width: 100% !important;
            min-height: 0 !important;
            overflow: hidden !important;
        }
        .tool-scope .rnd-hl-wrap > .rnd-hl,
        .tool-scope .rnd-hl-wrap > .rnd-hl-input {
            grid-area: 1 / 1 / 2 / 2 !important;
            margin: 0 !important;
            width: 100% !important;
            height: 100% !important;
            font: inherit !important;
            box-sizing: border-box !important;
        }
        .tool-scope .rnd-hl-has-gutter {
            grid-template-columns: 3.5rem 1fr !important;
        }
        .tool-scope .rnd-hl-has-gutter > .rnd-hl-gutter {
            grid-area: 1 / 1 / 2 / 2 !important;
            overflow: hidden !important;
            text-align: right !important;
            border-right: 1px solid var(--border-light) !important;
            background: transparent !important;
            padding-right: 0.5rem !important;
            user-select: none !important;
            white-space: pre !important;
            word-wrap: normal !important;
            color: var(--text-muted) !important;
        }
        .tool-scope .rnd-hl-has-gutter > .rnd-hl,
        .tool-scope .rnd-hl-has-gutter > .rnd-hl-input {
            grid-area: 1 / 2 / 2 / 3 !important;
            white-space: pre !important;
            word-wrap: normal !important;
        }
        .tool-scope .rnd-hl {
            pointer-events: none !important;
            overflow: hidden !important;
            background: transparent !important;
            z-index: 0 !important;
        }
        .tool-scope .rnd-hl code {
            font: inherit; white-space: inherit; display: block;
            color: var(--text-main);
        }
        .tool-scope .rnd-hl-input.rnd-hl-input {
            position: relative !important;
            z-index: 1 !important;
            overflow-y: auto !important;
            overflow-x: auto !important;
            background: transparent !important;
            color: transparent !important;
            -webkit-text-fill-color: transparent;
            caret-color: var(--accent-cyan);
        }
        .rnd-hl-input::selection { -webkit-text-fill-color: transparent; background: rgba(34,211,238,0.28); }

/* ============================================================ */
/* Overlay editors that are not .rnd-hl                         */
/* ============================================================ */
/* Six pages already had working syntax colouring built the same way: an
   [aria-hidden="true"] <pre> or <div> painting coloured tokens, with the real
   <textarea> stacked on top rendering its text transparent so the colours show
   through. They just do not use the .rnd-hl class names.

   The glass-input rule near the top of this file exempts .rnd-hl-input and nothing
   else, so rolling patch.css out to all 33 pages gave those textareas an opaque
   colour and a translucent background -- which hid the coloured layer completely
   and turned working editors into flat white text. Measured on json-formatter:
   webkitTextFillColor was rgba(0,0,0,0) without this stylesheet and
   rgb(249,250,251) with it.

   Keyed on the overlay itself rather than on class names, because the six pages
   spell it six ways: highlight-overlay, editor-backdrop, editor-highlight-layer,
   and three with no class at all. An aria-hidden pre/div immediately followed by a
   textarea is the pattern, and it is specific enough not to catch anything else. */
/* :not(.rnd-hl-input) is here purely for specificity: the glass-input rule scores
   (0,3,2) thanks to its own :not() chain, and without this the background and
   colour declarations below lose to it even with !important. */
.tool-scope :is(pre, div)[aria-hidden="true"] + textarea:not(.rnd-hl-input) {
    background: transparent !important;
    color: transparent !important;
    -webkit-text-fill-color: transparent !important;
    caret-color: var(--accent-cyan, #22d3ee) !important;
    /* The glass rule also puts backdrop-filter: blur(8px) on this textarea, and the
       thing directly behind it is the coloured layer -- so the blur was applied to the
       code itself, which came out fuzzy and washed out once the text above it went
       transparent. Same for the inset shadow, which shaded the top of the first line. */
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    box-shadow: none !important;
}
.tool-scope :is(pre, div)[aria-hidden="true"] + textarea:not(.rnd-hl-input)::selection {
    -webkit-text-fill-color: transparent;
    background: rgba(34, 211, 238, 0.28);
}

/* ============================================================ */
/* Overlay editor: caret vs painted text                        */
/* ============================================================ */
/* Pages bump form controls to 16px below 640px so iOS does not zoom the page on
   focus -- a good rule that targets `textarea` and leaves everything else alone. In an
   overlay editor the mirror is a <div> or <pre>, so it keeps its own 14px while the
   textarea jumps to 16px. The caret is drawn by the textarea and the visible text by
   the mirror, so they start together on line one and drift further apart with every
   line: measured on json-formatter, 16px/24px against 14px/21px.
   The .rnd-hl editors are immune because their script copies font metrics onto the
   <pre> at runtime; these six pages have no such script, so pin both layers here.
   Both declarations must stay identical -- that is the whole point. */
@media (max-width: 640px) {
    .tool-scope :is(pre, div)[aria-hidden="true"],
    .tool-scope :is(pre, div)[aria-hidden="true"] + textarea:not(.rnd-hl-input) {
        font-size: 16px !important;
        line-height: 1.5 !important;
    }
    /* Borders must match too, and they disagree in both directions: the glass rule puts
       1px on the textarea that the mirror lacks, while regex-tester puts 1px on the
       mirror that its textarea lacks. Either way the two layers are offset by a pixel.
       Zero on both -- the visible frame around these editors is drawn by the wrapper,
       not by either layer. */
    .tool-scope :is(pre, div)[aria-hidden="true"],
    .tool-scope :is(pre, div)[aria-hidden="true"] + textarea:not(.rnd-hl-input) {
        border: 0 !important;
    }
}
