        /* ==========================================================================
           #G  Edit profile — the form behind the Profile's Edit
           --------------------------------------------------------------------------
           2026-09-05. The old world's form (labels stacked over bordered inputs, a
           camera icon, a Save Changes button) redrawn as the sign-in sheet's ruled
           entries under the rooms-off-Home head: Cancel · EDIT PROFILE · Save. The
           one new part is the choice of two words for who sees the wall.
           ========================================================================== */

        #profileEditPage,
        #profileEditPage.active {
            background: var(--log-stock);
            min-height: 100vh;
            padding-bottom: calc(var(--sp-2xl) + env(safe-area-inset-bottom, 0px));
        }

        /* The head and its title are the room head (.room-bar, css/11-home.css, since
           2026-09-16). What is this room's own: the page scrolls, so the head sticks; and its
           side cells go to the ends — Cancel at the left, not Back, because leaving this page
           abandons an edit rather than returning from a room. */
        #profileEditPage .pe-bar {
            position: sticky;
            top: 0;
            z-index: 2;
        }
        #profileEditPage .pe-bar > :first-child { justify-self: start; }
        #profileEditPage .pe-bar > :last-child { justify-self: end; }

        #profileEditPage .pe-word {
            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;
            background: none;
            border: none;
            padding: 0;
            cursor: pointer;
            min-height: 44px;
            display: inline-flex;
            align-items: center;
            white-space: nowrap;
        }
        #profileEditPage .pe-word.is-mark { color: var(--log-magenta); }

        #profileEditPage .pe-avatar-row {
            display: flex;
            align-items: center;
            gap: var(--sp-md);
            padding: var(--sp-lg) var(--sp-lg) var(--sp-md);
        }

        #profileEditPage .pe-avatar {
            width: 56px;
            height: 56px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--log-stock-band);
            border: 1px solid var(--log-rule-firm);
            font-family: var(--log-print);
            font-size: var(--fs-lg);
            font-weight: 600;
            color: var(--log-ink);
        }

        /* The entries: the sign-in sheet's rows, bound top and bottom by a firm rule. */
        #profileEditPage .pe-entries { border-top: 1px solid var(--log-rule-firm); }

        /* The @ sits in the entry column before the value, in the softer ink; the
           value's own left padding is dropped so the two read as one word. */
        #profileEditPage .pe-entry-handle { grid-template-columns: 6.5rem auto 1fr; }
        #profileEditPage .pe-at {
            display: flex;
            align-items: center;
            padding-left: var(--sp-sm);
            font-family: var(--log-write);
            font-size: var(--fs-base);
            color: var(--log-ink-soft);
        }
        #profileEditPage .pe-entry-handle .log-entry-value { padding-left: 2px; }

        /* The photograph, once there is one. */
        #profileEditPage .pe-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
        #profileEditPage .pe-avatar { overflow: hidden; }

        /* The About row grows with its words; the label stays at the top of it. */
        #profileEditPage .pe-entry-about .log-entry-label { align-items: flex-start; }
        #profileEditPage .pe-entry-about textarea.log-entry-value {
            resize: none;
            line-height: 1.5;
            min-height: calc(3 * 1.5em + 2 * var(--sp-md));
        }

        /* The place row's suggestions hang from the row's baseline, in the entry
           column, as more ruled rows: stock ground, a firm rule around, hairlines
           between, the write face at the entry's size, 44px a row. The old world's
           list (paper, 13px sans, a 4px gap) is overridden here and nowhere else. */
        #profileEditPage .pe-entry-place { position: relative; }
        /* Where this room's list sits: indented past the label column it hangs under. Its
           INK moved to the shared block in css/17t-stop.css on 2026-09-11 — four rooms were
           dressing this list and the fourth was about to be written. */
        #profileEditPage .pe-entry-place .place-suggestions {
            left: 6.5rem;
            right: 0;
            top: 100%;
            z-index: 3;
            padding: 0;
            border-top: none;
            max-height: calc(5 * 44px);
        }

        /* Two words, one chosen: the chosen in ink, underlined; the other in the softer
           ink. The same grammar as the tabs, for the same reason — a choice among a few
           named things is a row of words, not a control. */

        #profileEditPage .pe-choices {
            margin-top: var(--sp-lg);
            border-top: 1px solid var(--log-rule-firm);
            border-bottom: 1px solid var(--log-rule-firm);
            background: var(--log-stock-band);
        }

        #profileEditPage .pe-choice {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: var(--sp-md);
            padding: var(--sp-sm) var(--sp-lg);
        }
        #profileEditPage .pe-choice + .pe-choice { border-top: 1px solid var(--log-rule); }

        #profileEditPage .pe-choice-label {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--log-ink);
        }

        #profileEditPage .pe-choice-words { display: flex; gap: var(--sp-lg); }

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

        #profileEditPage .pe-note {
            margin: var(--sp-md) var(--sp-lg) 0;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            line-height: 1.6;
            color: var(--log-ink-soft);
        }

        #profileEditPage :focus-visible {
            outline: 2px solid var(--log-ink);
            outline-offset: 2px;
        }
        #profileEditPage .log-entry-value:focus-visible { outline: 2px solid transparent; outline-offset: -2px; border-bottom: none; }

        /* ==========================================================================
           #F  The Profile — the page one traveller shows another
           --------------------------------------------------------------------------
           Sixth surface in the deck log world, 2026-09-05. Brief:
           .impeccable/surfaces/public-27-profile-js.md

           Assembled from plates that exist: the rooms-off-Home head, the Register's
           world plate (.reg-map, admitted above), the Wall's strips (.wall-root), the
           Specimen for what is empty or private. Its own parts are the head — avatar,
           name, a line about them, the account line — the three tabs, and the trip
           outline: a cover square, a name, a meta line, and for the owner the word that
           says who may see it.
           ========================================================================== */

        #profilePage,
        /* .active as well: the bottom-bar pages' shared rule five thousand lines
           further down paints them paper, and document order would hand it the
           argument — the same fight #mainPage had, settled the same way. */
        #profilePage.active {
            background: var(--log-stock);
            min-height: 100vh;
        }

        /* The bottom-bar pages' shared rule gives this page room for the bar. On a
           friend's page the bar is hidden (02-state.js), and the room goes with it. */
        body.bar-hidden #profilePage,
        body.bar-hidden #profilePage.active { padding-bottom: env(safe-area-inset-bottom, 0px); }

        /* The head and its title are the room head (.room-bar, css/11-home.css, since
           2026-09-16). What is this room's own: the whole page scrolls, so the head sticks;
           and its two side cells are laid to the ends, because either can be an empty span —
           one's own Profile has no Back. */
        #profilePage .pf-bar {
            position: sticky;
            top: 0;
            z-index: 2;
        }

        #profilePage .pf-bar > :first-child { justify-self: start; }
        #profilePage .pf-bar > :last-child { justify-self: end; }

        /* The world's action word: print caps, underlined, ink. Magenta (.is-mark)
           for the two that change the record — Edit, and a trip's visibility. */
        #profilePage .pf-word {
            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;
            background: none;
            border: none;
            padding: 0;
            cursor: pointer;
            min-height: 44px;
            display: inline-flex;
            align-items: center;
            white-space: nowrap;
        }
        #profilePage .pf-word.is-mark { color: var(--log-magenta); }
        #profilePage .pf-word.is-quiet { color: var(--log-ink-soft); text-decoration: none; cursor: default; }

        /* ---- The head --------------------------------------------------------------- */
        #profilePage .pf-head {
            display: grid;
            grid-template-columns: auto 1fr;
            column-gap: var(--sp-md);
            row-gap: var(--sp-2xs);
            align-items: center;
            padding: var(--sp-lg) var(--sp-lg) var(--sp-md);
        }

        /* A square, like the log's cachet and the Home card's avatar: this world has
           no circles but the play mark. The initial in print caps until a photograph
           exists. */
        #profilePage .pf-avatar {
            grid-row: 1;
            width: 56px;
            height: 56px;
            /* The rule round it is part of the 56, or the head moves by two pixels depending on whether the
               traveller has a photograph: a button counts its border in, a div does not (2026-09-21). */
            box-sizing: border-box;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--log-stock-band);
            border: 1px solid var(--log-rule-firm);
            font-family: var(--log-print);
            font-size: var(--fs-lg);
            font-weight: 600;
            color: var(--log-ink);
            overflow: hidden;
        }
        #profilePage .pf-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

        #profilePage .pf-who { grid-row: 1; min-width: 0; }

        #profilePage .pf-name {
            margin: 0;
            font-family: var(--log-print);
            font-size: var(--fs-body);
            font-weight: 600;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            line-height: 1.25;
            color: var(--log-ink);
            overflow-wrap: anywhere;
        }

        #profilePage .pf-handle {
            margin: 2px 0 0;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
        }

        #profilePage .pf-bio,
        #profilePage .pf-account {
            grid-column: 1 / -1;
            margin: 0;
            font-family: var(--log-write);
            line-height: 1.5;
        }
        #profilePage .pf-bio { margin-top: var(--sp-xs); font-size: var(--fs-body); color: var(--log-ink); }
        #profilePage .pf-bio.is-quiet { color: var(--log-ink-soft); font-style: italic; }
        /* Where they live, under the handle beside the avatar: the two facts about the
           person that are not their words. */
        #profilePage .pf-where {
            margin: 2px 0 0;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            line-height: 1.4;
            color: var(--log-ink-soft);
        }

        /* The account line: the Register's voice, numbers twenty and under in words. */
        #profilePage .pf-account {
            margin-top: var(--sp-xs);
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--log-ink);
        }

        /* ---- The tabs --------------------------------------------------------------- */
        /* Three words on the band with a firm rule under, the current one underlined in
           ink — the gallery's own tab grammar (ALL · FAVOURITES), on this world's band. */
        #profilePage .pf-tabs {
            /* Held under the bar once the head has scrolled away: the tabs are the
               panel's head, and a long log must not scroll its head off the screen. The
               offset is the bar's height — 44px word, twice --sp-2xs, one rule — plus
               the safe area the bar also carries. */
            position: sticky;
            top: calc(44px + 2 * var(--sp-2xs) + 1px + env(safe-area-inset-top, 0px));
            z-index: 1;
            display: flex;
            gap: var(--sp-lg);
            justify-content: space-between;
            padding: 0 var(--sp-lg);
            background: var(--log-stock-band);
            border-top: 1px solid var(--log-rule-firm);
            border-bottom: 1px solid var(--log-rule-firm);
        }

        #profilePage .pf-tab {
            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);
            background: none;
            border: none;
            padding: 0;
            min-height: 44px;
            cursor: pointer;
            position: relative;
        }
        #profilePage .pf-tab.is-on { color: var(--log-ink); }
        #profilePage .pf-tabs-word { margin-left: auto; }
        #profilePage .pf-tab.is-on::after {
            content: '';
            position: absolute;
            left: 0; right: 0; bottom: -1px;
            height: 2px;
            background: var(--log-ink);
        }

        /* ---- The trips panel -------------------------------------------------------- */
        #profilePage .pf-plate {
            padding: var(--sp-md) var(--sp-lg) var(--sp-sm);
            border-bottom: 1px solid var(--log-rule);
        }
        #profilePage .pf-plate .reg-map-wrap { margin: 0; }
        #profilePage .pf-plate path.is-visited { cursor: pointer; }

        /* Said out loud, drawn nowhere: the inked countries as words and as buttons
           for the keyboard, clipped away from sight — the Register's .stats-quiet. */
        #profilePage .pf-quiet {
            position: absolute;
            width: 1px;
            height: 1px;
            margin: -1px;
            padding: 0;
            overflow: hidden;
            clip: rect(0 0 0 0);
            clip-path: inset(50%);
            white-space: nowrap;
            border: 0;
        }
        #profilePage .pf-quiet button:focus-visible ~ *,
        #profilePage .pf-quiet:focus-within {
            /* Brought back when a keyboard reaches it, so the focused country is seen. */
            position: static;
            width: auto;
            height: auto;
            margin: var(--sp-sm) 0 0;
            clip: auto;
            clip-path: none;
            white-space: normal;
            display: flex;
            flex-wrap: wrap;
            gap: var(--sp-xs) var(--sp-md);
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
        }
        #profilePage .pf-quiet p { margin: 0; }
        #profilePage .pf-quiet button {
            background: none; border: none; padding: 0; cursor: pointer;
            font: inherit; color: var(--log-ink); text-decoration: underline; text-underline-offset: 0.2em;
        }
        #profilePage .pf-plate { position: relative; }

        #profilePage .pf-tabs { align-items: center; }
        #profilePage .pf-tablist { display: flex; gap: var(--sp-lg); }

        #profilePage .pf-plate-note,
        #profilePage .pf-filter {
            margin: var(--sp-sm) 0 0;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
        }
        #profilePage .pf-filter { padding: 0 var(--sp-lg); margin-top: var(--sp-sm); display: flex; align-items: center; gap: var(--sp-sm); }
        #profilePage .pf-filter .pf-word { min-height: 0; }

        #profilePage .pf-trips { padding: var(--sp-xs) 0; }

        #profilePage .pf-trip {
            display: flex;
            align-items: center;
            gap: var(--sp-sm);
            padding: 0 var(--sp-lg);
            border-bottom: 1px solid var(--log-rule);
        }
        #profilePage .pf-trip:last-child { border-bottom: none; }

        #profilePage .pf-trip-open {
            flex: 1 1 auto;
            min-width: 0;
            display: flex;
            align-items: center;
            gap: var(--sp-md);
            padding: var(--sp-sm) 0;
            background: none;
            border: none;
            text-align: left;
            cursor: pointer;
            color: inherit;
        }
        #profilePage .is-outline .pf-trip-open { cursor: default; }

        /* The cover: a square of the photograph the owner chose — the one picture a
           stranger may see of a trip. Band when there is none. */
        #profilePage .pf-cover {
            flex: none;
            width: 56px;
            height: 56px;
            background: var(--log-stock-band);
            overflow: hidden;
        }
        #profilePage .pf-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

        #profilePage .pf-trip-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }

        #profilePage .pf-trip-name {
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--log-ink);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        #profilePage .pf-trip-meta {
            font-family: var(--log-write);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        /* The one mark of relation: this trip was shared. Print caps, softer ink. */
        #profilePage .pf-together {
            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);
        }

        /* Who may see this trip — the owner's word, in the annotation ink. */
        #profilePage .pf-vis {
            flex: none;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--log-magenta);
            text-decoration: underline;
            text-underline-offset: 0.25em;
            text-decoration-thickness: 1px;
            background: none;
            border: none;
            padding: 0;
            min-height: 44px;
            cursor: pointer;
        }

        /* ---- Empty, private, waiting ----------------------------------------------- */
        #profilePage .pf-empty {
            padding: var(--sp-2xl) var(--sp-lg);
            font-family: var(--log-write);
            font-size: var(--fs-body);
            line-height: 1.5;
            color: var(--log-ink);
        }
        #profilePage .pf-empty span {
            display: block;
            margin-top: var(--sp-sm);
            font-size: var(--fs-small);
            color: var(--log-ink-soft);
        }
        #profilePage .pf-empty .pf-word { min-height: 0; display: inline; }
        #profilePage .pf-empty span .pf-word.is-mark { display: inline-flex; margin-top: var(--sp-sm); min-height: 44px; }

        #profilePage .pf-waiting { padding: var(--sp-lg); display: grid; grid-template-columns: auto 1fr; gap: var(--sp-sm) var(--sp-md); align-items: center; }
        #profilePage .pf-waiting i { display: block; background: var(--log-stock-band); animation: wall-breathe 1.8s ease-in-out infinite; }
        #profilePage .pf-waiting .is-avatar { width: 56px; height: 56px; grid-row: 1 / 3; }
        #profilePage .pf-waiting .is-line { height: 12px; width: 60%; }
        #profilePage .pf-waiting .is-line.is-short { width: 35%; }
        @media (prefers-reduced-motion: reduce) { #profilePage .pf-waiting i { animation: none; } }

        /* The Wall's strips on this page sit under the tabs; a firm rule between them
           as on the Wall, the first one flush with the tabs' own rule. */
        #profilePage .wall-root .wall-strip:first-child .wall-strip-head { border-top: none; }

        #profilePage :focus-visible {
            outline: 2px solid var(--log-ink);
            outline-offset: 2px;
        }


        /* ---- the portrait, larger (2026-09-20) ------------------------------------ */
        /* The night plate every photograph in this world opens on, and nothing typed over it: the picture at true
           aspect, CLOSE in the plate's own word. Flat, and gone on Escape, on CLOSE, or on a tap beside it. */
        .pf-portrait {
            position: fixed;
            inset: 0;
            z-index: 60;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: var(--sp-lg);
            background: var(--log-night-plate, #0B1220);
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.22s ease, visibility 0s linear 0.22s;
        }
        .pf-portrait.is-open { opacity: 1; visibility: visible; transition: opacity 0.22s ease; }
        .pf-portrait img {
            max-width: min(92vw, 560px);
            max-height: 76vh;
            object-fit: contain;
        }
        .pf-portrait-close {
            position: absolute;
            top: calc(var(--sp-md) + env(safe-area-inset-top, 0px));
            right: var(--sp-lg);
            min-height: 44px;
            padding: 0;
            background: none;
            border: none;
            cursor: pointer;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--log-stock);
            text-decoration: underline;
            text-underline-offset: 0.25em;
        }
        /* The portrait says it opens: the same plate as the rest of the head, pressable.

           ⚠️ IT KEEPS THE RULE ROUND IT (owner, 2026-09-21: 帮我把profile里的头像加个边框). This said `border: none`,
           which is what a button needs said to it — and it also took off the hairline the plate above gives every
           avatar, so the one head in this app that has a photograph was the one without a frame. A button's own
           border is overridden by naming the rule again, not by taking every border away. */
        #profilePage button.pf-avatar {
            padding: 0;
            border: 1px solid var(--log-rule-firm);
            cursor: pointer;
        }
