        /* ==========================================================================
           #P  Tool kit — the instruments
           --------------------------------------------------------------------------
           A room off the sidebar, drawn by public/29a-toolkit.js. Built 2026-09-07.

           Takes the Rooms-off-Home head: one sticky bar, Back at the left, the title in
           print caps, nothing at the right — there is no act to put there.

           THIS SURFACE HAS NO MAGENTA, and the absence is the point. Magenta belongs to
           acts that change the record; nothing here changes anything, so there is not a
           single stroke of it on the page. An instrument is read, not signed.

           The whole page is entries: a print-caps label, a ruled line, and what the line
           reads. Every line is one ruling pitch tall, so the three plates stack as one
           continuously ruled sheet rather than three cards floating on a ground — the
           Plate-Not-Float Rule, and the reason there is no radius and no shadow anywhere
           below.
           ========================================================================== */
        #toolkitPage {
            background: var(--log-stock);
        }

        #toolkitPage.active {
            display: flex;
            flex-direction: column;
            height: 100vh;
            height: 100dvh;
            min-height: 0;
            /* A hidden box can still be scrolled by a focused field, which pushes the head
               off the screen — the fault the Boswell page had, and the friends page after
               it. Three fields live on this page, so it matters here too. */
            overflow: clip;
        }

        /* ---- the head ------------------------------------------------------------ */

        /* The head, its title and Back are the room head (.room-bar, css/11-home.css, since
           2026-09-16). What is this room's own: the page is a column with its own scroller,
           so the head must not shrink into it. */
        #toolkitPage .tk-bar {
            flex: none;
        }

        /* The tool kit's in-page words, in Back's word. */
        #toolkitPage .tk-act {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            text-decoration: underline;
            text-underline-offset: 0.25em;
            text-decoration-thickness: 1px;
            background: none;
            border: none;
            padding: 0;
            cursor: pointer;
            color: var(--log-ink);
            display: inline-flex;
            align-items: center;
            min-height: 44px;
        }

        /* ---- the sheet ----------------------------------------------------------- */

        #toolkitPage .tk-body {
            flex: 1;
            min-height: 0;
            display: flex;
            flex-direction: column;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
            /* The Ruled-To-The-Foot Rule: what is left below the last instrument is ruled
               stock, not a different ground. */
            padding-bottom: calc(var(--sp-2xl) + env(safe-area-inset-bottom, 0px));
        }

        /* An instrument's heading band, in the sheet's own band colour — the same device
           the Register uses to separate its plates. */
        #toolkitPage .tk-plate-label {
            margin: 0;
            /* The band carries the instrument's name at the left and, where there is one,
               the act that reconfigures it at the right. Swap lived on a ruled line of its
               own in the first draft — a rule drawn round an empty entry, which is not
               what a rule means on this sheet. */
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: var(--sp-sm);
            padding: var(--sp-xs) var(--sp-lg);
            background: var(--log-stock-band);
            border-bottom: 1px solid var(--log-rule-firm);
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--log-ink);
        }

        /* Only a band that follows another plate takes a top rule; the first sits under
           the head's own, and doubling them would print a two-pixel rule nothing else on
           the sheet has. There was a `:first-child { border-top: none }` here to say so,
           cancelling a border no rule ever set. */
        #toolkitPage .tk-plate + .tk-plate .tk-plate-label { border-top: 1px solid var(--log-rule-firm); }

        /* ---- an entry line -------------------------------------------------------- */

        /* One ruling pitch, a written value at the left and its stamp at the right. This
           is the Register's entry row, and it is the whole grammar of this page. */
        #toolkitPage .tk-line {
            display: grid;
            grid-template-columns: 1fr auto;
            align-items: center;
            gap: var(--sp-sm);
            min-height: var(--log-row);
            padding: 0 var(--sp-lg);
            border-bottom: 1px solid var(--log-rule);
        }

        /* Focus is said the way every writing line in this world says it: the band ground
           and a two-pixel ink baseline, no ring and no glow — Ink-Not-Glow. */
        #toolkitPage .tk-line:focus-within {
            background: var(--log-stock-lit, #DEE4E2);
            box-shadow: inset 0 -2px 0 0 var(--log-ink);
        }

        #toolkitPage .tk-in {
            min-width: 0;
            min-height: 44px;
            padding: 0;
            border: none;
            background: transparent;
            font-family: var(--log-write);
            font-size: var(--fs-lg);
            color: var(--log-ink);
            caret-color: var(--log-ink);
            -webkit-appearance: none;
            appearance: none;
        }
        #toolkitPage .tk-in:focus-visible { outline: none; }

        /* What the instrument reads back. The same size as what was typed, because they
           are the same fact said twice — making the answer larger would suggest the
           question was the smaller half of it. */
        #toolkitPage .tk-out {
            font-family: var(--log-write);
            font-size: var(--fs-lg);
            color: var(--log-ink);
            font-variant-numeric: tabular-nums;
        }
        #toolkitPage .tk-out.is-blank { color: var(--log-ink-soft); }

        /* The read line carries the firm rule: it is the answer, and the firm weight is
           what this world uses to say a line means something rather than merely divides. */
        #toolkitPage .tk-line.is-reading { border-bottom-color: var(--log-rule-firm); }

        /* The unit, stamped rather than written — it is what the form says, not what the
           traveller put in. */
        #toolkitPage .tk-unit,
        #toolkitPage .tk-clock-label {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-ink-soft);
            white-space: nowrap;
        }

        /* ---- the pickers ----------------------------------------------------------

           The currency menu is the component the expense form, the edit form, the activity
           form and the budget all use: same markup, same search row, same Enter-to-pick,
           and the app's own outside-click handler closes it because the class names are
           the ones it looks for. Only the dressing is this room's.

           It has to be dressed, though. The component's own colours are the old world's —
           #FFFFFF ground, brown accent, the browser's blue selection — and a native select
           before it was worse still: a narrow white rectangle with a system-blue bar down
           the middle, sitting on a ruled chart. What follows is the same control in the
           one ink.
           ---------------------------------------------------------------------------- */

        #toolkitPage .tk-pick {
            position: relative;
            display: inline-flex;
            justify-content: flex-end;
        }

        /* The trigger: a stamped code with the underline that means it can change. No
           dropdown arrow — this world has no glyphs, and the underline already says it. */
        #toolkitPage .category-selector.tk-code {
            display: inline-flex;
            align-items: center;
            justify-content: flex-end;
            min-height: 44px;
            padding: 0 0 0 var(--sp-xs);
            border: none;
            border-radius: 0;
            background: none;
            box-shadow: none;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-ink);
            text-decoration: underline;
            text-underline-offset: 0.25em;
            text-decoration-thickness: 1px;
            cursor: pointer;
        }
        #toolkitPage .category-selector.tk-code:focus-visible {
            outline: 2px solid var(--log-ink);
            outline-offset: 2px;
        }

        /* The panel. Hung from the right edge of the code rather than stretched between
           the cell's own sides, which is what made the first attempt a column two letters
           wide: the positioned ancestor was the width of "AUD". */
        #toolkitPage .currency-dropdown.tk-menu {
            position: absolute;
            top: calc(100% - 6px);
            right: 0;
            left: auto;
            box-sizing: border-box;
            min-width: 13rem;
            max-width: 78vw;
            background: var(--log-stock);
            border: 1px solid var(--log-rule-firm);
            border-radius: 0;
            margin: 0;
            box-shadow: none;
            text-align: left;

            /* Closed. The height is FIXED and the reveal is a fade and a short fall — not
               the max-height the component animates elsewhere. Animating a height relays
               out everything inside it on every frame, and inside this are a hundred and
               fifty-five ruled rows; on a phone that is the difference between a menu that
               opens and a menu that stutters. Opacity and transform are the compositor's
               work and cost the rows nothing.

               The movement is kept rather than dropped: a panel that appears without moving
               reads as a mis-paint. `visibility` is what makes it untouchable while closed,
               and it is switched at the end of the fade out and the start of the fade in, so
               it never eats a tap that belongs to the sheet behind it. */
            max-height: 19rem;
            overflow: hidden;
            opacity: 0;
            visibility: hidden;
            transform: translateY(-6px);
            transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
            z-index: 2000;
        }
        #toolkitPage .currency-dropdown.tk-menu.active {
            opacity: 1;
            visibility: visible;
            transform: none;
            transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }

        /* Somebody who has asked for less movement gets none of it, and still gets the
           panel — the fade is decoration, the visibility is the control. */
        @media (prefers-reduced-motion: reduce) {
            #toolkitPage .currency-dropdown.tk-menu,
            #toolkitPage .currency-dropdown.tk-menu.active {
                transform: none;
                transition: opacity 0.01s linear, visibility 0s;
            }
        }

        /* The search row. A hundred and sixty codes are not scrolled, they are typed —
           which is the whole reason this component exists and the whole reason a native
           select was the wrong borrowing. Written in the writing voice, on the band, with
           the ink baseline this world gives every writing line. */
        #toolkitPage .tk-menu .cur-search {
            position: sticky;
            top: 0;
            z-index: 1;
            padding: 0 var(--sp-sm);
            background: var(--log-stock-band);
            border-bottom: 1px solid var(--log-rule-firm);
        }
        #toolkitPage .tk-menu .cur-search-input {
            width: 100%;
            box-sizing: border-box;
            min-height: 44px;
            padding: 0;
            border: none;
            border-radius: 0;
            background: transparent;
            font-family: var(--log-write);
            font-size: var(--fs-body);
            letter-spacing: normal;
            text-transform: none;
            color: var(--log-ink);
            caret-color: var(--log-ink);
        }
        #toolkitPage .tk-menu .cur-search-input::placeholder { color: var(--log-ink-soft); }
        #toolkitPage .tk-menu .cur-search:focus-within { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #toolkitPage .tk-menu .cur-search-input:focus-visible { outline: none; border: none; }

        /* One code, one ruled line, at the sheet's own pitch — the panel is a small ruled
           page, not a floating list. */
        #toolkitPage .tk-menu .currency-option {
            display: flex;
            align-items: center;
            min-height: 40px;
            padding: 0 var(--sp-sm);
            border-bottom: 1px solid var(--log-rule);
            background: none;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-ink);
            cursor: pointer;
        }
        #toolkitPage .tk-menu .currency-option:last-child { border-bottom: none; }
        /* The pointer says which line it is on with the band ground, not a blue bar.
           Hover only: the options are divs the shared component writes with no tabindex, so
           nothing can focus one — the keyboard route to a code is the search row and Enter,
           which is the route worth having anyway. A `:focus-visible` rule stood here
           styling a state that cannot occur. */
        #toolkitPage .tk-menu .currency-option:hover {
            background: var(--log-stock-band);
        }

        #toolkitPage .tk-menu .cur-empty {
            padding: var(--sp-sm);
            font-family: var(--log-write);
            font-size: var(--fs-small);
            text-transform: none;
            letter-spacing: normal;
            color: var(--log-ink-soft);
        }

        /* The browser's own selection colour is the last piece of another world on this
           page — it lands on the codes as somebody drags across them while typing. */
        #toolkitPage .tk-menu ::selection { background: var(--log-stock-band); color: var(--log-ink); }

        /* ---- swap ----------------------------------------------------------------- */

        /* On the band, at the right. It is an act on the instrument, not on the record —
           ink, never magenta, on this page as on every line of it. The band's own height
           is set by the label, so the tap target is widened rather than made taller. */
        /* The one exception on the page: ADD A PLACE takes the magenta, as every add does (owner, 2026-09-17: 打开表单算写记录，删除统一用品红).
           DONE, the same button once the adder is open, goes back to the ink. */
        #toolkitPage .tk-plate-label .tk-act.is-record { color: var(--log-magenta); }
        #toolkitPage .tk-plate-label .tk-act {
            min-height: 28px;
            padding: 0 0 0 var(--sp-md);
        }
        /* Money's band carries two words once a rate has failed: Try again, then Swap. */
        #toolkitPage .tk-plate-acts {
            display: inline-flex;
            align-items: center;
        }

        /* The Ruled-To-The-Foot Rule: what is left of the sheet below the last entry is
           ruled stock at the same pitch, not a blank ground. The same device as the
           sidebar's own foot, and the reason this page never reads as three cards
           floating on something else. */
        #toolkitPage .tk-rule-out {
            flex: 1;
            min-height: calc(var(--log-row) * 2);
            background-image: repeating-linear-gradient(to bottom,
                transparent 0,
                transparent calc(var(--log-row) - 1px),
                var(--log-rule) calc(var(--log-row) - 1px),
                var(--log-rule) var(--log-row));
        }

        /* ---- the note under an instrument ----------------------------------------- */

        /* What the reading is worth: the rate and the day it was published, the difference
           in hours, or the reason there is no answer. The softer pressure of the one ink,
           which is this world's whole hierarchy. */
        #toolkitPage .tk-note {
            margin: 0;
            padding: var(--sp-xs) var(--sp-lg) var(--sp-sm);
            font-family: var(--log-write);
            font-size: var(--fs-small);
            line-height: 1.45;
            color: var(--log-ink-soft);
        }

        /* ---- the clocks ----------------------------------------------------------- */

        /* `.tk-zone` and `.is-ask` were here until the Time instrument stopped asking
           which zone home is on. The profile already holds where the traveller lives and
           a city knows its own clock, so the question — and the six-hundred-name select
           that carried it — went. */
        #toolkitPage .tk-line.is-clock { grid-template-columns: minmax(0, auto) 1fr; }

        /* Who the clock belongs to, and — on a place the traveller added by hand — the
           word that takes it off again. Stacked, so the left of the row balances the time
           and its note on the right rather than sitting alone on one line. */
        #toolkitPage .tk-clock-who {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            gap: 1px;
            min-width: 0;
        }
        #toolkitPage .tk-clock-who .tk-clock-label {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            max-width: 44vw;
        }
        /* Remove is an act on the instrument, not on the record — ink, never magenta, and
           set at the micro floor so it sits under the name without competing with it. */
        /* Remove sits between two ruled rows, so its box cannot grow without pushing them
           apart — but a twenty-pixel target on a phone is not a target. The padding widens
           and deepens the tap area while the negative margin keeps the line where the
           ruling put it, which is the trick this codebase already uses to bring small
           words up to a reachable size without disturbing the pitch. */
        #toolkitPage .tk-act.is-small {
            min-height: 0;
            padding: 12px 12px 12px 0;
            margin: -12px -12px -12px 0;
            font-size: var(--fs-micro);
            letter-spacing: 0.1em;
            color: var(--log-ink-soft);
        }

        /* ---- adding a place --------------------------------------------------------- */

        /* The search line and its suggestions, hidden until asked for. It is the app's own
           places autocomplete — the same one the "Lives in" field and every stop uses — so
           the list that drops out of it is dressed here rather than rebuilt. */
        #toolkitPage .tk-adder {
            border-bottom: 1px solid var(--log-rule-firm);
        }
        #toolkitPage .tk-in.is-search {
            font-size: var(--fs-body);
        }
        #toolkitPage .tk-in.is-search::placeholder { color: var(--log-ink-soft); }

        #toolkitPage .tk-suggest:empty { display: none; }
        #toolkitPage .tk-suggest {
            background: var(--log-stock);
        }
        /* The generic autocomplete writes its own rows; they are ruled to this sheet's
           pitch and set in the writing voice, because a place name is what somebody typed
           and not what the form stamped. */
        #toolkitPage .tk-suggest > * {
            display: flex;
            align-items: center;
            min-height: 44px;
            padding: 0 var(--sp-lg);
            border-bottom: 1px solid var(--log-rule);
            background: none;
            font-family: var(--log-write);
            font-size: var(--fs-body);
            color: var(--log-ink);
            cursor: pointer;
        }
        #toolkitPage .tk-suggest > *:hover { background: var(--log-stock-band); }

        #toolkitPage .tk-clock {
            justify-self: end;
            display: flex;
            flex-direction: column;
            align-items: flex-end;
            gap: 1px;
            min-width: 0;
        }

        /* A clock that has nothing to say takes the soft pressure, the same as a reading
           that has nothing to say. It is not an error and is not marked as one. */
        #toolkitPage .tk-clock-time.is-blank { color: var(--log-ink-soft); }

        #toolkitPage .tk-clock-time {
            font-family: var(--log-write);
            font-size: var(--fs-lg);
            line-height: 1.1;
            color: var(--log-ink);
            font-variant-numeric: tabular-nums;
        }

        #toolkitPage .tk-clock-where {
            font-family: var(--log-write);
            font-size: var(--fs-small);
            line-height: 1.2;
            color: var(--log-ink-soft);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            max-width: 62vw;
        }

        /* ---- the measures ---------------------------------------------------------- */

        /* The five words, the same grammar as the friends page's filters: the underline
           says which one is being read, and there is no second colour to say it with. */
        #toolkitPage .tk-words {
            display: flex;
            flex-wrap: wrap;
            gap: 0 var(--sp-md);
            padding: 0 var(--sp-lg);
            border-bottom: 1px solid var(--log-rule);
        }

        #toolkitPage .tk-word {
            min-height: 40px;
            padding: 0;
            border: none;
            background: none;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-ink-soft);
            cursor: pointer;
        }
        #toolkitPage .tk-word.is-on {
            color: var(--log-ink);
            text-decoration: underline;
            text-underline-offset: 0.25em;
            text-decoration-thickness: 1px;
        }
