
        /* ══════════════════════════════════════════════════════════════
           MOVED OUT OF css/04-legacy-forms.css · 2026-09-21  (prepended)
           12 rules. DESIGN.md: a surface's rules go in that surface's part, and the
           legacy parts only shrink.
           ⚠️ 04-legacy-forms.css loaded BEFORE this file. Placing them
           at the head keeps their order against THIS PART’S OWN rules — and nothing else.
           Against the parts BETWEEN #37 and #3 the order is reversed by this move, and
           whether that matters was a separate question somebody had to answer. See DESIGN.md.
           ══════════════════════════════════════════════════════════════ */
        /* 选择器去掉 .card4b .bp-fold 限定：那两个类只在选定类别后才挂上，
           未选类别时这条规则根本不匹配，#costPreview 会继承父级的 16px。
           原来的内联 style="font-size:15px" 就是在补这个空档，而 CSS 侧
           又得加 !important 才压得过内联 —— 一处标记里的缺口，同时制造了
           一个内联样式和一个 !important。金额换算提示是从属数值，
           两种状态下都该是 13px。 */
        #costPreview { margin-top: 8px; margin-bottom: 16px; font-family: var(--log-write);
            font-size: 13px; color: var(--log-ink-soft); letter-spacing: 0.02em; }

        /* Add/Edit card width — fill the sheet content area so all category cards match */
        #addActivityModal .modal-body { width: 100%; }

        /* Expanded Notes modal — paper theme instead of the default grey panel */
        #sightsNotesExpandModal .modal-content {
            background: var(--log-stock); border-radius: 0;
            overflow: hidden;
            /* 批次 07：悬浮（模态）阴影删除，补 1px 实线边框接替。底色已是不透明 --surface-sheet。 */
            border: 1px solid var(--log-rule-firm);
        }

        #sightsNotesExpandModal .modal-header { display: none; }

        #sightsNotesExpandModal .modal-content { position: relative; }

        
        #sightsNotesExpandModal .modal-title {
            color: #F4F2EC; font-family: var(--log-write);
            font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 600;
        }

        #sightsNotesExpandModal .modal-close { color: rgba(244,242,236,0.8); }

        #sightsNotesExpandModal .modal-close:hover { color: #fff; }

        #sightsNotesExpandModal .tiptap-editor-container { background: var(--log-stock); border: 1px solid var(--log-rule-firm); border-radius: 0; }

        #sightsNotesExpandModal #sightsNotesEditorGroup { border: none; }

        #sightsNotesExpandModal .rich-text-toolbar { background: #EFEBE2; border: 1px solid var(--log-rule-firm); border-bottom: none; border-radius: 0; }

        /* Booking Ref | Already Booked side by side, Notes on its own row below */

        .already-booked-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
        }


        /* ══════════════════════════════════════════════════════════════
           MOVED OUT OF css/09-modal.css · 2026-09-21  (prepended)
           2 rules. DESIGN.md: a surface's rules go in that surface's part, and the
           legacy parts only shrink.
           ⚠️ 09-modal.css loaded BEFORE this file. Placing them
           at the head keeps their order against THIS PART’S OWN rules — and nothing else.
           Against the parts BETWEEN #38 and #8 the order is reversed by this move, and
           whether that matters was a separate question somebody had to answer. See DESIGN.md.
           ══════════════════════════════════════════════════════════════ */
        /* Add/Edit Activity: the category card IS the sheet — drop the modal's own panel
           background and header so it isn't a card-inside-a-card. Each category card carries
           its own header + Save/Cancel, so no separate close chrome is needed. */
        #addActivityModal .modal-content { background: transparent; box-shadow: none; }

        #addActivityModal .modal-header { display: none; }


        /* ══════════════════════════════════════════════════════════════
           MOVED OUT OF css/10-legacy-home-sheet.css · 2026-09-21  (prepended)
           4 rules. DESIGN.md: a surface's rules go in that surface's part, and the
           legacy parts only shrink.
           ⚠️ 10-legacy-home-sheet.css loaded BEFORE this file. This placement keeps
           their order against THIS PART’S OWN rules and nothing else: against the 29 part(s)
           between #10 and #40 the move reverses it. The banner used to claim they "keep that
           place" full stop, which was never true (review, 2026-09-22). Checked separately.
           ══════════════════════════════════════════════════════════════ */
        /* Sights' TipTap toolbar is self-contained (own full border) rather than the
           "open bottom, closed by the editor below" style the old execCommand toolbar
           uses elsewhere — the editor content below it is intentionally borderless so
           it blends with the surrounding section instead of reading as a nested box. */
        #sightsTipTapToolbar {
            border: none;
            border-top: 1px solid var(--log-rule);
            border-bottom: 1px solid var(--log-rule);
        }

        /* In the expanded modal, the editor group runs edge-to-edge to match the header's
           divider (see #sightsNotesExpandBody's padding), so it needs its own left/right/
           bottom border to read as a framed box — the toolbar already supplies the top
           edge via its own border-top above. */
        #sightsNotesExpandBody #sightsNotesEditorGroup {
            border-left: 1px solid var(--log-rule);
            border-right: 1px solid var(--log-rule);
            border-bottom: 1px solid var(--log-rule);
        }


        /* One rule, formerly two. They were 96 lines and a whole family apart in
           css/10-legacy-home-sheet.css and the move brought them together with nothing between,
           which is the only reason the duplication is visible at all (review, 2026-09-22). */
        #sightsNotesExpandBody .tiptap-editor-container {
            padding-left: var(--sp-lg);
            padding-right: var(--sp-lg);
            min-height: 68vh;
        }

        /* ==========================================================================
           #AH  Add and edit an activity — the ticket, being written
           ==========================================================================

           2026-09-13. The owner: add / edit activity 这里还是旧世界 之前落下的 — the last form in
           the outgoing world. Three decisions, the owner's: the form is the activity's own
           ticket made writable, as the expense form is the receipt made writable; the type is
           chosen first, because every type prints a different ticket (因为 activity display 不同
           分类有不同格式 所以我选择的 先选分类); and the flight goes first, to be looked at by
           eye before the other four follow it.

           The ticket's parts are css/17k-ticket.css, whose rules name #addActivityModal. This
           file holds only what WRITING adds to reading, and the chassis the modal needs.

           ⚠️ THE SHARED SECTIONS ARE DRESSED ONLY INSIDE THE TICKET. Booking ref, booked, cost
           and attachments are single nodes that moveSharedFormSections carries into whichever
           card is up. The transit, stay, sights and generic cards are still the outgoing world
           until their own rounds, so every rule here that reaches those sections is scoped to
           .af-tk and they keep their old dress in the old cards.

           ⚠️ EVERY RULE IS QUALIFIED BY AN ID. The legacy form files load before this one and
           the chassis files after it. */

        /* ---- lying over the phone ------------------------------------------------ */
        /* openModal pins the form to the frame at full height (is-full-frame, as the expense
           form); the ticket lies in the middle of that and scrolls inside it. */
        #addActivityModal.modal-sheet.active { align-items: stretch; padding: 0; }
        #addActivityModal .modal-content {
            width: 100%;
            max-width: none;
            height: 100%;
            max-height: 100%;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            border-radius: 0;
            box-shadow: none;
            background: transparent;
            animation: none;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }
        #addActivityModal .modal-body {
            flex: 1 1 auto;
            min-height: 0;
            width: 100%;
            margin: 0;
            padding: var(--sp-lg) 0;
            box-sizing: border-box;
            overflow-y: auto;
            overscroll-behavior: contain;
            -webkit-overflow-scrolling: touch;
        }
        #addActivityModal .af-tk { width: calc(100% - 2 * var(--sp-lg)); margin: 0 auto; }
        /* The rules that kept the outgoing world's cards in their old measure went on 2026-09-13 with the last
           of them: every card of this form is its ticket now. */

        /* ---- the head ------------------------------------------------------------ */
        /* It carries CANCEL and SAVE, so it stays at the top of the scroller. */
        #addActivityModal .af-band {
            position: sticky;
            top: calc(-1 * var(--sp-lg));
            z-index: 8;
            grid-template-columns: minmax(0, 1fr) auto;
        }
        #addActivityModal .af-acts { display: flex; align-items: center; gap: var(--sp-md); }
        #addActivityModal .af-band .tk-act.is-primary { color: var(--log-magenta); }
        /* The old row of buttons is carried into the ticket by moveSharedFormSections; the
           ticket's head already says Cancel and Save, and its foot says Remove. */
        #addActivityModal .af-tk #activityFormActions { display: none; }

        /* ---- a field that takes typing ------------------------------------------- */
        /* The receipt's field: a hairline rule at the foot of a 44px box, two pixels of ink
           while it has the cursor. The type is the part it sits in — a code, a value, a
           reference — so this names no face. */
        #addActivityModal .af-tk .af-input {
            display: block;
            width: 100%;
            min-width: 0;
            min-height: 44px;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            background: transparent;
            box-shadow: inset 0 -1px 0 0 var(--log-rule);
            outline: none;
            caret-color: var(--log-ink);
            -webkit-appearance: none;
            appearance: none;
            text-align: left;
        }
        #addActivityModal .af-tk .af-input:focus { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk .af-input::placeholder { color: var(--log-ink-soft); opacity: 1; }
        #addActivityModal .af-tk .is-right { text-align: right; }

        /* The codes are the instrument's own shorthand, set as large as the ticket prints them. */
        #addActivityModal .af-tk input.af-code {
            width: 3.6em;
            text-transform: uppercase;
        }
        #addActivityModal .af-tk .af-where {
            display: grid;
            grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
            gap: var(--sp-sm);
        }
        #addActivityModal .af-tk .af-where .af-input {
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
        }

        /* ---- the times and the days ---------------------------------------------- */
        #addActivityModal .af-tk .af-times { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-sm); }
        #addActivityModal .af-tk .af-times > div { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
        #addActivityModal .af-tk .af-times > div:last-child { align-items: flex-end; text-align: right; }

        /* A word that opens the deck log's time sheet. */
        #addActivityModal .af-tk .af-at {
            position: relative;
            display: inline-flex;
            margin: 0;
            padding: 0;
            border: none;
            border-radius: 0;
            background: none;
            cursor: pointer;
            font: inherit;
            color: inherit;
            text-align: inherit;
            align-items: center;
            min-height: 44px;
            min-width: 5.5em;
            box-shadow: inset 0 -1px 0 0 var(--log-rule-firm);
        }
        #addActivityModal .af-tk .af-times > div:last-child .af-at { justify-content: flex-end; }
        #addActivityModal .af-tk .af-at:focus-within { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk .is-unset { color: var(--log-ink-soft); }

        /* The day is the date picker's own field, showing the reader's words (data-shown). */
        #addActivityModal .af-tk input.af-day {
            display: block;
            width: 100%;
            min-height: 44px;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            background: transparent;
            box-shadow: inset 0 -1px 0 0 var(--log-rule-firm);
            outline: none;
            cursor: pointer;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
            text-align: left;
            -webkit-appearance: none;
            appearance: none;
        }
        #addActivityModal .af-tk input.af-day.is-right { text-align: right; }
        #addActivityModal .af-tk input.af-day:focus-visible { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk input.af-day::placeholder { color: var(--log-ink-soft); opacity: 1; }

        /* ---- the booking, the flight, the airline, the note ----------------------- */
        #addActivityModal .af-tk .af-field .tk-label,
        #addActivityModal .af-tk .form-label {
            display: block;
            margin: 0;
            padding: 0;
            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);
        }
        #addActivityModal .af-tk .af-field + .af-field,
        #addActivityModal .af-tk .af-pair + .af-field { margin-top: var(--sp-md); }

        #addActivityModal .af-tk .af-pair {
            display: grid;
            grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
            gap: var(--sp-md) var(--sp-lg);
        }
        #addActivityModal .af-tk .af-pair > #bookingRefSection { order: 1; }
        #addActivityModal .af-tk .af-pair > .af-flightno,
        #addActivityModal .af-tk .af-pair > .af-pair-right { order: 2; text-align: right; }
        #addActivityModal .af-tk .af-pair > #alreadyBookedSection { order: 3; grid-column: 1 / -1; }

        #addActivityModal .af-tk .form-section {
            margin: 0;
            padding: 0;
            border: none;
            background: none;
        }
        /* The booking reference, printed as the reading ticket prints it. */
        #addActivityModal .af-tk #bookingRefSection .form-input {
            display: block;
            width: 100%;
            min-height: 44px;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            background: transparent;
            box-shadow: inset 0 -1px 0 0 var(--log-rule);
            outline: none;
            font-family: var(--log-print);
            font-size: var(--fs-body);
            font-weight: 400;
            letter-spacing: 0.08em;
            font-variant-numeric: lining-nums tabular-nums;
            text-transform: none;
            color: var(--log-ink);
            caret-color: var(--log-ink);
        }
        #addActivityModal .af-tk #bookingRefSection .form-input:focus { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk #bookingRefSection .form-input::placeholder { color: var(--log-ink-soft); opacity: 1; letter-spacing: normal; }

        /* ⚠️ BOOKED IS A STAMP, NOT A SWITCH (the Stamped-State Rule). The reading ticket prints
           the state as a word in a ruled box; the form prints the same box and a press turns
           it. The checkbox is still the control — laid over the stamp — so the label, the
           keyboard and the value FormData reads are the ones they always were. */
        #addActivityModal .af-tk .already-booked-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: var(--sp-sm);
            min-height: 44px;
            margin: 0;
            padding: 0;
            border: none;
            background: none;
        }
        /* Was an inline margin on both labels in the markup; said here for every card. */
        #addActivityModal .already-booked-row .form-label { margin: 0; }
        #addActivityModal .af-tk .toggle-switch {
            position: relative;
            display: inline-flex;
            align-items: center;
            width: auto;
            height: auto;
            min-height: 44px;
            margin: 0;
            cursor: pointer;
        }
        #addActivityModal .af-tk .toggle-switch input {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            margin: 0;
            opacity: 0;
            cursor: pointer;
            z-index: 1;
        }
        #addActivityModal .af-tk .toggle-slider {
            position: static;
            display: inline-block;
            width: auto;
            height: auto;
            inset: auto;
            padding: 2px 6px;
            border: 1px solid var(--log-rule-firm);
            border-radius: 0;
            background: none;
            box-shadow: none;
            transition: none;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            white-space: nowrap;
            color: var(--log-ink-soft);
        }
        #addActivityModal .af-tk .toggle-slider::before { content: none; display: none; }
        #addActivityModal .af-tk .toggle-slider::after { content: 'Not booked'; }
        #addActivityModal .af-tk .toggle-switch input:checked + .toggle-slider { color: var(--log-ink); background: none; }
        #addActivityModal .af-tk .toggle-switch input:checked + .toggle-slider::after { content: 'Booked'; }
        #addActivityModal .af-tk .toggle-switch input:focus-visible + .toggle-slider { outline: 2px solid var(--log-ink); outline-offset: 2px; }

        #addActivityModal .af-tk textarea.af-notes {
            resize: none;
            overflow: hidden;
            line-height: 1.4;
            white-space: pre-wrap;
        }
        /* ⚠️ AN ADDRESS IS SEEN WHOLE (2026-09-13). A picked address is Google's formatted one, and one of those ran 310px in
           a 294px single-line field on the transit ticket, its end cut off. The five address fields wrap and grow a line at
           a time, as notes do; one line still sits in the 44px of the field it replaced. */
        #addActivityModal .af-tk textarea.af-address {
            resize: none;
            overflow: hidden;
            line-height: 1.4;
            padding: 12px 0;
        }

        /* ---- a sight's own furniture, being written ---------------------------------- */
        #addActivityModal .af-tk .af-daytime { display: flex; align-items: flex-start; gap: var(--sp-md); }
        /* A sight's booking has nothing beside it — the flight's shares its line with FLIGHT — so it takes
           the whole line rather than half of one with an empty half beside it. */
        #addActivityModal .af-tk #sightBpBookingRow > #bookingRefSection,
        #addActivityModal .af-tk #genericCardBookingRow > #bookingRefSection { grid-column: 1 / -1; }
        #addActivityModal .af-tk .af-daytime input.af-day { flex: 1 1 auto; min-width: 0; }
        #addActivityModal .af-tk .af-daytime .af-at { flex: none; }

        /* A word that acts, beside a field: EXPAND, ADD, DONE. */
        #addActivityModal .af-word-act,
        #sightsNotesExpandModal .af-word-act {
            flex: none;
            min-height: 44px;
            padding: 0;
            border: none;
            background: none;
            cursor: pointer;
            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;
            color: var(--log-ink);
        }
        #addActivityModal .af-word-act:disabled { color: var(--log-ink-soft); text-decoration: none; cursor: default; }
        /* ADD beside the links: every add is magenta (owner, 2026-09-17: 打开表单算写记录，删除统一用品红). EXPAND and DONE stay ink. */
        #addActivityModal #sightseeingAddLinkBtn:not(:disabled) { color: var(--log-magenta); }

        #addActivityModal .af-tk .af-notes-box,
        #addActivityModal .af-tk .af-links-box { margin: 0; padding: 0; border: none; background: none; }
        #addActivityModal .af-tk .af-notes-head { display: flex; align-items: center; justify-content: space-between; }
        #addActivityModal .af-quiet {
            padding: var(--sp-xs) 0;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            font-style: normal;
            color: var(--log-ink-soft);
        }

        /* ⚠️ THE NOTES' ROW OF MARKS IS A FORMATTING RACK, dressed as the journal editor's is (see
           css/17q-editor.css): the one place this world keeps marks, because B is bold and three ruled
           lines are a list. One ink, square ends, a name on every one. */
        #addActivityModal .af-rack,
        #sightsNotesExpandModal .af-rack {
            display: flex;
            align-items: center;
            /* No gap: each mark is a 44px square and its own spacing. With a gap the five marks and two
               rules asked for more than the ticket's measure and shrank to 39px, 36px at 375. */
            gap: 0;
            margin: var(--sp-2xs) 0 0;
            padding: 0 var(--sp-sm);
            border: none;
            border-radius: 0;
            background: var(--log-stock-band);
            flex-wrap: nowrap;
        }
        #addActivityModal .af-rack .rich-text-btn,
        #sightsNotesExpandModal .af-rack .rich-text-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 44px;
            height: 44px;
            flex: none;
            padding: 0;
            border: none;
            border-radius: 0;
            background: none;
            transition: none;
            cursor: pointer;
            color: var(--log-ink);
            font-family: var(--log-print);
            font-size: var(--fs-small);
        }
        #addActivityModal .af-rack .rich-text-btn.active,
        #sightsNotesExpandModal .af-rack .rich-text-btn.active { background: none; color: var(--log-ink); box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-rack .rich-text-btn:active,
        #sightsNotesExpandModal .af-rack .rich-text-btn:active { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-rack .rich-text-btn svg,
        #sightsNotesExpandModal .af-rack .rich-text-btn svg { display: block; width: 16px; height: 16px; }
        #addActivityModal .af-rack .rich-text-sep,
        #sightsNotesExpandModal .af-rack .rich-text-sep { width: 1px; height: 16px; margin: 0; background: var(--log-rule); }
        #addActivityModal .af-tk .tiptap-editor-container,
        #sightsNotesExpandModal .tiptap-editor-container {
            min-height: 88px;
            padding: 0;
            background: transparent;
            box-shadow: inset 0 -1px 0 0 var(--log-rule);
            font-family: var(--log-write);
            font-size: var(--fs-body);
            line-height: 1.45;
            color: var(--log-ink);
        }
        #addActivityModal .af-tk .tiptap-content,
        #sightsNotesExpandModal .tiptap-content { outline: none; min-height: 88px; padding: var(--sp-xs) 0; }
        #addActivityModal .af-tk .tiptap-content p,
        #sightsNotesExpandModal .tiptap-content p { margin: 0 0 0.5em; }
        #addActivityModal .af-tk .tiptap-content ul, #addActivityModal .af-tk .tiptap-content ol,
        #sightsNotesExpandModal .tiptap-content ul, #sightsNotesExpandModal .tiptap-content ol { margin: 0 0 0.5em; padding-left: 1.3em; }
        #addActivityModal .af-tk .tiptap-content strong,
        #sightsNotesExpandModal .tiptap-content strong { font-weight: 600; color: var(--log-ink); }
        #addActivityModal .af-tk .tiptap-content h2,
        #sightsNotesExpandModal .tiptap-content h2 {
            font-family: var(--log-print);
            font-size: var(--fs-small);
            font-weight: 600;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            color: var(--log-ink);
        }

        #addActivityModal .af-tk .af-link-add { display: flex; align-items: center; gap: var(--sp-md); }
        #addActivityModal .af-tk .af-link-add .af-input { flex: 1 1 auto; }
        #addActivityModal .af-tk .af-link { align-items: center; }
        #addActivityModal .af-tk .af-link .tk-link-body { flex: 1 1 auto; }
        #addActivityModal .af-tk .af-link .tk-link-title { text-decoration: none; }

        /* The larger sheet for the notes: the log's stock, a head that says NOTES and DONE. */
        #sightsNotesExpandModal.modal.active { display: flex; align-items: stretch; justify-content: center; padding: 0; z-index: 1100; background: rgba(22, 25, 26, 0.42); }
        #sightsNotesExpandModal .modal-content {
            position: relative;
            width: 100%;
            max-width: 600px;
            height: 100%;
            max-height: none;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            box-shadow: none;
            background: var(--log-stock);
            color: var(--log-ink);
        }
        #sightsNotesExpandModal .af-expand-band {
            flex: none;
            display: flex;
            align-items: center;
            justify-content: space-between;
            min-height: var(--log-row);
            padding: 0 var(--sp-lg);
            background: var(--log-stock-band);
            border-bottom: 1px solid var(--log-rule-firm);
        }
        #sightsNotesExpandModal .af-expand-title {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            color: var(--log-ink);
        }
        #sightsNotesExpandModal #sightsNotesExpandBody { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 var(--sp-lg) var(--sp-lg); }
        #sightsNotesExpandModal #sightsNotesEditorGroup { border: none; }
        /* The old sheet framed the editor in a box (04-legacy-forms.css, deleted 2026-09-24, named a border on it). No foot rule here either,
           though every field on the ticket has one: this editor is held open at 60vh, so its rule was drawn across the
           middle of the sheet under a line or two of writing. The sheet is the page, and its foot is the screen's. */
        #sightsNotesExpandModal .tiptap-editor-container { border: none; border-radius: 0; box-shadow: none; }
        #sightsNotesExpandModal .tiptap-editor-container,
        #sightsNotesExpandModal .tiptap-content { min-height: 60vh; }

        /* ---- transit's own furniture, being written -------------------------------- */
        /* The mode is the first line: a word that opens a list, like the method. */
        #addActivityModal .af-tk .af-mode { position: relative; display: flex; margin-bottom: var(--sp-xs); }
        #addActivityModal .af-tk #transitTypeWord {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-ink);
        }
        #addActivityModal .af-tk #transitTypeMenu .currency-option.active { color: var(--log-ink); text-decoration: underline; text-underline-offset: 0.25em; }
        /* The two ends are places, not three-letter codes: each takes half the line, set at the
           size the reading ticket prints them. */
        #addActivityModal .af-tk .af-ends-places { grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1fr); }
        #addActivityModal .af-tk input.af-place-end { width: 100%; }

        /* ---- a stay's own furniture, being written --------------------------------- */
        #addActivityModal .af-tk .af-head-row { align-items: flex-start; }
        #addActivityModal .af-tk .af-grow { flex: 1 1 auto; min-width: 0; }
        #addActivityModal .af-tk .af-place { position: relative; }
        #addActivityModal .af-tk input.tk-name { min-height: 44px; }
        #addActivityModal .af-tk .af-address {
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
        }
        /* BOOKED beside the name, as the confirmation prints it: the stamp alone. Its label stays
           in the page for the screen reader and out of the line. */
        #addActivityModal .af-tk .af-stamp-slot { flex: none; padding-top: 6px; }
        #addActivityModal .af-tk .af-stamp-slot .form-label {
            position: absolute;
            width: 1px;
            height: 1px;
            overflow: hidden;
            clip: rect(0 0 0 0);
            white-space: nowrap;
        }
        #addActivityModal .af-tk .af-stay-dates {
            flex: 1 1 auto;
            min-width: 0;
            display: grid;
            grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
            gap: var(--sp-md);
        }
        #addActivityModal .af-tk .af-when { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
        #addActivityModal .af-tk .af-when .tk-label { display: block; }
        /* ⚠️ THE DAYS WERE CUT OFF. Set at the body size beside the nights figure, "Wed, 16 Sept 2026"
           ran out of a field that cannot wrap — at 430 and worse at 375, photographed on the first
           run. The day is written at the size the flight's days are, in the ink, and the nights go
           under the two days rather than beside them. */
        #addActivityModal .af-tk input.af-day.af-day-value { font-size: var(--fs-small); color: var(--log-ink); }
        #addActivityModal .af-tk .af-at.af-at-small { min-width: 4em; }
        #addActivityModal .af-tk .af-stay-row { flex-wrap: wrap; }
        #addActivityModal .af-tk .af-stay-row .af-stay-dates { flex: 1 1 100%; }
        #addActivityModal .af-tk .af-nights {
            flex: 1 1 100%;
            display: flex;
            align-items: baseline;
            justify-content: flex-end;
            gap: var(--sp-xs);
            margin-top: var(--sp-2xs);
        }
        #addActivityModal .af-tk .af-nights .tk-nights-w { margin-top: 0; }
        /* Each field rules its own foot, so the space between them is space, not a second rule. */
        #addActivityModal .af-tk .af-slot,
        #addActivityModal .af-tk .af-when + .af-when,
        #addActivityModal .af-tk .af-stay-row + .af-field,
        #addActivityModal .af-tk .af-field + .af-slot,
        #addActivityModal .af-tk .af-slot + .af-slot,
        #addActivityModal .af-tk .af-slot + .af-field { margin-top: var(--sp-md); }
        #addActivityModal .af-tk .af-when + .af-when { margin-top: 0; }
        #addActivityModal .af-tk #breakfastSection .toggle-slider::after { content: 'Not included'; }
        #addActivityModal .af-tk #breakfastSection .toggle-switch input:checked + .toggle-slider::after { content: 'Included'; }

        /* ---- what it cost -------------------------------------------------------- */
        #addActivityModal .af-tk #costPaymentSection .form-row-split {
            display: grid;
            grid-template-columns: auto minmax(0, 1fr) auto;
            align-items: center;
            gap: 0 var(--sp-sm);
            margin: var(--sp-xs) 0 0;
        }
        #addActivityModal .af-tk #costPaymentSection .form-group {
            position: relative;
            min-width: 0;
            margin: 0;
            padding: 0;
        }
        #addActivityModal .af-tk #costPaymentSection .form-group:last-child { justify-self: end; }

        /* A word that opens a list, ruled at the foot of its box as on the receipt. */
        #addActivityModal .af-tk .category-selector {
            display: inline-flex;
            align-items: center;
            gap: var(--sp-xs);
            width: auto;
            min-height: 44px;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            background: none;
            box-shadow: inset 0 -1px 0 0 var(--log-rule-firm);
            cursor: pointer;
            white-space: nowrap;
            text-align: inherit;
            color: var(--log-ink);
        }
        #addActivityModal .af-tk .category-selector:has(~ .currency-dropdown.active) { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk #activityCurrencyText {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            color: var(--log-ink-soft);
        }
        #addActivityModal .af-tk #selectedPaymentText {
            font-family: var(--log-write);
            font-size: var(--fs-small);
            font-weight: 400;
            letter-spacing: normal;
            text-transform: none;
            color: var(--log-ink-soft);
        }
        #addActivityModal .af-tk .amount-input-wrapper {
            display: block;
            position: relative;
            margin: 0;
            padding: 0;
            border: none;
            border-radius: 0;
            background: none;
            box-shadow: none;
        }
        #addActivityModal .af-tk .currency-symbol { display: none; }
        #addActivityModal .af-tk #activityCostInput {
            display: block;
            width: 100%;
            min-width: 0;
            min-height: 44px;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            background: transparent;
            box-shadow: inset 0 -1px 0 0 var(--log-rule);
            outline: none;
            text-align: left;
            font-family: var(--log-print);
            font-size: var(--fs-lg);
            font-weight: 600;
            font-variant-numeric: lining-nums tabular-nums;
            letter-spacing: normal;
            color: var(--log-ink);
            caret-color: var(--log-ink);
        }
        #addActivityModal .af-tk #activityCostInput:focus { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk #activityCostInput::placeholder { color: var(--log-ink-soft); opacity: 1; }

        /* THE LIST, NAMING THE PROPERTIES THE OLD DROPDOWN HIDES IT WITH. 10-legacy-home-sheet.css
           keeps .currency-dropdown at opacity 0, visibility hidden, max-height 0 and a transition
           until it is .active — the expense form's currency list opened invisibly for that reason
           on the same day. ⚠️ HERE THEY ARE NOT WHAT SHOWS IT: these lists open by .active, and the
           old file's own .currency-dropdown.active rule already makes them visible. Removing
           opacity and visibility below changed nothing on screen (the breakage proof could not
           fail), so they are kept only so this list does not depend on that file's .active rule,
           and this note says so rather than claiming they are load-bearing. */
        #addActivityModal .af-tk .currency-dropdown {
            display: none;
            position: absolute;
            top: calc(100% - 4px);
            left: 0;
            right: auto;
            z-index: 20;
            min-width: 200px;
            max-width: 280px;
            max-height: 264px;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            overflow-y: auto;
            overscroll-behavior: contain;
            opacity: 1;
            visibility: visible;
            transition: none;
            border: 1px solid var(--log-rule-firm);
            border-radius: 0;
            box-shadow: none;
            background: var(--log-stock);
            text-align: left;
        }
        #addActivityModal .af-tk .currency-dropdown.active { display: block; }
        #addActivityModal .af-tk .currency-dropdown.is-up { top: auto; bottom: calc(100% - 4px); }
        #addActivityModal .af-tk #paymentDropdown { left: auto; right: 0; }
        #addActivityModal .af-tk .currency-option {
            display: flex;
            align-items: center;
            gap: var(--sp-xs);
            width: 100%;
            min-height: 44px;
            margin: 0;
            padding: 0 var(--sp-sm);
            box-sizing: border-box;
            border: none;
            border-radius: 0;
            background: none;
            text-align: left;
            cursor: pointer;
            white-space: nowrap;
            font-family: var(--log-write);
            font-size: var(--fs-body);
            letter-spacing: normal;
            text-transform: none;
            color: var(--log-ink-soft);
        }
        #addActivityModal .af-tk .currency-option + .currency-option { border-top: 1px solid var(--log-rule); }
        #addActivityModal .af-tk .currency-option:hover,
        #addActivityModal .af-tk .currency-option:active { background: var(--log-stock-band); }
        #addActivityModal .af-tk .currency-option:focus-visible { outline: 2px solid var(--log-ink); outline-offset: -2px; }
        #addActivityModal .af-tk .cur-search {
            position: sticky;
            top: 0;
            z-index: 1;
            padding: 0 var(--sp-sm);
            background: var(--log-stock);
            border: none;
            border-bottom: 1px solid var(--log-rule-firm);
        }
        #addActivityModal .af-tk .cur-search:focus-within { box-shadow: inset 0 -2px 0 0 var(--log-ink); }
        #addActivityModal .af-tk .cur-search-input {
            width: 100%;
            min-height: 44px;
            margin: 0;
            padding: 0;
            border: none;
            background: transparent;
            outline: none;
            font-family: var(--log-write);
            font-size: var(--fs-body);
            letter-spacing: normal;
            text-transform: none;
            color: var(--log-ink);
        }
        #addActivityModal .af-tk .cur-search-input::placeholder { color: var(--log-ink-soft); opacity: 1; }
        #addActivityModal .af-tk .cur-empty {
            padding: var(--sp-sm);
            font-family: var(--log-write);
            font-size: var(--fs-body);
            color: var(--log-ink-soft);
        }

        /* What it came to, in the words the reading ticket uses; nothing when nothing was spent. */
        #addActivityModal .af-tk #costPreview {
            margin: var(--sp-2xs) 0 0;
            padding: 0;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            font-variant-numeric: lining-nums tabular-nums;
            letter-spacing: normal;
            color: var(--log-ink-soft);
        }
        #addActivityModal #costPreview[hidden] { display: none; }
        #addActivityModal #costPreview.is-warn { color: var(--log-port); }

        /* ---- what came with it --------------------------------------------------- */
        #addActivityModal .af-tk #attachmentsSection {
            display: flex;
            flex-direction: column;
            margin-top: var(--sp-md);
        }
        #addActivityModal .af-tk #attachmentsSection > .form-label { order: 0; }
        #addActivityModal .af-tk #attachmentList { order: 1; margin: var(--sp-2xs) 0 0; }
        #addActivityModal .af-tk .attachment-upload {
            order: 2;
            display: flex;
            align-items: center;
            align-self: flex-start;
            min-height: 44px;
            margin: 0;
            padding: 0;
            border: none;
            border-radius: 0;
            background: none;
            cursor: pointer;
            text-align: left;
        }
        #addActivityModal .af-tk .attachment-upload svg,
        #addActivityModal .af-tk .upload-subtext { display: none; }
        #addActivityModal .af-tk .upload-text {
            margin: 0;
            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;
            color: var(--log-magenta);
        }
        #addActivityModal button.tk-file-act {
            min-height: 44px;
            padding: 0;
            border: none;
            background: none;
            cursor: pointer;
        }

        /* ---- read a booking (2026-09-16) ------------------------------------------- */
        /* The first panel of the flight and the stay: READ A BOOKING, what that sends and to whom, and
           what the reading came to (37-read-booking.js). The word is ink, not magenta: reading fills
           the ticket and changes no record — SAVE does. */
        #addActivityModal .af-tk .af-reader { display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
        #addActivityModal .af-tk .af-reader-note { margin: 0; padding-top: 0; }
        #addActivityModal .af-tk .af-reader-out { align-self: stretch; }
        /* No :empty rule: display none on the live region kept it out of the accessibility tree until its first
           message, so "Reading" was not announced. Empty, in a column with no gap, it takes no room. */
        #addActivityModal .af-tk .af-reader-out .af-quiet { margin: 0; }
        #addActivityModal .af-tk .af-reader-fault,
        #addActivityModal .af-tk .af-reader-dupe { color: var(--log-ink); }
        #addActivityModal .af-tk .af-reader-rows { margin: var(--sp-2xs) 0; border-top: 1px solid var(--log-rule); }
        #addActivityModal .af-tk .af-reader-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: var(--sp-sm);
            width: 100%;
            min-height: 44px;
            padding: 0;
            border: none;
            border-bottom: 1px solid var(--log-rule);
            background: none;
            cursor: pointer;
            text-align: left;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink);
        }
        #addActivityModal .af-tk .af-reader-row:active,
        #addActivityModal .af-tk .af-reader-row[aria-pressed="true"] { box-shadow: inset 0 -2px 0 0 currentColor; }
        #addActivityModal .af-tk .af-reader-what { display: flex; flex-wrap: wrap; column-gap: var(--sp-sm); min-width: 0; }
        /* The state stamp, boxed as BOOKED is on the same ticket (DESIGN.md, state-stamp): unboxed soft caps are a label. */
        #addActivityModal .af-tk .af-reader-stamp {
            flex: none;
            padding: 5px 6px 4px;
            border: 1px solid var(--log-ink);
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-ink);
        }

        /* ---- the foot ------------------------------------------------------------ */
        #addActivityModal .af-foot {
            padding: var(--sp-xs) var(--sp-lg);
            border-top: 1px solid var(--log-rule-firm);
        }
        #addActivityModal .af-foot[hidden] { display: none; }
        #addActivityModal .af-drop {
            min-height: 44px;
            padding: 0;
            border: none;
            background: none;
            cursor: pointer;
            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;
            color: var(--log-magenta);   /* was port red (owner, 2026-09-17: 打开表单算写记录，删除统一用品红) */
        }

        /* ---- a place, offered, under the field that asked ----------------------------------- */
        /* ⚠️ IN THE TICKET'S FLOW, UNDER ITS FIELD, WITH NO RULE OF ITS OWN ON TOP (owner, 2026-09-13: activity里面 where 应该是个
           地址选择器). The ink is the shared list's (css/17t-stop.css). `position` and `width` are this ticket's: without them
           a legacy rule floats the list, and on the flight and transit tickets it opened where a press lands on nothing
           (af-leaves-from, af-leaves-transit). There is no top rule: one stood directly under the field's own foot rule and
           drew two lines. Each place is ruled below; it scrolls after five. */
        #addActivityModal .af-tk .place-suggestions {
            position: static;
            width: auto;
            max-height: 220px;
            margin-top: var(--sp-xs);
            border: none;
        }
        #addActivityModal .af-tk .place-suggestion {
            padding: var(--sp-2xs) 0;
            border-top: none;
            border-bottom: 1px solid var(--log-rule);
            font-size: var(--fs-small);
        }
        /* Where a flight or a transit leaves from: its own line, under the two ends. */
        #addActivityModal .af-tk .af-leaves { margin-top: var(--sp-md); }
