      html,
      body {
        margin: 0;
        height: 100%;
        overflow: hidden;
        background: #9ed2f5;
        font-family: system-ui, sans-serif;
      }
      canvas {
        display: block;
      }
      /* the settings panel: a grey floating box top-left, under the Cities button */
      #hud {
        position: fixed;
        top: 72px;
        left: 18px;
        width: 272px;
        box-sizing: border-box;
        color: #374151;
        font-size: 13px;
        line-height: 1.4;
        background: rgba(238, 240, 244, 0.94);
        border: 1px solid #cfd4dd;
        border-radius: 10px;
        padding: 10px 12px;
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
        pointer-events: auto;
        display: flex;
        flex-direction: column;
        gap: 8px;
        z-index: 5;
        transition: opacity 0.25s, transform 0.25s;
      }
      /* the panel stays out of the way until D is pressed (and D again puts it away) */
      body:not(.hud) #hud {
        opacity: 0;
        transform: translateY(-8px);
        pointer-events: none;
      }
      body:not(.hud) #hud * {
        pointer-events: none;
      }
      /* hide UI (H): the canvas alone, for screenshots */
      body.bare > :not(canvas) {
        display: none !important;
      }
      #hud b {
        color: #2b3a67;
      }
      /* one control per row: a fixed label column, the control filling the rest */
      #glowUi,
      #tiltUi,
      #themeUi,
      #wireUi,
      #shadeUi {
        display: grid;
        grid-template-columns: 64px 1fr;
        align-items: center;
        gap: 8px;
      }
      #glowUi select,
      #tiltUi select,
      #themeUi select,
      #wireUi select,
      #shadeUi select {
        font: inherit;
        color: #2b3a67;
        border: 1px solid #c5cbd6;
        border-radius: 6px;
        padding: 3px 6px;
        background: #fff;
        cursor: pointer;
        width: 100%;
        min-width: 0;
      }
      /* a note under its row ("houses unchanged"): its own line, the row above unmoved */
      #glowHint,
      #themeHint {
        grid-column: 1 / -1;
        color: #7c8596;
        font-size: 12px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      #glowHint:empty,
      #themeHint:empty {
        display: none;
      }
      /* the Theme row: the picker, then the 🎨 that opens the colour lab */
      #themeUi {
        grid-template-columns: 64px 1fr auto;
      }
      #colorLabBtn,
      #blenderBtn {
        font: inherit;
        line-height: 1;
        padding: 3px 5px;
        border: 1px solid #cfd4dd;
        border-radius: 6px;
        background: #fff;
        cursor: pointer;
      }
      #blenderBtn {
        padding: 5px;
      }
      #blenderBtn:disabled {
        color: #8a93a3;
        cursor: default;
      }
      /* the colour lab (js/color-lab.js): the kits' swatches with a picker each, the tower
         palette, and the JSON to paste. Sits where the settings panel does, and steps aside
         when that is up. */
      #colorLab {
        position: fixed;
        top: 72px;
        left: 18px;
        width: 300px;
        max-height: calc(100vh - 150px);
        overflow-y: auto;
        box-sizing: border-box;
        color: #374151;
        font-size: 12px;
        line-height: 1.4;
        background: rgba(238, 240, 244, 0.96);
        border: 1px solid #cfd4dd;
        border-radius: 10px;
        padding: 10px 12px;
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
        z-index: 6;
        display: flex;
        flex-direction: column;
        gap: 6px;
      }
      body.hud #colorLab {
        left: 302px;
      }
      #colorLab .head,
      #colorLab .title {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
      }
      #colorLab .head {
        font-weight: 600;
        font-size: 13px;
      }
      #colorLab .title {
        text-transform: capitalize;
        font-weight: 600;
        color: #2b3a67;
        margin-top: 4px;
      }
      #colorLab button {
        font: inherit;
        color: inherit;
        background: none;
        border: 0;
        padding: 0 2px;
        cursor: pointer;
      }
      #colorLab .head .x {
        font-size: 18px;
        line-height: 1;
      }
      #colorLab .reset,
      #colorLab .note {
        color: #7c8596;
        font-size: 11px;
      }
      #colorLab .reset:hover {
        color: #2b3a67;
      }
      #colorLab section {
        display: grid;
        gap: 2px;
      }
      #colorLab details {
        margin-top: 2px;
      }
      #colorLab summary {
        color: #7c8596;
        font-size: 11px;
        cursor: pointer;
      }
      #colorLab .swatch {
        display: grid;
        grid-template-columns: 22px 34px 1fr 14px;
        align-items: center;
        gap: 8px;
        height: 24px;
      }
      #colorLab .chip {
        width: 22px;
        height: 18px;
        border-radius: 4px;
        border: 1px solid rgba(0, 0, 0, 0.15);
      }
      #colorLab input[type="color"] {
        width: 34px;
        height: 22px;
        padding: 0 1px;
        border: 1px solid #cfd4dd;
        border-radius: 5px;
        background: #fff;
        cursor: pointer;
      }
      #colorLab .share {
        font-variant-numeric: tabular-nums;
        color: #5b6577;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      #colorLab .swatch .x {
        color: #7c8596;
        font-size: 14px;
      }
      #colorLab .swatch .x:hover {
        color: #b3261e;
      }
      #colorLab .foot {
        display: grid;
        gap: 6px;
        margin-top: 6px;
        border-top: 1px solid #d8dde6;
        padding-top: 8px;
      }
      #colorLab .foot .row {
        display: grid;
        grid-template-columns: 1fr auto;
        gap: 6px;
      }
      #colorLab .foot input,
      #colorLab .foot select,
      #colorLab textarea {
        font: inherit;
        color: inherit;
        border: 1px solid #cfd4dd;
        border-radius: 6px;
        background: #fff;
        padding: 3px 6px;
        min-width: 0;
      }
      #colorLab textarea {
        font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
        resize: vertical;
      }
      #colorLab .copy {
        justify-self: start;
        border: 1px solid #cfd4dd;
        border-radius: 6px;
        background: #fff;
        padding: 3px 10px;
      }
      #colorLab .foot .note {
        margin: 0;
      }
      #clock {
        display: grid;
        grid-template-columns: 20px 1fr 44px;
        align-items: center;
        gap: 8px;
      }
      #clock input {
        width: 100%;
        min-width: 0;
        margin: 0;
        accent-color: #2b3a67;
        cursor: pointer;
      }
      #clock input:disabled {
        cursor: default; /* it only reports the city's clock */
      }
      #clock b {
        font-variant-numeric: tabular-nums;
        text-align: right;
      }
      #clockOverride,
      #multiUi,
      #skyUi,
      #bareUi {
        display: flex;
        align-items: center;
        gap: 6px;
        cursor: pointer;
        color: #6b7280;
      }
      #clockOverride {
        margin-top: -4px;
      }
      #clockOverride input,
      #multiUi input,
      #skyUi input,
      #bareUi input {
        margin: 0;
        accent-color: #2b3a67;
        cursor: pointer;
      }
      #hud #help {
        margin: 2px 0 0;
        padding-top: 8px;
        border-top: 1px solid #d6dae2;
        font-size: 12px;
        color: #6b7280;
      }
      #hud #status {
        font-size: 12px;
        color: #8a93a3;
      }
      /* the lab details: slides in from the right; the interior (offices) opens over everything */
      #panel {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        width: 40%;
        background: #fff;
        color: #1f2430;
        box-shadow: -12px 0 40px rgba(0, 0, 0, 0.18);
        padding: 0 56px 48px; /* the top padding lives in #panelHead so it sticks flush */
        box-sizing: border-box;
        overflow-y: auto;
        transform: translateX(100%);
        visibility: hidden; /* off-screen it would still cast its shadow down the window's edge */
        transition:
          transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1),
          visibility 0s 0.45s;
        z-index: 10;
      }
      #panel.open {
        visibility: visible;
        transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
        transform: translateX(0);
      }
      /* pinned header: spans the panel's padding so content scrolls under it cleanly */
      #panelHead {
        position: sticky;
        top: 0;
        z-index: 2;
        margin: 0 -56px;
        padding: 48px 56px 10px;
        background: #fff;
      }
      #panel h1 {
        margin: 0 0 6px;
        font-size: 30px;
        letter-spacing: -0.01em;
      }
      #panel .sub {
        color: #6b7280;
        font-size: 13px;
        text-transform: uppercase;
        letter-spacing: 0.12em;
        margin-bottom: 18px;
      }
      #panel h2 {
        font-size: 16px;
        margin: 26px 0 8px;
      }
      #panel p {
        line-height: 1.65;
        font-size: 15px;
        margin: 0 0 14px;
        color: #374151;
      }
      #panel .stats {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 12px;
        margin: 22px 0 8px;
      }
      #panel .stat {
        background: #f3f4f8;
        border-radius: 10px;
        padding: 12px 14px;
      }
      #panel .stat b {
        display: block;
        font-size: 22px;
      }
      #panel .stat span {
        font-size: 12px;
        color: #6b7280;
      }
      /* ---- build strip (editing mode): icon palette, no text. It unfolds from under
         the pen (#editBtn), which is the same width and sits directly above. ---- */
      #buildPanel {
        position: fixed;
        top: 138px;
        right: 16px;
        width: 62px;
        max-height: calc(100vh - 178px);
        background: #fff;
        border: 3px solid #dfe6f5;
        border-radius: 16px;
        box-shadow: 0 6px 0 #c9d3ea, 0 10px 24px rgba(0, 0, 0, 0.18);
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 6px;
        box-sizing: border-box;
        transform-origin: top center;
        transform: translateY(-10px) scaleY(0.6);
        opacity: 0;
        pointer-events: none;
        transition:
          transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1),
          opacity 0.2s;
        z-index: 6;
      }
      #buildPanel.open {
        transform: none;
        opacity: 1;
        pointer-events: auto;
      }
      /* the palette's tooltip: fixed to the page, left of the hovered button, above the
         palette and its flyout; the pointer passes through it */
      #buildTip {
        position: fixed;
        transform: translateY(-50%);
        padding: 5px 10px;
        border-radius: 8px;
        background: #2b3a67;
        color: #fff;
        font: 600 13px system-ui, sans-serif;
        white-space: nowrap;
        pointer-events: none;
        z-index: 8;
      }
      #buildTip::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 100%;
        transform: translateY(-50%);
        border: 5px solid transparent;
        border-left-color: #2b3a67;
      }
      /* ---- City Info: bottom-left, directly above the stat bar whose chips open it,
         out of the build palette's way ---- */
      #infoPanel {
        position: fixed;
        left: 16px;
        bottom: 72px;
        width: 400px;
        max-height: calc(100vh - 246px);
        display: flex;
        flex-direction: column;
        background: #fff;
        border: 3px solid #dfe6f5;
        border-radius: 16px;
        box-shadow: 0 6px 0 #c9d3ea, 0 10px 24px rgba(0, 0, 0, 0.18);
        padding: 12px 14px 14px;
        box-sizing: border-box;
        transform: translateY(calc(100% + 90px));
        transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1);
        z-index: 6;
      }
      #infoPanel.open {
        transform: translateY(0);
      }
      /* the inspector owns the right 40% of the screen, and the picker owns all of it;
         the stat bar steps out for those too, and for the dashboard while driving */
      body.selecting #infoPanel,
      body.inspecting #infoPanel,
      body.placingMega #infoPanel,
      body.driving #infoPanel {
        transform: translateY(calc(100% + 90px));
      }
      #infoHead {
        display: flex;
        align-items: center;
        flex: none;
      }
      #infoTitle {
        font: 700 16px system-ui, sans-serif;
        color: #2b3a67;
      }
      #infoClose {
        margin-left: auto;
        border: 0;
        background: none;
        color: #8a93a8;
        font-size: 20px;
        line-height: 1;
        cursor: pointer;
        padding: 0 2px;
      }
      #infoClose:hover {
        color: #2b3a67;
      }
      .infoPane {
        display: none;
        overflow-y: auto;
        min-height: 0;
        margin-top: 8px;
      }
      .infoPane.on {
        display: block;
      }
      /* ---- Labs / Researchers panes: the search box (and, for researchers, the role
         split) pinned on top, the list scrolling under them. The pane itself must not
         scroll (the panel is a bottom-pinned flex column of bounded height), so the
         list is the one scrolling box. ---- */
      #labsPane.on,
      #researchersPane.on {
        display: flex;
        flex-direction: column;
        overflow: hidden;
      }
      #roleSummary {
        flex: none;
        padding-bottom: 8px;
        margin-bottom: 8px;
        border-bottom: 1px solid #eef1f8;
      }
      .infoSearch {
        flex: none;
        width: 100%;
        box-sizing: border-box;
        margin-bottom: 6px;
        padding: 7px 10px;
        border: 2px solid #dfe6f5;
        border-radius: 10px;
        background: #fafbff;
        font: 600 12px system-ui, sans-serif;
        color: #1f2430;
        outline: none;
      }
      .infoSearch:focus {
        background: #fff7fd;
        border-color: #ff4fd0;
      }
      .infoList {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        /* never sideways: a scrolling box turns any width overrun into a horizontal
           scrollbar, and the rows deliberately overrun it (.rRow / .lRow bleed 4px past
           each edge so their hover highlight reaches the list's edge). Clip instead. */
        overflow-x: hidden;
      }
      .roleBar {
        display: flex;
        height: 8px;
        border-radius: 4px;
        overflow: hidden;
        background: #eef1f8;
        margin-bottom: 8px;
      }
      .roleBar span {
        display: block;
        height: 100%;
        transition: width 0.3s;
      }
      .roleBar .maverick {
        background: #ff4fd0;
      }
      .roleBar .follower {
        background: #6f8ff5;
      }
      .roleBar .skeptic {
        background: #f0a83a;
      }
      .roleStats {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 8px;
      }
      .roleStats .pStat span {
        text-transform: none;
        letter-spacing: 0;
      }
      .roleStats .pStat.maverick b {
        color: #8a1b66;
      }
      .roleStats .pStat.follower b {
        color: #2b3a67;
      }
      .roleStats .pStat.skeptic b {
        color: #7a4b00;
      }
      /* ---- Labs and Researchers panes: one clickable row per lab / director ---- */
      .lRow,
      .rRow {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 6px 4px;
        margin: 0 -4px;
        border-radius: 8px;
        border-bottom: 1px solid #eef1f8;
        font: 600 12px system-ui, sans-serif;
        color: #374151;
        cursor: pointer;
      }
      .lRow:hover,
      .rRow:hover {
        background: #f3f4f8;
      }
      .lRow.muted {
        color: #8a93a8;
        font-weight: 600;
      }
      .lRow .nm {
        flex: 1;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .lRow .ct,
      .rRow .ct {
        color: #8a93a8;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
      }
      /* the maverick dot: the same blue->magenta as a researcher's --maverick */
      .lRow .mv,
      .rRow .mv {
        width: 10px;
        height: 10px;
        border-radius: 50%;
        flex: none;
        background: var(--maverick, #c9d3ea);
      }
      .rRow .rText {
        flex: 1;
        min-width: 0;
      }
      .rRow .rText b {
        display: block;
        color: #1f2430;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      /* the sub-line only (a direct child) — not the role pill inside the name */
      .rRow .rText > span {
        display: block;
        font-weight: 500;
        color: #6b7280;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      /* a small portrait, the office cards' avatar at list size */
      .listAvatar {
        flex: none;
        width: 30px;
        height: 30px;
        border-radius: 8px;
        overflow: hidden;
        display: flex;
        align-items: center;
        justify-content: center;
        background: hsl(var(--avatarHue, 220) 70% 88%);
        color: hsl(var(--avatarHue, 220) 45% 32%);
        font: 700 11px system-ui, sans-serif;
        user-select: none;
      }
      .listAvatar.hasImg {
        background: none;
      }
      .listAvatar img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      /* ---- Power pane ---- */
      #powerBalance {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 8px;
      }
      .pStat {
        background: #f3f4f8;
        border-radius: 10px;
        padding: 8px 10px;
      }
      .pStat b {
        display: block;
        font: 700 17px system-ui, sans-serif;
        color: #1f2430;
      }
      .pStat span {
        font: 600 11px system-ui, sans-serif;
        color: #6b7280;
        text-transform: uppercase;
        letter-spacing: 0.06em;
      }
      #pGapStat.short {
        background: #ffeceb;
      }
      #pGapStat.short b {
        color: #a11d13;
      }
      #pGapStat.ok b {
        color: #1b5e35;
      }
      /* demand drawn against supply: the track is the stations' capability, the fill is
         what the city is asking for, and anything past the end is the deficit */
      #powerBar {
        display: flex;
        height: 14px;
        margin: 12px 0 6px;
        border-radius: 7px;
        background: #e6eaf5;
        overflow: hidden;
      }
      #powerBarFill {
        background: linear-gradient(90deg, #6fc3d9, #4f9ae0);
        transition: width 0.3s;
      }
      #powerBarOver {
        background: repeating-linear-gradient(
          45deg,
          #e5544a,
          #e5544a 5px,
          #c33f36 5px,
          #c33f36 10px
        );
        transition: width 0.3s;
      }
      #powerBarNote {
        font: 600 11px system-ui, sans-serif;
        color: #6b7280;
        margin-bottom: 10px;
      }
      /* the day profile: supply as a filled band, demand as a line over it, the hours
         they cross drawn in red */
      #powerProfile {
        display: block;
        width: 100%;
        height: 96px;
        background: #f7f8fc;
        border-radius: 10px;
      }
      #powerProfileNote {
        font: 600 11px system-ui, sans-serif;
        color: #6b7280;
        margin: 5px 0 10px;
      }
      #powerRows,
      #cityZones {
        border-top: 1px solid #eef1f8;
      }
      .pRow {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 6px 0;
        border-bottom: 1px solid #eef1f8;
        font: 600 12px system-ui, sans-serif;
        color: #374151;
      }
      .pRow:last-child {
        border-bottom: 0;
      }
      .pRow .swatch {
        width: 10px;
        height: 10px;
        border-radius: 3px;
        flex: none;
      }
      .pRow .nm {
        flex: 1;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .pRow .ct {
        color: #8a93a8;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
      }
      .pRow .kw {
        font-variant-numeric: tabular-nums;
        color: #1f2430;
        min-width: 64px;
        text-align: right;
      }
      .pHead {
        font: 700 11px system-ui, sans-serif;
        color: #8a93a8;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        padding: 10px 0 4px;
      }
      .pEmpty {
        font: 600 12px system-ui, sans-serif;
        color: #8a93a8;
        padding: 8px 0;
      }
      /* ---- City pane ---- */
      #cityStats,
      #rfpStats {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 8px;
        margin-bottom: 12px;
      }
      /* the way on from a pane: a full-width button in the list rows' idiom */
      .infoMore {
        display: block;
        width: 100%;
        padding: 9px 12px;
        border: 2px solid #e3e8f5;
        border-radius: 10px;
        background: #f7f8fc;
        color: #2b3a67;
        font: 700 13px system-ui, sans-serif;
        text-align: center;
        cursor: pointer;
        transition: border-color 0.15s;
      }
      .infoMore:hover {
        border-color: #b9c6ea;
      }
      /* the block menu: a small card pinned under the building picked in the editor, with
         its name and the three things that can be done to it. Positioned from the block's
         screen corners (placeBlockMenu in main.js), centred on its horizontal middle. */
      #blockMenu {
        position: fixed;
        left: 0;
        top: 0;
        transform: translateX(-50%);
        z-index: 7;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 6px;
        background: #fff;
        color: #2b3a67;
        padding: 8px 10px;
        border-radius: 14px;
        border: 3px solid #dfe6f5;
        box-shadow: 0 4px 0 #c9d3ea, 0 10px 24px rgba(0, 0, 0, 0.18);
        font: 600 14px system-ui, sans-serif;
        white-space: nowrap;
      }
      #blockMenu[hidden] {
        display: none;
      }
      #blockMenu .row {
        display: flex;
        gap: 6px;
      }
      #blockMenu button {
        width: 38px;
        height: 34px;
        display: flex;
        align-items: center;
        justify-content: center;
        border: 2px solid #dfe6f5;
        background: #f7f8fc;
        color: #2b3a67;
        border-radius: 10px;
        padding: 0;
        font: 600 18px system-ui, sans-serif;
        cursor: pointer;
        transition: border-color 0.15s;
      }
      #blockMenu button:hover:not(:disabled) {
        border-color: #b9c6ea;
      }
      #blockMenu button:disabled {
        opacity: 0.45;
        cursor: not-allowed;
      }
      #blockMenu button#blockDelete:hover:not(:disabled) {
        border-color: #ff8a8a;
        background: #fff1f1;
      }
      /* the power-station / service flyout, sitting just left of the build palette */
      #plantPanel {
        position: fixed;
        top: 150px;
        right: 90px;
        width: 300px; /* name, then what it makes, then what it costs */
        background: #fff;
        border: 3px solid #dfe6f5;
        border-radius: 16px;
        box-shadow: 0 6px 0 #c9d3ea, 0 10px 24px rgba(0, 0, 0, 0.18);
        display: flex;
        flex-direction: column;
        gap: 4px;
        padding: 6px;
        box-sizing: border-box;
        opacity: 0;
        pointer-events: none;
        transform: translateX(16px);
        transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.2s;
        z-index: 6;
      }
      #plantPanel.open {
        opacity: 1;
        pointer-events: auto;
        transform: translateX(0);
      }
      .plantItem {
        display: flex;
        align-items: center;
        gap: 7px;
        padding: 5px 7px;
        border: 2px solid #e5e7ee;
        border-radius: 11px;
        background: #f7f8fc;
        cursor: pointer;
        font: 600 13px system-ui, sans-serif;
        color: #2b3a67;
        transition: border-color 0.15s;
      }
      .plantItem:hover {
        border-color: #b9c6ea;
      }
      .plantItem.selected {
        border-color: #ff4fd0;
        background: #fff0fb;
      }
      .plantItem.poor {
        opacity: 0.5;
      }
      .plantItem .ico {
        font-size: 17px;
        line-height: 1;
      }
      .plantItem .nm {
        flex: 1;
      }
      /* what the price buys, so the two can be read against each other */
      .plantItem .mw {
        font: 600 11px system-ui, sans-serif;
        color: #2b3a67;
        background: #eef2ff;
        border-radius: 7px;
        padding: 2px 6px;
        margin-right: 2px;
        white-space: nowrap;
        flex: none;
      }
      .plantItem .price {
        font: 600 11px system-ui, sans-serif;
        color: #7a5a00;
        background: #fff7d6;
        border-radius: 7px;
        padding: 2px 7px;
        white-space: nowrap;
        flex: none;
      }
      .plantItem.poor .price {
        color: #b42318;
        background: #fee4e2;
      }
      #buildGrid {
        flex: 1;
        overflow-y: auto;
        display: flex;
        flex-direction: column;
        gap: 6px;
        scrollbar-width: none;
      }
      .buildItem {
        flex: none;
        width: 44px;
        height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 26px;
        border: 2px solid #e5e7ee;
        border-radius: 12px;
        background: #f7f8fc;
        cursor: pointer;
        transition: border-color 0.15s, transform 0.15s;
      }
      .buildItem:hover {
        border-color: #b9c6ea;
        transform: translateX(-2px);
      }
      .buildItem.selected {
        border-color: #ff4fd0;
        background: #fff0fb;
      }
      .buildItem.poor {
        opacity: 0.45;
        cursor: not-allowed;
      }
      #labEdit {
        display: none;
      }
      #panel.editable #labEdit {
        display: block;
      }
      #panel.editable #labStatic,
      #panel.bare #labStatic {
        display: none;
      }
      #panel.editable #labName,
      body.megaFocus #labName {
        cursor: text;
        border-radius: 6px;
        outline: none;
        padding: 0 4px;
        margin-left: -4px;
        transition: background 0.15s;
      }
      #panel.editable #labName:hover,
      body.megaFocus #labName:hover {
        background: #f3f6ff;
      }
      #panel.editable #labName:focus,
      body.megaFocus #labName:focus {
        background: #fff7fd;
        box-shadow: inset 0 -2px 0 #ff4fd0;
      }
      #labEdit [contenteditable] {
        border-bottom: 1px dashed #c9d3ea;
        padding: 2px 2px;
        border-radius: 4px;
        outline: none;
        transition: background 0.15s;
      }
      #labEdit [contenteditable]:hover {
        background: #f3f6ff;
      }
      #labEdit [contenteditable]:focus {
        background: #fff7fd;
        border-bottom-color: #ff4fd0;
      }
      #labEdit ul {
        margin: 0 0 8px;
        padding-left: 22px;
      }
      #labEdit li {
        line-height: 1.6;
        font-size: 15px;
        color: #374151;
        margin: 2px 0;
      }
      .labAdd {
        border: 2px dashed #c9d3ea;
        background: #f7f8fc;
        color: #2b3a67;
        border-radius: 10px;
        padding: 6px 12px;
        font: 600 13px system-ui, sans-serif;
        cursor: pointer;
        margin-bottom: 8px;
      }
      .labAdd:hover {
        background: #eef2ff;
      }
      .labAdd:disabled {
        opacity: 0.5;
        cursor: default;
        background: #f7f8fc;
      }
      /* block level row: "Level 2 of 4" with upgrade / downgrade buttons */
      #blockLevel {
        display: none;
        align-items: center;
        gap: 8px;
        margin: 0 0 10px;
      }
      #panel.leveled #blockLevel {
        display: flex;
      }
      #blockLevel span {
        flex: 1;
        font: 600 13px system-ui, sans-serif;
        color: #6b7280;
      }
      #blockLevel button {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 6px 12px;
        font: 700 13px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 3px 0 #c9d3ea;
        transition: background 0.15s, transform 0.15s;
      }
      #blockLevel button:hover:not(:disabled) {
        background: #f3f6ff;
        transform: translateY(-1px);
      }
      #blockLevel button:disabled {
        opacity: 0.45;
        cursor: default;
        box-shadow: none;
      }
      /* a research director: name + approach + style on one read-only card */
      #labEdit li.researcher {
        list-style: none;
        margin: 0 0 8px -22px;
        padding: 8px 10px;
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        background: #fafbff;
        line-height: 1.4;
      }
      #labEdit .rName {
        font-weight: 700;
        color: #1f2937;
        border-bottom: none;
      }
      /* lab categories: chips, the lab's own lit up */
      .tags {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin-bottom: 8px;
      }
      .tag {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 999px;
        padding: 3px 10px;
        font: 600 12px system-ui, sans-serif;
        cursor: pointer;
      }
      .tag:hover {
        border-color: #ff4fd0;
      }
      .tag.on {
        background: #ff4fd0;
        border-color: #ff4fd0;
        color: #fff;
      }
      /* a lab's own chip carries a small × that takes the category off the lab */
      #tagsEdit .tag {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        cursor: default;
      }
      #tagsEdit .tag .x {
        cursor: pointer;
        opacity: 0.7;
        font-weight: 800;
        line-height: 1;
      }
      #tagsEdit .tag .x:hover {
        opacity: 1;
      }
      #tagsEmpty {
        color: #9199b3;
        font: 500 12px system-ui, sans-serif;
      }
      /* the category picker under "+ Add category": a filter box over the categories
         the lab doesn't have yet, plus a "create" chip for a name that matches none */
      #tagPicker {
        margin: -4px 0 8px;
        padding: 8px;
        border: 2px solid #ff4fd0;
        border-radius: 10px;
        background: #fff;
      }
      #tagPicker[hidden] {
        display: none;
      }
      #tagNew {
        display: block;
        width: 100%;
        box-sizing: border-box;
        margin: 0 0 8px;
        padding: 6px 10px;
        border: 2px solid #dfe6f5;
        border-radius: 8px;
        font: 500 13px system-ui, sans-serif;
        outline: none;
      }
      #tagNew:focus {
        border-color: #ff4fd0;
      }
      #tagOptions {
        margin-bottom: 0;
      }
      #tagOptions .tag.create {
        border-style: dashed;
      }
      #tagOptions .none {
        color: #9199b3;
        font: 500 12px system-ui, sans-serif;
      }
      /* "Look Inside" — opens the office view of the focused building */
      #lookInside {
        display: block;
        width: 100%;
        margin: 8px 0 4px;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 12px 16px;
        font: 700 16px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 4px 0 #c9d3ea;
        transition: background 0.15s, transform 0.15s;
      }
      #lookInside:hover {
        background: #f3f6ff;
        transform: translateY(-1px);
      }
      body.inside #lookInside {
        border-color: #ff4fd0;
        background: #fff0fb;
      }
      /* Primus connection: mega tower panel only, and only for the player's own
         cities (toggled from JS with the [hidden] attribute; see focusMega). */
      #citySettings {
        display: none;
      }
      /* :not([hidden]) keeps this from outranking the [hidden] attribute JS uses to
         keep the section off showcase cities (an id selector otherwise beats the
         browser's very low-specificity `[hidden] { display: none }` rule) */
      body.megaFocus #citySettings:not([hidden]) {
        display: block;
      }
      .settingsField {
        display: block;
        margin: 0 0 10px;
      }
      .settingsField span {
        display: block;
        font: 600 12px system-ui, sans-serif;
        color: #6b7280;
        margin-bottom: 4px;
      }
      /* the tower model picker (moved out of the HUD); only the tower panel has one */
      #towerPick {
        display: none;
      }
      body.megaFocus #towerPick {
        display: block;
      }
      #towerPick select {
        cursor: pointer;
      }
      #towerPick .settingsField {
        margin-bottom: 0; /* the heading above it already spaces the section */
      }
      .settingsField input,
      .settingsField select {
        display: block;
        width: 100%;
        box-sizing: border-box;
        padding: 8px 10px;
        border: 2px solid #dfe6f5;
        border-radius: 10px;
        font: 500 14px system-ui, sans-serif;
        color: #1f2430;
        outline: none;
        transition: border-color 0.15s, background 0.15s;
      }
      .settingsField input:hover,
      .settingsField select:hover {
        background: #f3f6ff;
      }
      .settingsField input:focus,
      .settingsField select:focus {
        background: #fff7fd;
        border-color: #ff4fd0;
      }
      /* connected cities collapse the form to this one line; it opens #csModal */
      #csConnectedLine {
        display: flex;
        align-items: center;
        gap: 10px;
        width: 100%;
        box-sizing: border-box;
        padding: 12px 14px;
        border: 2px solid #dfe6f5;
        border-radius: 12px;
        background: #f7f9ff;
        font: 500 14px system-ui, sans-serif;
        color: #1f2430;
        text-align: left;
        cursor: pointer;
        transition: border-color 0.15s, background 0.15s;
      }
      #csConnectedLine[hidden] {
        display: none;
      }
      #csConnectedLine:hover {
        background: #eef3ff;
        border-color: #b9c8ee;
      }
      #csConnectedLine .csDot {
        flex: none;
        width: 9px;
        height: 9px;
        border-radius: 50%;
        background: #1a9c6a;
        box-shadow: 0 0 0 3px rgba(26, 156, 106, 0.18);
      }
      #csConnectedLine .csConnectedText {
        flex: 1;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        color: #6b7280;
      }
      #csConnectedLine .csConnectedText b {
        font-weight: 600;
        color: #1f2430;
      }
      #csConnectedLine .csChevron {
        flex: none;
        color: #9aa4bd;
        font-size: 18px;
        line-height: 1;
      }
      #csStatus {
        margin-top: 4px;
        font-size: 13px;
        color: #6b7280;
      }
      #csStatus:empty {
        display: none;
      }
      #csStatus.warn {
        color: #c2410c;
      }
      /* ---- founding a lab: shown instead of #labEdit/#labStatic's auto-fiction for a
         connected player city's commercial block with no lab yet (see focusBlock/
         showFoundLabForm in main.js). Reuses .settingsField for the plain inputs. */
      #labFound {
        display: none;
      }
      #panel.founding #labFound {
        display: block;
      }
      #labFound textarea,
      #rfpCard textarea {
        display: block;
        width: 100%;
        box-sizing: border-box;
        min-height: 64px;
        padding: 8px 10px;
        border: 2px solid #dfe6f5;
        border-radius: 10px;
        font: 500 14px system-ui, sans-serif;
        color: #1f2430;
        outline: none;
        resize: vertical;
        transition: border-color 0.15s, background 0.15s;
      }
      #labFound textarea:hover,
      #rfpCard textarea:hover {
        background: #f3f6ff;
      }
      #labFound textarea:focus,
      #rfpCard textarea:focus {
        background: #fff7fd;
        border-color: #ff4fd0;
      }
      #lfSubmit {
        display: block;
        width: 100%;
        margin: 4px 0 4px;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 12px 16px;
        font: 700 16px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 4px 0 #c9d3ea;
        transition: background 0.15s, transform 0.15s;
      }
      #lfSubmit:hover:not(:disabled) {
        background: #f3f6ff;
        transform: translateY(-1px);
      }
      #lfSubmit:disabled {
        opacity: 0.5;
        cursor: default;
        box-shadow: none;
      }
      #lfStatus,
      #rfpStatus {
        margin-top: 6px;
        font-size: 13px;
        color: #6b7280;
      }
      #lfStatus.warn,
      #rfpStatus.warn {
        color: #c2410c;
      }
      /* ---- requests for proposals: the Call-for-Proposals Office floor (#rfpSection,
         shown only for a connected player city — see focusMega/saveCitySettings in
         main.js), its New Proposal form (#rfpModal, further down) and the lab panel's
         open-requests list (#labRfps). Status chips (.chip) are shared between both. */
      #rfpPoolBalance {
        display: inline; /* .settingsField's own span rule would stack it under the label */
        font-weight: 500;
        text-transform: none;
        letter-spacing: normal;
        color: #9199b3;
      }
      /* the office's three titled sections; their h2s are nested one level deeper than
         the pane rule that hides a pane's own heading (#floorBody > .floorPane > div > h2),
         so they show */
      .rfpOfficeSection {
        margin: 0 0 28px;
      }
      .rfpOfficeSection h2 {
        margin: 0 0 10px;
        font-size: 17px;
        color: #2b3a67;
        letter-spacing: -0.01em;
      }
      .rfpOfficeHead {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
      }
      .rfpOfficeHead h2 {
        margin: 0;
      }
      #rfpNew {
        flex: none;
        border: 2px solid #6c7bff;
        background: #6c7bff;
        color: #fff;
        border-radius: 10px;
        padding: 8px 14px;
        font: 600 14px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 3px 0 #4c5bd9;
        transition: background 0.15s, transform 0.15s;
      }
      #rfpNew:hover {
        background: #5765e8;
        transform: translateY(-1px);
      }
      .rfpOfficeBlurb {
        margin: 8px 0 0;
        font-size: 14px;
        line-height: 1.55;
        color: #6b7280;
      }
      #rfpOfficeStatus {
        margin-top: 6px;
        font-size: 13px;
        color: #6b7280;
      }
      #rfpOfficeStatus:empty {
        display: none;
      }
      #rfpOfficeStatus.warn {
        color: #c2410c;
      }
      #labRfpList {
        margin-top: 10px;
      }
      .rfpOfficeList .none,
      #labRfpList .none {
        font-size: 13px;
        color: #9199b3;
      }
      .rfpRow {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        margin-bottom: 8px;
        background: #fafbff;
        overflow: hidden;
      }
      .rfpRowHead {
        display: block;
        width: 100%;
        box-sizing: border-box;
        text-align: left;
        border: 0;
        background: none;
        padding: 10px 12px;
        cursor: pointer;
        font: inherit;
      }
      .rfpRowHead:hover {
        background: #f3f6ff;
      }
      .rfpRowTitle {
        font-weight: 700;
        color: #1f2937;
      }
      .rfpRowMeta {
        font-size: 12px;
        color: #6b7280;
        margin-top: 2px;
      }
      .proposalRow {
        padding: 8px 0;
        border-bottom: 1px solid #eef1f8;
      }
      .proposalRow:last-child {
        border-bottom: 0;
      }
      .proposalRowHead {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
      }
      .proposalWho {
        font-weight: 600;
        font-size: 13px;
        color: #374151;
      }
      .proposalLine {
        margin-top: 4px;
        font-size: 12px;
        color: #6b7280;
      }
      .proposalLine.warn {
        color: #c2410c;
      }
      /* proposal / notice status chip — pending pulses gently so a live poll reads
         as "still waiting" rather than stalled; see watchRfpPending in main.js. */
      .chip {
        display: inline-flex;
        flex: none;
        align-items: center;
        padding: 3px 9px;
        border-radius: 999px;
        font: 700 11px system-ui, sans-serif;
        text-transform: uppercase;
        letter-spacing: 0.04em;
      }
      .chip-pending {
        background: #eef2ff;
        color: #2b3a67;
        animation: chipPulse 1.6s ease-in-out infinite;
      }
      .chip-arrived {
        background: #eafaf3;
        color: #1a9c6a;
      }
      .chip-declined {
        background: #f3f4f8;
        color: #6b7280;
      }
      .chip-failed {
        background: #fff1ea;
        color: #c2410c;
      }
      .chip-unavailable {
        background: #f3f4f8;
        color: #9ca3af;
      }
      @keyframes chipPulse {
        0%,
        100% {
          opacity: 1;
        }
        50% {
          opacity: 0.5;
        }
      }
      .labRfpRow {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 8px;
        background: #fafbff;
      }
      .labRfpTitle {
        font-weight: 700;
        color: #1f2937;
      }
      .labRfpMeta {
        font-size: 12px;
        color: #6b7280;
        margin: 2px 0 8px;
      }
      .labRfpResearchers {
        display: flex;
        flex-direction: column;
        margin-top: 8px;
      }
      .labRfpResearcherRow {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
        padding: 6px 0;
        border-top: 1px solid #eef1f8;
      }
      .labRfpResearcherName {
        font-weight: 600;
        font-size: 13px;
        color: #374151;
        flex: 1 1 auto;
        min-width: 90px;
      }
      .labRfpProposalLine {
        font-size: 12px;
        color: #6b7280;
        flex-basis: 100%;
      }
      .labRfpProposalLine.warn {
        color: #c2410c;
      }
      .chip-score {
        background: #f3f4f8;
        color: #2b3a67;
      }
      .chip-funded {
        background: #fff7e0;
        color: #b7791f;
      }
      .labRfpFeedbackToggle {
        flex-basis: 100%;
        align-self: flex-start;
        border: 0;
        background: none;
        padding: 0;
        margin-top: 2px;
        font: 600 11px system-ui, sans-serif;
        color: #6b7280;
        cursor: pointer;
      }
      .labRfpFeedbackToggle:hover {
        color: #2b3a67;
      }
      .labRfpFeedback {
        flex-basis: 100%;
        display: none;
      }
      .labRfpFeedback.open {
        display: block;
        margin-top: 4px;
      }
      /* ---- requests for proposals: judging + awards, once a proposal has arrived
         (tower panel — see renderJudgingAwardSection in main.js). Reuses .labAdd for
         primary buttons and introduces .ghostBtn for secondary ones (Cancel, Resume's
         sibling Abandon, Re-run judging). */
      .judgingSection {
        margin-top: 10px;
        padding-top: 10px;
        border-top: 1px solid #e3e8f5;
      }
      .judgingHeading {
        font: 700 12px system-ui, sans-serif;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: #9199b3;
        margin-bottom: 8px;
      }
      .judgeControlRow {
        margin-bottom: 4px;
      }
      /* a judging round mid-flight (renderJudgingProgress): the count, a bar that
         fills as verdicts land, and one line on what to expect */
      .judgingProgress {
        margin: 2px 0 10px;
        padding: 10px 12px;
        border: 1px solid #dfe6f5;
        border-radius: 10px;
        background: #f6f8fe;
      }
      .judgingProgressLine {
        display: flex;
        align-items: center;
        gap: 8px;
        font: 600 13px system-ui, sans-serif;
        color: #3b4661;
      }
      .judgingProgressDot {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: #4f7cf5;
        animation: judgingPulse 1.4s ease-in-out infinite;
      }
      @keyframes judgingPulse {
        0%, 100% { opacity: 1; transform: scale(1); }
        50% { opacity: 0.35; transform: scale(0.7); }
      }
      @media (prefers-reduced-motion: reduce) {
        .judgingProgressDot { animation: none; }
      }
      .judgingProgressBar {
        height: 6px;
        margin: 8px 0 6px;
        border-radius: 3px;
        background: #e3e8f5;
        overflow: hidden;
      }
      .judgingProgressFill {
        height: 100%;
        border-radius: 3px;
        background: #4f7cf5;
        transition: width 0.4s ease;
      }
      .judgingProgressNote {
        font: 12px/1.4 system-ui, sans-serif;
        color: #7c86a3;
      }
      /* verdicts exist but the panel is short and nothing is running */
      .judgingShort {
        margin: 2px 0 8px;
        font: 600 13px system-ui, sans-serif;
        color: #a8641d;
      }
      /* an open RFP's proposals, sorted under three tabs (renderOpenProposalTabs);
         a pink underline on the lit one */
      .proposalTabs {
        display: flex;
        gap: 2px;
        margin-bottom: 10px;
        border-bottom: 2px solid #dfe6f5;
      }
      .proposalTab {
        border: 0;
        background: none;
        margin-bottom: -2px;
        padding: 6px 10px 8px;
        border-bottom: 3px solid transparent;
        font: 700 13px system-ui, sans-serif;
        color: #6b7280;
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        gap: 6px;
        transition: color 0.15s, border-color 0.15s;
      }
      .proposalTab:hover {
        color: #2b3a67;
      }
      .proposalTab.on {
        color: #2b3a67;
        border-bottom-color: #ff4fd0;
      }
      .proposalTabCount {
        min-width: 18px;
        height: 18px;
        padding: 0 5px;
        border-radius: 9px;
        background: #e9edf8;
        color: #6b7280;
        font: 700 11px/18px system-ui, sans-serif;
        text-align: center;
      }
      .proposalTab.on .proposalTabCount {
        background: #ff4fd0;
        color: #fff;
      }
      .ghostBtn {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #6b7280;
        border-radius: 10px;
        padding: 6px 12px;
        font: 600 13px system-ui, sans-serif;
        cursor: pointer;
        margin: 0 8px 8px 0;
      }
      .ghostBtn:hover:not(:disabled) {
        background: #f3f6ff;
        color: #2b3a67;
      }
      .ghostBtn:disabled {
        opacity: 0.5;
        cursor: default;
      }
      .ghostBtn.warnBtn {
        color: #c2410c;
        border-color: #fcd9c4;
      }
      .ghostBtn.warnBtn:hover:not(:disabled) {
        background: #fff1ea;
      }
      .rankedTable {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        overflow: hidden;
        margin-bottom: 10px;
        background: #fafbff;
      }
      .rankedTableHead {
        display: grid;
        grid-template-columns: 1.2fr 1.2fr 0.6fr 0.8fr 28px;
        gap: 6px;
        padding: 6px 12px;
        font: 700 11px system-ui, sans-serif;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        color: #9199b3;
        border-bottom: 1px solid #eef1f8;
      }
      .rankedRow {
        border-bottom: 1px solid #eef1f8;
      }
      .rankedRow:last-child {
        border-bottom: 0;
      }
      .rankedRowHead {
        display: grid;
        grid-template-columns: 1.2fr 1.2fr 0.6fr 0.8fr 28px;
        gap: 6px;
        width: 100%;
        box-sizing: border-box;
        text-align: left;
        border: 0;
        background: none;
        padding: 8px 12px;
        cursor: pointer;
        font: inherit;
      }
      .rankedRowHead:hover {
        background: #f3f6ff;
      }
      .rankedCell {
        font-size: 13px;
        color: #374151;
        align-self: center;
      }
      .rankedLab {
        font-weight: 700;
        color: #1f2937;
      }
      .rankedScoreCell {
        font-weight: 700;
        color: #2b3a67;
      }
      .rankedAskedCell {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        flex-wrap: wrap;
      }
      .chip-variant {
        background: #eef2ff;
        color: #3730a3;
      }
      .rankedRowDetail {
        display: none;
        padding: 0 12px 10px;
      }
      .rankedRowDetail.open {
        display: block;
      }
      .judgeVerdictRow {
        padding: 6px 0;
        border-top: 1px solid #eef1f8;
      }
      .judgeVerdictRow:first-child {
        border-top: 0;
      }
      .judgeVerdictHead {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
      }
      .judgeName {
        font-weight: 700;
        font-size: 12px;
        color: #1f2937;
      }
      .judgeScore {
        font-weight: 700;
        font-size: 12px;
        color: #1a9c6a;
      }
      .judgeScore.judgeErr {
        color: #c2410c;
        text-transform: none;
        font-weight: 600;
      }
      .judgeVerdict {
        font-weight: 600;
        font-size: 12px;
        color: #2b3a67;
        margin-top: 2px;
      }
      .judgeFeedback {
        font-size: 12px;
        color: #6b7280;
        margin-top: 2px;
      }
      .judgeFeedback.warn {
        color: #c2410c;
      }
      .awardControls {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        padding: 10px 12px;
        background: #fafbff;
      }
      .awardControlsHeading {
        font: 700 12px system-ui, sans-serif;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: #9199b3;
        margin-bottom: 6px;
      }
      .awardRow {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 5px 0;
        border-top: 1px solid #eef1f8;
      }
      .awardRow:first-of-type {
        border-top: 0;
      }
      .awardRow label {
        display: flex;
        align-items: center;
        gap: 6px;
        flex: 1 1 auto;
        min-width: 0;
      }
      .awardRowWho {
        font-weight: 600;
        font-size: 13px;
        color: #374151;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .awardRowScore {
        flex: none;
        font-size: 12px;
        color: #6b7280;
      }
      .awardUsdInput {
        flex: none;
        width: 72px;
        box-sizing: border-box;
        padding: 4px 8px;
        border: 2px solid #dfe6f5;
        border-radius: 8px;
        font: 600 13px system-ui, sans-serif;
        color: #1f2430;
        outline: none;
      }
      .awardUsdInput:disabled {
        background: #f3f4f8;
        color: #9ca3af;
      }
      .awardUsdInput:focus:not(:disabled) {
        border-color: #ff4fd0;
      }
      .awardAllocLine {
        margin: 8px 0;
        font-size: 12px;
        font-weight: 600;
        color: #6b7280;
      }
      .awardAllocLine.warn {
        color: #c2410c;
      }
      .grantsArea {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        padding: 10px 12px;
        background: #fafbff;
      }
      .grantsHeading {
        font: 700 12px system-ui, sans-serif;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: #9199b3;
        margin-bottom: 6px;
      }
      .grantRow {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
        padding: 6px 0;
        border-top: 1px solid #eef1f8;
      }
      .grantRow:first-of-type {
        border-top: 0;
      }
      .grantRowWho {
        font-weight: 600;
        font-size: 13px;
        color: #374151;
        flex: 1 1 auto;
        min-width: 90px;
      }
      .grantCountdown {
        font-size: 12px;
        color: #9199b3;
      }
      .grantError {
        flex-basis: 100%;
        font-size: 12px;
        color: #c2410c;
      }
      .chip-grant-pending {
        background: #eef2ff;
        color: #2b3a67;
        animation: chipPulse 1.6s ease-in-out infinite;
      }
      .chip-grant-granted {
        background: #eafaf3;
        color: #1a9c6a;
      }
      .chip-grant-unresolved {
        background: #fff7e0;
        color: #b7791f;
      }
      .chip-grant-failed {
        background: #fff1ea;
        color: #c2410c;
      }
      /* An `unresolved` grant with no retry countdown — primus's terminal "needs a
         human on our side" case (see isUnresolvedTerminal in main.js). Same failed
         palette: Resume won't help here, only Abandon will. */
      .chip-grant-unresolved-terminal {
        background: #fff1ea;
        color: #c2410c;
      }
      .chip-grant-unavailable {
        background: #f3f4f8;
        color: #9ca3af;
      }
      .chip-grant-abandoned {
        background: #f3f4f8;
        color: #6b7280;
      }
      .awardNote {
        margin-top: 8px;
        padding-top: 8px;
        border-top: 1px solid #eef1f8;
        font-size: 12px;
        color: #6b7280;
      }
      /* one founding researcher: name/approach/style + the maverick slider, tinted by
         --maverick (set from JS's one gradient helper — see applyMaverickTint). */
      .foundRow {
        border: 1px solid #e3e8f5;
        border-left: 6px solid var(--maverick, #dfe6f5);
        border-radius: 10px;
        padding: 10px 12px 12px;
        margin-bottom: 10px;
        background: #fafbff;
        transition: border-left-color 0.15s;
      }
      .foundRow .frTop {
        display: flex;
        gap: 8px;
        align-items: center;
      }
      .foundRow .frTop input[type="text"] {
        flex: 1;
        min-width: 0;
        box-sizing: border-box;
        padding: 7px 9px;
        border: 2px solid #dfe6f5;
        border-radius: 8px;
        font: 600 14px system-ui, sans-serif;
        color: #1f2430;
        outline: none;
      }
      .foundRow .frTop input[type="text"]:focus {
        background: #fff7fd;
        border-color: #ff4fd0;
      }
      .foundRow .frRemove {
        flex: none;
        border: 0;
        background: #f3f4f8;
        width: 26px;
        height: 26px;
        border-radius: 50%;
        font-size: 14px;
        line-height: 1;
        cursor: pointer;
        color: #6b7280;
      }
      .foundRow .frRemove:hover {
        background: #ffe3f4;
        color: #c2410c;
      }
      .foundRow .frMeta {
        display: flex;
        gap: 6px;
        margin-top: 6px;
      }
      .foundRow .frMeta input[type="text"] {
        flex: 1;
        min-width: 0;
        box-sizing: border-box;
        padding: 6px 8px;
        border: 1px solid #dfe6f5;
        border-radius: 8px;
        font: 500 12px system-ui, sans-serif;
        color: #374151;
        outline: none;
      }
      .foundRow .frMeta input[type="text"]:focus {
        background: #fff7fd;
        border-color: #ff4fd0;
      }
      /* the approach: a few lines of markdown, under the style */
      .foundRow textarea.frApproach {
        display: block;
        width: 100%;
        box-sizing: border-box;
        margin-top: 6px;
        padding: 6px 8px;
        border: 1px solid #dfe6f5;
        border-radius: 8px;
        background: #fff;
        font: 500 12px/1.45 system-ui, sans-serif;
        color: #374151;
        resize: vertical;
        min-height: 40px;
        outline: none;
      }
      .foundRow textarea.frApproach:focus {
        background: #fff7fd;
        border-color: #ff4fd0;
      }
      /* the role picker: three pills, one lit, in the role's own colour */
      .foundRow .frRole {
        display: flex;
        gap: 6px;
        margin-top: 8px;
      }
      .foundRow .frRoleBtn {
        flex: 1;
        border: 2px solid #dfe6f5;
        background: #fff;
        border-radius: 999px;
        padding: 4px 0;
        font: 700 11px system-ui, sans-serif;
        color: #6b7280;
        cursor: pointer;
        transition: background 0.15s, border-color 0.15s, color 0.15s;
      }
      .foundRow .frRoleBtn:hover {
        border-color: #c3d4ff;
      }
      .foundRow .frRoleBtn.on.maverick {
        background: #fff0fb;
        border-color: #ff4fd0;
        color: #8a1b66;
      }
      .foundRow .frRoleBtn.on.follower {
        background: #eef2ff;
        border-color: #6f8ff5;
        color: #2b3a67;
      }
      .foundRow .frRoleBtn.on.skeptic {
        background: #fff7e6;
        border-color: #f0a83a;
        color: #7a4b00;
      }
      /* a researcher's role, wherever they are listed */
      .roleTag {
        display: inline-block;
        vertical-align: 1px;
        margin-left: 6px;
        padding: 1px 7px;
        border-radius: 999px;
        font: 700 9px system-ui, sans-serif;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        white-space: nowrap;
      }
      .roleTag.maverick {
        background: #fff0fb;
        color: #8a1b66;
      }
      .roleTag.follower {
        background: #eef2ff;
        color: #2b3a67;
      }
      .roleTag.skeptic {
        background: #fff7e6;
        color: #7a4b00;
      }
      .foundRow .frMaverick {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-top: 8px;
        font: 600 11px system-ui, sans-serif;
        color: #6b7280;
      }
      .foundRow .frMaverick input[type="range"] {
        flex: 1;
        accent-color: var(--maverick, #ff4fd0);
      }
      .foundRow .frMaverick .frMaverickVal {
        min-width: 28px;
        text-align: right;
        color: #1f2430;
      }
      /* ---- provisioning status strip (top of #labEdit): pending while primus is
         being contacted, done once the workspace is connected, failed with a Retry
         button that resumes from src/labs/provision.ts's state machine. */
      #provisionStrip {
        display: none;
      }
      #provisionStrip.show {
        display: flex;
        align-items: center;
        gap: 10px;
        margin: 0 0 18px;
        padding: 10px 14px;
        border-radius: 12px;
        font: 600 13px system-ui, sans-serif;
      }
      #provisionStrip span {
        flex: 1;
        line-height: 1.4;
      }
      #provisionStrip.pending {
        background: #eef2ff;
        color: #2b3a67;
      }
      #provisionStrip.done {
        background: #eafaf3;
        color: #1a9c6a;
      }
      #provisionStrip.failed {
        background: #fff1ea;
        color: #c2410c;
      }
      #provisionStrip button {
        flex: none;
        margin: 0;
      }
      /* maverick tint on a founded lab's read-only researcher rows — the .maverick
         class (and --maverick) is only ever added by JS for a lab that actually went
         through the founding flow (see renderResearchers), so a plain/cosmetic lab's
         rows are untouched by this rule: byte-identical to before this feature existed. */
      #labEdit li.researcher.maverick {
        border-left-width: 6px;
        border-left-color: var(--maverick, #e3e8f5);
      }
      /* interior view: a scrolling list of offices over the whole window, the lab panel
         included (‹ Outside, or Esc, is the way back to it) */
      #interior {
        position: fixed;
        inset: 0;
        background: #eef1f8;
        color: #1f2430;
        z-index: 11; /* over the panel (10), under what opens from in here (15 and up) */
        display: none;
        flex-direction: column;
        box-sizing: border-box;
      }
      body.inside #interior {
        display: flex;
      }
      #interiorHead {
        flex: none;
        display: flex;
        align-items: center;
        gap: 16px;
        padding: 18px 28px;
        background: #fff;
        border-bottom: 3px solid #dfe6f5;
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
      }
      #interiorHead h1 {
        margin: 0;
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: 26px;
        color: #2b3a67;
        letter-spacing: 0.02em;
        line-height: 1;
        padding-top: 4px;
      }
      #interiorHead .count {
        margin-left: auto;
        font-size: 13px;
        color: #6b7280;
        text-transform: uppercase;
        letter-spacing: 0.12em;
      }
      #interiorBack {
        white-space: nowrap;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 12px;
        padding: 8px 14px;
        font: 700 15px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 4px 0 #c9d3ea;
      }
      #interiorBack:hover {
        background: #f3f6ff;
      }
      #offices {
        flex: 1;
        overflow-y: auto;
        padding: 28px 36px 60px;
        display: flex;
        flex-direction: column;
        gap: 28px;
      }
      .office {
        display: flex;
        align-items: flex-start;
        gap: 24px;
      }
      /* the 16x10 tile placeholder that will hold the office's sprites */
      .officeGrid {
        --tile: 16px;
        flex: none;
        width: calc(var(--tile) * 18);
        height: calc(var(--tile) * 12);
        display: grid;
        grid-template-columns: repeat(18, var(--tile));
        grid-template-rows: repeat(12, var(--tile));
        background:
          linear-gradient(#e1e6f2 1px, transparent 1px) 0 0 / var(--tile) var(--tile),
          linear-gradient(90deg, #e1e6f2 1px, transparent 1px) 0 0 / var(--tile) var(--tile),
          #f7f8fc;
        border: 3px solid #c9d3ea;
        border-radius: 8px;
        box-shadow: 0 4px 0 #c9d3ea;
        image-rendering: pixelated;
        overflow: hidden;
        position: relative;
      }
      /* ---- one floor, opened from the floor list: fills the interior side ---- */
      #interior.floorOpen #offices {
        display: none;
      }
      #floorView {
        flex: 1;
        min-height: 0;
        display: none;
        flex-direction: column;
      }
      #interior.floorOpen #floorView {
        display: flex;
      }
      #floorHead {
        flex: none;
        display: flex;
        align-items: center;
        gap: 14px;
        padding: 18px 36px 0;
      }
      #floorHead h1 {
        margin: 0;
        font-size: 22px;
        color: #2b3a67;
        letter-spacing: -0.01em;
      }
      /* back from a page inside the floor (an RFP's page) to the floor's own list */
      #floorUp {
        white-space: nowrap;
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 6px 12px;
        font: 600 14px system-ui, sans-serif;
        cursor: pointer;
      }
      #floorUp:hover {
        background: #f3f6ff;
      }
      /* an RFP's own page on the Grant Review Board (#rfpPage): the title and its
         standing line up top, then the same detail a board row used to unfold */
      .rfpPageHead {
        padding: 6px 0 12px;
        border-bottom: 1px solid #e3e8f5;
        margin-bottom: 10px;
      }
      .rfpPageHead h2 {
        margin: 0;
        font: 700 18px system-ui, sans-serif;
        color: #1f2937;
        letter-spacing: -0.01em;
      }
      #floorBody {
        flex: 1;
        overflow-y: auto;
        padding: 8px 36px 60px;
        max-width: 760px;
        box-sizing: border-box;
      }
      /* the panel's own h2 rule doesn't reach in here, and the floor head already
         names what this is */
      #floorBody > .floorPane > div > h2 {
        display: none;
      }
      #floorGate {
        color: #6b7280;
        font-size: 14px;
        line-height: 1.6;
      }
      /* a floor with something behind it says so and opens on click; the rest are
         plans on a wall */
      .floorRow.openable .officeMeta h3 {
        cursor: pointer;
      }
      .floorRow.openable .officeMeta h3:hover {
        color: #ff4fd0;
      }
      .floorRow.openable .floorPlan {
        cursor: pointer;
        transition: border-color 0.15s, transform 0.15s;
      }
      .floorRow.openable .floorPlan:hover {
        border-color: #ff4fd0;
        transform: translateY(-1px);
      }
      .floorEnter {
        margin-top: 12px;
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 6px 12px;
        font: 600 13px system-ui, sans-serif;
        cursor: pointer;
      }
      .floorEnter:hover {
        background: #f3f6ff;
      }
      /* the tower's floors are rooms of the same size as a researcher's office (the
         editor draws 18x12), so .officeGrid's box is theirs too */
      .floorRow .officeMeta {
        max-width: 46ch;
      }
      .officeGrid img {
        image-rendering: pixelated;
        width: var(--tile);
        height: var(--tile);
      }
      .officeGrid .empty {
        position: absolute;
        inset: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #b2bbd1;
        font: 600 13px system-ui, sans-serif;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        pointer-events: none;
      }
      .officeMeta {
        padding-top: 6px;
        min-width: 0;
      }
      .officeMeta h3 {
        margin: 0 0 4px;
        font-size: 19px;
        color: #1f2430;
      }
      /* avatar on the left, spanning the name and "Office N" stacked beside it */
      .officeMeta .officeHead {
        display: flex;
        align-items: center;
        gap: 12px;
      }
      .officeMeta .officeTitles {
        min-width: 0;
      }
      .officeMeta .officeHead h3 {
        margin: 0 0 2px;
      }
      /* the researcher's portrait (an img from /assets/gemini-avatars), or — for a row
         with no avatar yet — their initials on a square tinted per researcher
         (--avatarHue set by JS) */
      .officeAvatar {
        position: relative;
        flex: none;
        width: 64px;
        height: 64px;
        border-radius: 10px;
        overflow: hidden;
        display: flex;
        align-items: center;
        justify-content: center;
        background: hsl(var(--avatarHue, 220) 70% 88%);
        color: hsl(var(--avatarHue, 220) 45% 32%);
        font: 700 20px system-ui, sans-serif;
        letter-spacing: 0.02em;
        user-select: none;
      }
      /* a researcher in the player's own lab: hovering the portrait shows a pen, and a
         click opens the avatar picker */
      .officeAvatar.pickable {
        cursor: pointer;
      }
      .officeAvatar.pickable::after {
        content: "✎";
        position: absolute;
        inset: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(31, 36, 48, 0.45);
        color: #fff;
        font: 700 26px system-ui, sans-serif;
        opacity: 0;
        transition: opacity 0.12s;
      }
      .officeAvatar.pickable:hover::after {
        opacity: 1;
      }
      .officeAvatar.hasImg {
        background: none;
      }
      .officeAvatar img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      /* ---- the avatar picker ---- */
      #avatarPicker {
        position: fixed;
        inset: 0;
        z-index: 18; /* over the interior list and the researcher modal (15), under the office editor (20) */
        display: none;
        align-items: center;
        justify-content: center;
        background: rgba(31, 36, 48, 0.55);
        backdrop-filter: blur(3px);
      }
      body.avatarPicking #avatarPicker {
        display: flex;
      }
      #apCard {
        width: min(720px, 92vw);
        max-height: 86vh;
        background: #fff;
        color: #1f2430;
        border-radius: 22px;
        box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
        padding: 22px 26px 24px;
        display: flex;
        flex-direction: column;
        gap: 14px;
        font-family: system-ui, sans-serif;
      }
      #apHead {
        display: flex;
        align-items: center;
        gap: 10px;
      }
      #apHead h1 {
        margin: 0;
        flex: 1;
        font-size: 20px;
        line-height: 1.2;
      }
      #apHead h1 span {
        font-weight: 500;
        color: #6b7280;
      }
      #apRandom {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 999px;
        padding: 6px 12px;
        font: 600 13px system-ui, sans-serif;
        cursor: pointer;
      }
      #apRandom:hover {
        border-color: #ff4fd0;
      }
      #apClose {
        border: none;
        background: none;
        font: 700 26px system-ui, sans-serif;
        line-height: 1;
        color: #6b7280;
        cursor: pointer;
        padding: 0 4px;
      }
      #apClose:hover {
        color: #1f2430;
      }
      #apGrid {
        overflow-y: auto;
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
        gap: 10px;
        padding: 4px;
      }
      #apGrid button {
        aspect-ratio: 1;
        padding: 0;
        border: 3px solid transparent;
        border-radius: 12px;
        background: none;
        overflow: hidden;
        cursor: pointer;
        transition: transform 0.12s, border-color 0.12s;
      }
      #apGrid button img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      #apGrid button:hover {
        transform: translateY(-2px);
        border-color: #c9d3ea;
      }
      #apGrid button.on {
        border-color: #ff4fd0;
      }
      .officeMeta span {
        display: block;
        font-size: 13px;
        color: #6b7280;
      }
      /* the director's approach, under "Office N": a plain-text preview, three lines at
         most (the room shows all of it, rendered) */
      .officeMeta .officeTrait {
        margin-top: 6px;
        font-size: 14px;
        color: #4b5563;
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
      }
      /* the only way into the office editor from the list */
      .officeEdit {
        margin-top: 12px;
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 6px 12px;
        font: 700 13px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 3px 0 #c9d3ea;
        transition: background 0.15s, transform 0.15s, border-color 0.15s;
      }
      .officeEdit:hover {
        background: #f3f6ff;
        border-color: #ff4fd0;
        transform: translateY(-1px);
      }
      .officeEdit.icon {
        padding: 6px 10px;
        font-size: 15px;
        line-height: 1;
      }
      /* a director in one of the player's own labs: the name is renamed in place, and a
         click on the approach opens it for editing */
      .officeMeta h3[contenteditable="true"],
      .officeMeta .officeTrait.editable {
        cursor: text;
        outline: none;
        border-radius: 6px;
        padding: 0 6px;
        margin-left: -6px;
        transition: background 0.15s;
      }
      .officeMeta h3[contenteditable="true"]:hover,
      .officeMeta .officeTrait.editable:hover {
        background: #fff;
      }
      .officeMeta h3[contenteditable="true"]:focus {
        background: #fff7fd;
        box-shadow: inset 0 -3px 0 #ff4fd0;
      }
      .officeMeta .officeTrait.editable:empty::before {
        content: attr(data-placeholder);
        color: #a3adc9;
      }
      .officeTraitInput {
        display: block;
        width: min(560px, 100vw - 420px); /* the column is only as wide as what is in it */
        box-sizing: border-box;
        min-height: 72px;
        margin-top: 6px;
        resize: none; /* it grows with what is typed */
        padding: 8px 10px;
        border: 2px solid #ff4fd0;
        border-radius: 10px;
        background: #fff7fd;
        font: 500 14px/1.5 system-ui, sans-serif;
        color: #374151;
        outline: none;
      }
      /* reputation, under "Office N": five small stars, the earned ones lit */
      .officeStars {
        margin-top: 2px;
        font-size: 14px;
        line-height: 1;
        letter-spacing: 1px;
        color: #cfd7ea;
        cursor: default;
      }
      .officeStars b {
        font-weight: inherit;
        color: #f5b301;
      }
      .officeMeta .officeActions {
        display: flex;
        gap: 8px;
        flex-wrap: wrap;
      }
      /* ---- typed confirmation before anything is deleted ---- */
      #confirmModal {
        position: fixed;
        inset: 0;
        z-index: 40; /* above everything: the picker, the panel, the interior, the office editor */
        display: none;
        align-items: center;
        justify-content: center;
        background: rgba(31, 36, 48, 0.6);
        backdrop-filter: blur(3px);
      }
      body.confirming #confirmModal {
        display: flex;
      }
      #cmCard,
      #rnCard {
        width: min(560px, 92vw);
        max-height: 88vh;
        background: #fff;
        color: #1f2430;
        border-radius: 22px;
        box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
        padding: 28px 32px 24px;
        display: flex;
        flex-direction: column;
        gap: 12px;
        font-family: system-ui, sans-serif;
      }
      #cmCard h1,
      #rnCard h1 {
        margin: 0;
        font-size: 24px;
        line-height: 1.2;
      }
      #cmCard p,
      #rnCard p {
        margin: 0;
        font-size: 15px;
        line-height: 1.45;
      }
      #cmEffects {
        margin: 0;
        padding: 10px 14px;
        max-height: 30vh;
        overflow: auto;
        list-style: none;
        background: #f6f7fb;
        border-radius: 12px;
        font-size: 14px;
        line-height: 1.5;
      }
      #cmEffects:empty {
        display: none;
      }
      #cmEffects li b {
        font-weight: 600;
      }
      #cmEffects li span {
        color: #5b6478;
      }
      #cmCard .cmNote {
        color: #5b6478;
        font-size: 13px;
      }
      #cmCard label,
      #rnCard label {
        font-size: 14px;
        display: flex;
        flex-direction: column;
        gap: 6px;
      }
      #cmCard label code {
        font: 600 14px ui-monospace, SFMono-Regular, Menlo, monospace;
        background: #f6f7fb;
        padding: 1px 6px;
        border-radius: 6px;
        user-select: all;
      }
      #cmInput,
      #rnInput {
        font: 16px system-ui, sans-serif;
        padding: 10px 12px;
        border: 2px solid #dfe6f5;
        border-radius: 10px;
        outline: none;
      }
      #cmInput:focus,
      #rnInput:focus {
        border-color: #2b3a67;
      }
      #cmInput.match {
        border-color: #d7263d;
      }
      .cmRow {
        display: flex;
        justify-content: flex-end;
        gap: 10px;
        margin-top: 4px;
      }
      .cmRow button {
        font: 600 15px system-ui, sans-serif;
        padding: 10px 18px;
        border-radius: 10px;
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        cursor: pointer;
      }
      .cmRow button:hover {
        background: #f3f6ff;
      }
      #cmOk {
        border-color: #d7263d;
        background: #d7263d;
        color: #fff;
      }
      #cmOk:hover {
        background: #b81f32;
      }
      #cmOk:disabled {
        opacity: 0.4;
        cursor: not-allowed;
        background: #d7263d;
      }
      /* ---- primus connection details (read-only, from the tower panel's line) ---- */
      #csModal {
        position: fixed;
        inset: 0;
        z-index: 20; /* above the panel it opens from, below the delete confirmation */
        display: none;
        align-items: center;
        justify-content: center;
        background: rgba(31, 36, 48, 0.55);
        backdrop-filter: blur(3px);
      }
      body.csDetails #csModal {
        display: flex;
      }
      #csmCard {
        position: relative;
        width: min(520px, 92vw);
        max-height: 88vh;
        overflow-y: auto;
        background: #fff;
        color: #1f2430;
        border-radius: 22px;
        box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
        padding: 28px 32px 24px;
        font-family: system-ui, sans-serif;
      }
      #csmClose {
        position: absolute;
        top: 16px;
        right: 20px;
        border: 0;
        background: #f3f4f8;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        font-size: 20px;
        cursor: pointer;
        color: #374151;
      }
      #csmClose:hover {
        background: #e5e7ee;
      }
      #csmCard h1 {
        margin: 0 0 4px;
        font-size: 24px;
        line-height: 1.2;
        padding-right: 44px;
      }
      #csmCard .csmNote {
        margin: 0 0 16px;
        color: #5b6478;
        font-size: 13px;
      }
      #csmRows {
        margin: 0;
      }
      #csmRows > div {
        padding: 12px 0;
        border-top: 1px solid #eef1f8;
      }
      #csmRows > div:first-child {
        border-top: 0;
      }
      #csmRows dt {
        font: 600 12px system-ui, sans-serif;
        color: #6b7280;
        margin-bottom: 4px;
      }
      #csmRows dd {
        margin: 0;
        font: 500 14px ui-monospace, SFMono-Regular, Menlo, monospace;
        color: #1f2430;
        word-break: break-all;
      }
      /* the one thing in here that is still editable: topping the pool up */
      #csmTopUp {
        margin-top: 18px;
        padding-top: 16px;
        border-top: 1px solid #eef1f8;
      }
      #csmStatus {
        margin-top: 8px;
        font-size: 13px;
        color: #6b7280;
      }
      #csmStatus:empty {
        display: none;
      }
      #csmStatus.ok {
        color: #1a9c6a;
      }
      #csmStatus.warn {
        color: #c2410c;
      }
      /* ---- the researcher's computer: the photo of the machine fills the view and the
         fake desktop sits on its glass (z 17: over the researcher modal, under the avatar
         picker and the office editor) ---- */
      #desktopView {
        position: fixed;
        inset: 0;
        z-index: 17;
        display: none;
        overflow: hidden;
        background: #6fbfa3;
      }
      body.atDesk #desktopView {
        display: block;
      }
      /* the photo blurred behind itself fills whatever the 2:3 photo doesn't */
      #desktopBackdrop {
        position: absolute;
        inset: -40px;
        background: url("/assets/greencomputer.jpg") center / cover no-repeat;
        filter: blur(28px) brightness(0.85);
      }
      /* The stage is laid out at the size it has LEANED IN — the glass filling the view —
         so that state carries no transform at all: the desktop renders at its own size,
         text stays crisp and a drag maps 1:1 to the pointer. Sitting back is the transform:
         the same picture shrunk to the band of the photo from the monitor's top to the
         keyboard's bottom (seatedTransform in main.js measures it).
         466.32vh = 0.9 of the viewport's height in glass, which is 19.3% of the photo;
         310.33vw = 0.96 of its width, for a window too narrow for that. */
      #desktopStage {
        --H: min(466.32vh, 310.33vw);
        position: absolute;
        height: var(--H);
        width: calc(var(--H) * 0.6667);
        /* the glass's own centre (49.7% across the photo, 41.65% down) on the viewport's */
        left: calc(50vw - var(--H) * 0.33137);
        top: calc(50vh - var(--H) * 0.4165);
        transform-origin: 0 0;
        transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
      }
      /* leaned in: the photo is blown far past its own resolution, so it reads as the
         out-of-focus room around the glass */
      #desktopView.zoomed #desktopPhoto {
        filter: brightness(0.82) saturate(0.92);
      }
      /* sitting down: the desktop is only a picture until the glass is clicked */
      #desktopView:not(.zoomed) #desktopScreen {
        cursor: zoom-in;
      }
      #desktopView:not(.zoomed) #desktopScreen > *:not(#deskGlare) {
        pointer-events: none;
      }
      #desktopView:not(.zoomed) #desktopScreen:hover #deskGlare {
        box-shadow:
          inset 0 0 1.6cqw rgba(0, 0, 0, 0.28),
          inset 0 0 0 0.3cqw rgba(255, 255, 255, 0.6);
      }
      /* leaned in: anywhere off the glass sits back up */
      #desktopView.zoomed {
        cursor: zoom-out;
      }
      #desktopView.zoomed #desktopScreen {
        cursor: default;
      }
      #desktopPhoto {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        display: block;
        user-select: none;
      }
      /* the glass: measured on the photo. Everything inside is sized in cq units so the
         desktop scales with the screen */
      /* The desktop's own furniture — the menu bar, a window's title bar, the dock — is
         sized in cq units of the glass, so it keeps its proportions in both states: it is
         the leaned-in view that they are sized for, and sitting back shows the same
         desktop smaller. */
      #desktopScreen {
        --deskBar: 2.6cqw; /* the menu bar */
        --deskDock: calc(5.67cqw + 1.04cqh); /* the dock and the gap under it */
        position: absolute;
        left: 26.5%;
        top: 32%;
        width: 46.4%;
        height: 19.3%;
        border-radius: 2.4% / 6%;
        overflow: hidden;
        background: linear-gradient(160deg, #8fd3dd 0%, #5aa9bd 60%, #3f8ea6 100%);
        container-type: size;
        font: 500 1.25cqw system-ui, sans-serif;
        color: #1f2430;
      }
      #deskBar {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: var(--deskBar);
        display: flex;
        align-items: center;
        justify-content: space-between;
        /* the glass's corner radius is a percentage of the screen, so the bar's inset is
           too: scaled down with the rest of the chrome, the name and the clock would
           crowd the curve once the view leans in */
        padding: 0 2cqw;
        background: rgba(255, 255, 255, 0.55);
        backdrop-filter: blur(6px);
        font-size: 1.2cqw;
        font-weight: 600;
        z-index: 1000; /* over every window (they count up from 1) */
      }
      #deskWindows {
        position: absolute;
        inset: 0;
        pointer-events: none; /* the empty desktop below it stays clickable */
      }
      .deskWin {
        pointer-events: auto;
      }
      .deskWin {
        position: absolute;
        width: 76cqw;
        height: 72cqh;
        background: #fff;
        border-radius: 0.83cqw;
        box-shadow: 0 1.04cqw 2.6cqw rgba(0, 0, 0, 0.3);
        overflow: hidden;
        display: flex;
        flex-direction: column;
      }
      .deskWinBar {
        flex: none;
        height: 3.1cqw;
        display: flex;
        align-items: center;
        gap: 1.04cqw;
        padding: 0 1.04cqw;
        background: linear-gradient(#f4f5f8, #e6e8ee);
        border-bottom: 1px solid #d5d8e0;
        cursor: grab;
        user-select: none;
      }
      .deskWinBar:active {
        cursor: grabbing;
      }
      .deskLights {
        display: flex;
        gap: 0.62cqw;
      }
      .deskLights span {
        width: 1.14cqw;
        height: 1.14cqw;
        border-radius: 50%;
        background: #febc2e;
      }
      .deskLights .close {
        background: #ff5f57;
        cursor: pointer;
      }
      .deskLights .min,
      .deskLights .max {
        cursor: pointer;
      }
      .deskLights .max {
        background: #28c840;
      }
      .deskWin.min {
        display: none;
      }
      .deskApp.minimized {
        opacity: 0.7;
      }
      .deskWinTitle {
        flex: 1;
        text-align: center;
        font-weight: 600;
        font-size: 1.25cqw;
        color: #4b5563;
        margin-right: 4.47cqw; /* the lights' width, so the title sits centred */
      }
      .deskWinBody {
        flex: 1;
        min-height: 0;
        position: relative;
        overflow: hidden;
      }
      /* the pane lays out DESK_PANE_W wide inside and is zoomed to the body (setDeskZoom) */
      .deskZoom {
        zoom: var(--z, 1);
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
      }
      .deskOff {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #9aa3b5;
        font: 600 20px system-ui, sans-serif;
      }
      /* zoomed: everything the desktop isn't already using — the menu bar stays, and the
         dock keeps its strip along the bottom */
      .deskWin.max {
        left: 1.5cqw !important;
        top: calc(var(--deskBar) + 1.5cqh) !important;
        width: calc(100% - 3cqw) !important;
        height: calc(100% - var(--deskBar) - var(--deskDock) - 3cqh) !important;
      }
      #deskDock {
        position: absolute;
        left: 50%;
        bottom: 1.04cqh;
        transform: translateX(-50%);
        display: flex;
        gap: 0.83cqw;
        padding: 0.62cqw;
        background: rgba(255, 255, 255, 0.45);
        border: 1px solid rgba(255, 255, 255, 0.6);
        border-radius: 1.25cqw;
        backdrop-filter: blur(6px);
        z-index: 1000; /* over every window, like the bar */
      }
      .deskApp {
        position: relative;
        width: 4.42cqw;
        height: 4.42cqw;
        border: 0;
        border-radius: 1.04cqw;
        background: linear-gradient(#fff, #e6ecf5);
        font-size: 2.4cqw;
        line-height: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        box-shadow: 0 0.21cqw 0.52cqw rgba(0, 0, 0, 0.18);
        transition: transform 0.12s;
      }
      .deskApp img {
        width: 2.4cqw;
        height: 2.4cqw;
        display: block;
        pointer-events: none;
      }
      .deskApp:hover {
        transform: translateY(-0.42cqw) scale(1.08);
      }
      .deskApp.running::after {
        content: "";
        position: absolute;
        left: 50%;
        bottom: -0.62cqw;
        width: 0.47cqw;
        height: 0.47cqw;
        border-radius: 50%;
        background: #1f2430;
        transform: translateX(-50%);
      }
      /* the glass over the desktop: the photo's glare in the top right corner and a
         shade at the edges of the tube */
      #deskGlare {
        position: absolute;
        inset: 0;
        pointer-events: none;
        z-index: 1001;
        background: radial-gradient(ellipse at 78% 12%, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 34%);
        box-shadow: inset 0 0 1.6cqw rgba(0, 0, 0, 0.28);
        border-radius: inherit;
      }
      #desktopBack {
        position: absolute;
        top: 16px;
        left: 20px;
        z-index: 2;
        white-space: nowrap;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 12px;
        padding: 8px 14px;
        font: 700 15px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 4px 0 #c9d3ea;
      }
      #desktopBack:hover {
        background: #f3f6ff;
      }
      /* leaned in it would sit on the menu bar, and the way out is the bezel (or Esc) */
      #desktopView.zoomed #desktopBack {
        display: none;
      }
      /* the main desk's computer, in the office list's pictures, opens the machine */
      .officeGrid .sprite.mainDesk {
        pointer-events: auto;
        cursor: pointer;
        animation: deskBeckon 2.4s ease-in-out infinite;
      }
      .officeGrid .sprite.mainDesk:hover {
        animation: none;
        filter: brightness(1.3) drop-shadow(0 0 3px #fff);
      }
      /* a slow glow, so the one clickable thing in the picture can be found */
      @keyframes deskBeckon {
        50% {
          filter: brightness(1.25) drop-shadow(0 0 2px #fff);
        }
      }
      /* unread mail, on the dock's Mail tile */
      .deskBadge {
        position: absolute;
        top: -0.5cqw;
        right: -0.5cqw;
        min-width: 1.6cqw;
        height: 1.6cqw;
        padding: 0 0.4cqw;
        box-sizing: border-box;
        border-radius: 0.8cqw;
        background: #ff4fd0;
        color: #fff;
        font: 700 1cqw/1.6cqw system-ui, sans-serif;
        text-align: center;
      }
      .deskBadge[hidden] {
        display: none;
      }
      /* ---- the panes the researcher's computer puts in its windows (#deskPanes) ---- */
      .rmPane {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-height: 0;
      }
      /* ---- the email pane: a folder bar, then the thread list beside the reading pane ---- */
      #rmMailPane {
        background: #f7f8fc;
        font: 14px system-ui, sans-serif;
      }
      #mailBar {
        flex: none;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 10px 20px 10px 24px;
        background: #fff;
        border-bottom: 2px solid #e6eaf5;
      }
      #mailFolders {
        display: flex;
        gap: 6px;
      }
      .mailFolder {
        border: 2px solid transparent;
        background: none;
        border-radius: 10px;
        padding: 5px 12px;
        font: 700 13px system-ui, sans-serif;
        color: #6b7280;
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        gap: 6px;
      }
      .mailFolder:hover {
        background: #f3f6ff;
      }
      .mailFolder.on {
        background: #eef1f8;
        color: #2b3a67;
        border-color: #dfe6f5;
      }
      .mailFolder .count:empty {
        display: none;
      }
      .mailFolder .count {
        font-size: 11px;
        color: #fff;
        background: #2b3a67;
        border-radius: 8px;
        padding: 0 6px;
        line-height: 16px;
      }
      #mailAccount {
        font-size: 12px;
        color: #6b7280;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      #mailBody {
        flex: 1;
        min-height: 0;
        display: grid;
        grid-template-columns: minmax(220px, 290px) 1fr;
      }
      #mailList {
        overflow-y: auto;
        border-right: 2px solid #e6eaf5;
        background: #fff;
      }
      #mailList .none,
      #mailRead .none {
        padding: 40px 24px;
        color: #6b7280;
        text-align: center;
      }
      .mailRow {
        display: grid;
        grid-template-columns: 36px 1fr auto;
        grid-template-rows: auto auto;
        column-gap: 10px;
        row-gap: 2px;
        padding: 12px 14px 12px 12px;
        border-bottom: 1px solid #eef1f8;
        cursor: pointer;
        position: relative;
      }
      .mailRow:hover {
        background: #f7f8fc;
      }
      .mailRow.on {
        background: #eef1f8;
        box-shadow: inset 3px 0 0 #ff4fd0;
      }
      .mailAvatar {
        grid-row: 1 / span 2;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        background: #2b3a67;
        color: #fff;
        font: 700 13px/36px system-ui, sans-serif;
        text-align: center;
        align-self: center;
      }
      .mailAvatar.me {
        background: #ff4fd0;
      }
      .mailAvatar.inst {
        background: #eef1f8;
        font-size: 18px;
      }
      .mailRow .who {
        font-weight: 600;
        color: #374151;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .mailRow .when {
        font-size: 11px;
        color: #9aa3b8;
        white-space: nowrap;
      }
      .mailRow .what {
        grid-column: 2 / span 2;
        font-size: 13px;
        color: #6b7280;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .mailRow .what b {
        color: #374151;
        font-weight: 600;
      }
      .mailRow .what .n {
        color: #9aa3b8;
        font-weight: 400;
      }
      .mailRow.unread .who,
      .mailRow.unread .what b {
        color: #1f2430;
        font-weight: 800;
      }
      .mailRow.unread::before {
        content: "";
        position: absolute;
        left: 4px;
        top: 50%;
        width: 6px;
        height: 6px;
        margin-top: -3px;
        border-radius: 50%;
        background: #ff4fd0;
      }
      #mailRead {
        overflow-y: auto;
        padding: 20px 28px 32px;
      }
      #mailRead h3 {
        margin: 0 0 4px;
        font-size: 20px;
        color: #2b3a67;
      }
      .mailRfpMeta {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin: 0 0 18px;
      }
      .mailRfpMeta span {
        font-size: 11px;
        font-weight: 700;
        color: #2b3a67;
        background: #eef1f8;
        border: 1px solid #dfe6f5;
        border-radius: 8px;
        padding: 2px 8px;
      }
      .mailMsg {
        background: #fff;
        border: 1px solid #e6eaf5;
        border-radius: 14px;
        padding: 14px 18px 16px;
        margin-bottom: 12px;
        box-shadow: 0 2px 0 #eef1f8;
      }
      .mailMsg.me {
        border-color: #ffd1f2;
        background: #fffafe;
      }
      .mailMsgHead {
        display: grid;
        grid-template-columns: 36px 1fr auto;
        column-gap: 10px;
        align-items: center;
        margin-bottom: 10px;
      }
      .mailMsgHead .from {
        font-weight: 700;
        color: #1f2430;
        line-height: 1.2;
      }
      .mailMsgHead .from small {
        display: block;
        font-weight: 400;
        font-size: 11px;
        color: #9aa3b8;
      }
      .mailMsgHead .when {
        font-size: 12px;
        color: #9aa3b8;
      }
      .mailMsg .text {
        white-space: pre-wrap;
        line-height: 1.5;
        color: #374151;
        font-size: 14px;
      }
      #mailActions {
        display: flex;
        gap: 8px;
        margin-top: 4px;
      }
      /* the composer: replies to the authority, kept until the page is reloaded */
      #mailCompose {
        background: #fff;
        border: 2px solid #ff4fd0;
        border-radius: 14px;
        padding: 14px 18px 16px;
        margin-top: 4px;
        box-shadow: 0 10px 24px rgba(255, 79, 208, 0.15);
      }
      #mailCompose .line {
        font-size: 12px;
        color: #6b7280;
        padding: 4px 0;
        border-bottom: 1px solid #eef1f8;
      }
      #mailCompose .line b {
        color: #374151;
      }
      #mailCompose textarea {
        display: block;
        width: 100%;
        min-height: 150px;
        margin: 10px 0 12px;
        border: 0;
        outline: none;
        resize: vertical;
        font: 14px/1.5 system-ui, sans-serif;
        color: #1f2430;
        background: none;
      }
      #mailCompose .buttons {
        display: flex;
        gap: 8px;
      }
      .mailBtn {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 6px 14px;
        font: 700 13px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 3px 0 #c9d3ea;
        transition: background 0.15s, transform 0.15s, border-color 0.15s;
      }
      .mailBtn:hover {
        background: #f3f6ff;
        border-color: #ff4fd0;
        transform: translateY(-1px);
      }
      .mailBtn.primary {
        background: #ff4fd0;
        border-color: #ff4fd0;
        color: #fff;
        box-shadow: 0 3px 0 #c22b9b;
      }
      .mailBtn.primary:hover {
        background: #ff66d8;
      }
      .mailBtn:disabled {
        opacity: 0.5;
        cursor: default;
        transform: none;
      }
      /* rendered markdown, wherever a .md box holds some */
      .md p { margin: 0 0 0.7em; }
      .md p:last-child { margin-bottom: 0; }
      .md h2, .md h3, .md h4 { margin: 0.9em 0 0.3em; line-height: 1.25; font-size: 1em; color: #2b3a67; }
      .md h2:first-child, .md h3:first-child, .md h4:first-child { margin-top: 0; }
      .md ul, .md ol { margin: 0 0 0.7em; padding-left: 1.4em; }
      .md li { margin: 0.15em 0; }
      .md blockquote { margin: 0 0 0.7em; padding: 0.2em 0.9em; border-left: 3px solid #c9d1ea; color: #555e78; }
      .md code { background: #eef1fa; border-radius: 4px; padding: 0.05em 0.35em; font-size: 0.92em; }
      .md pre.mdCode { background: #14151d; color: #e8e9f0; border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: 0 0 0.7em; white-space: pre; font-size: 0.9em; }
      .md .mdTableWrap { overflow-x: auto; margin: 0 0 0.7em; }
      .md table.mdTable { border-collapse: collapse; font-size: 0.93em; }
      .md .mdTable th, .md .mdTable td { border: 1px solid #d5dbee; padding: 4px 8px; text-align: left; vertical-align: top; }
      .md .mdTable th { background: #eef1fa; font-weight: 600; }
      .md .mdLink { color: #6c7bff; border-bottom: 1px dotted #6c7bff; cursor: help; }
      /* an RFP's body (markdown) on the review board's detail and a lab's open-request row */
      .rfpBody {
        font-size: 13px;
        line-height: 1.5;
        color: #374151;
        margin: 0 0 10px;
      }
      .labRfpRow .rfpBody {
        max-height: 220px;
        overflow-y: auto;
        padding-right: 4px;
      }
      /* the RFP body inside a mail message: between the letter's plain-text intro and tail */
      .mailMsg .md {
        white-space: normal;
        line-height: 1.5;
        color: #374151;
        font-size: 14px;
        margin: 0.8em 0;
      }
      #offices .none {
        color: #6b7280;
        font-size: 15px;
        padding: 20px 0;
      }
      /* a sprite cut from one of the tilesheets (both in the list and in the editor) */
      .sprite {
        position: absolute;
        background-repeat: no-repeat;
        image-rendering: pixelated;
        pointer-events: none;
      }
      /* ---- office editor: full-screen modal, office on the left, tile palette on the right ---- */
      #officeEditor {
        position: fixed;
        inset: 0;
        z-index: 20;
        background: #f4f6fb;
        color: #1f2430;
        display: none;
        flex-direction: column;
        font: 14px system-ui, sans-serif;
      }
      body.officeEditing #officeEditor {
        display: flex;
      }
      #oeHead {
        flex: none;
        display: flex;
        align-items: center;
        gap: 8px 14px;
        flex-wrap: wrap; /* the layer bar drops to a second line on narrow windows */
        padding: 12px 20px;
        background: #fff;
        border-bottom: 3px solid #dfe6f5;
      }
      #oeHead h1,
      #oeHead .sub,
      #oeTools button,
      #oeRoomZoom,
      .layerChip button {
        white-space: nowrap;
      }
      #oeHead h1 {
        margin: 0;
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: 24px;
        letter-spacing: 0.02em;
        line-height: 1;
        padding-top: 4px;
        color: #2b3a67;
      }
      #oeHead h1 span {
        color: #ff4fd0;
      }
      #oeHead h1 .suffix {
        color: inherit; /* only the name is pink */
      }
      #oeHead .sub {
        color: #6b7280;
        font-size: 13px;
      }
      #oeTools {
        margin-left: auto;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
      }
      #oeTools button,
      #oeSheets button {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 7px 12px;
        font: 600 13px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 3px 0 #c9d3ea;
      }
      #oeTools button:hover,
      #oeSheets button:hover {
        background: #f3f6ff;
      }
      #oeTools button.on,
      #oeSheets button.on {
        border-color: #ff4fd0;
        background: #fff0fb;
      }
      #oeSaved {
        font-size: 12px;
        color: #1f9d55;
        min-width: 60px;
        text-align: right;
        opacity: 0;
        transition: opacity 0.3s;
      }
      #oeSaved.show {
        opacity: 1;
      }
      #oeClose {
        width: 36px;
        height: 36px;
        border-radius: 50% !important;
        padding: 0 !important;
        font-size: 20px !important;
      }
      #oeBody {
        flex: 1;
        display: flex;
        min-height: 0;
      }
      /* the room can be bigger than the stage: scroll to reach the rest (margin: auto keeps
         a small room centred without clipping a big one) */
      #oeStage {
        flex: 1;
        display: flex;
        overflow: auto;
        padding: 24px;
        min-width: 0;
        background: #fff;
      }
      #oeStage #oeRoom {
        flex: none;
        margin: auto;
      }
      /* layer chips: name selects the active layer, the dot toggles visibility */
      #oeLayers {
        display: flex;
        gap: 4px;
        margin-right: 10px;
      }
      .layerChip {
        display: flex;
        align-items: stretch;
        border: 2px solid #dfe6f5;
        border-radius: 10px;
        background: #fff;
        overflow: hidden;
        box-shadow: 0 3px 0 #c9d3ea;
      }
      .layerChip button {
        border: 0;
        background: transparent;
        color: #2b3a67;
        font: 600 13px system-ui, sans-serif;
        cursor: pointer;
        padding: 7px 10px;
      }
      .layerChip .eye {
        padding: 7px 8px 7px 4px;
        color: #9aa5c6;
        font-size: 11px;
      }
      .layerChip .wand {
        padding: 5px 4px 5px 2px;
        font-size: 14px;
        line-height: 1;
        border-left: 1px solid #eef1f8;
      }
      .layerChip button:hover {
        background: #f3f6ff;
      }
      .layerChip.on {
        border-color: #ff4fd0;
        background: #fff0fb;
      }
      .layerChip.on .eye {
        color: #ff4fd0;
      }
      .layerChip.hidden .name {
        color: #b2bbd1;
        text-decoration: line-through;
      }
      #oeRoomZoom {
        display: flex;
        align-items: center;
        gap: 6px;
        font-size: 12px;
        color: #6b7280;
        margin-right: 6px;
      }
      #oeRoomZoom input {
        width: 90px;
        accent-color: #ff4fd0;
      }
      /* the office: white, with a 16x16 cell grid that sprites lock to */
      #oeRoom {
        --tile: 48px;
        position: relative;
        overflow: hidden; /* sprites drawn at native size may overhang the room's edge */
        background:
          linear-gradient(rgba(43, 58, 103, 0.14) 1px, transparent 1px) 0 0 /
            var(--tile) var(--tile),
          linear-gradient(90deg, rgba(43, 58, 103, 0.14) 1px, transparent 1px)
            0 0 / var(--tile) var(--tile),
          #fff;
        border: 3px solid #c9d3ea;
        border-radius: 6px;
        box-shadow: 0 6px 0 #c9d3ea, 0 16px 40px rgba(43, 58, 103, 0.15);
        cursor: crosshair;
        user-select: none;
        touch-action: none;
      }
      #oeRoom.erasing {
        cursor: not-allowed;
      }
      #oeRoom.selecting {
        cursor: default;
      }
      #oeRoom .sprite.hit {
        outline: 2px solid #ff4f4f;
        filter: brightness(1.15);
      }
      /* the Select tool: what the pointer is over, and what it picked */
      #oeRoom .sprite.pick {
        outline: 2px dashed #6c7bff;
      }
      #oeRoom .sprite.sel {
        outline: 2px solid #ff4fd0;
        box-shadow: 0 0 0 4px rgba(255, 79, 208, 0.25);
      }
      #oeTools button:disabled {
        opacity: 0.45;
        cursor: default;
        box-shadow: none;
      }
      /* the cells the selected sprite will occupy, and the sprite itself, following the pointer
         (furniture and walkers carry a depth z-index, so these sit far above them) */
      #oeFoot {
        position: absolute;
        display: none;
        box-sizing: border-box;
        border: 2px solid #ff4fd0;
        background: rgba(255, 79, 208, 0.12);
        pointer-events: none;
        z-index: 10001;
      }
      #oeGhost {
        position: absolute;
        display: none;
        opacity: 0.75;
        background-repeat: no-repeat;
        image-rendering: pixelated;
        pointer-events: none;
        z-index: 10002;
      }
      /* a person walking about the office: one frame of a character sheet */
      .walker {
        position: absolute;
        background-repeat: no-repeat;
        image-rendering: pixelated;
        pointer-events: none;
      }
      /* the walkability overlay (W): green where a person can stand, red where not */
      #oeWalk {
        position: absolute;
        inset: 0;
        display: none;
        grid-template-columns: repeat(18, var(--tile));
        grid-auto-rows: var(--tile);
        pointer-events: none;
        z-index: 10000;
      }
      #oeRoom.showWalk #oeWalk {
        display: grid;
      }
      #oeWalk div {
        box-sizing: border-box;
        border: 1px solid rgba(255, 255, 255, 0.35);
        background: rgba(255, 79, 79, 0.35);
      }
      #oeWalk div.ok {
        background: rgba(31, 157, 85, 0.3);
      }
      /* palette */
      #oePalette {
        flex: none;
        width: 44%;
        max-width: 640px;
        min-width: 360px;
        display: flex;
        flex-direction: column;
        background: #f4f6fb;
        border-left: 3px solid #dfe6f5;
        min-height: 0;
      }
      #oePaletteHead {
        flex: none;
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 10px 14px;
        border-bottom: 1px solid #dfe6f5;
        flex-wrap: wrap;
      }
      #oeSheets {
        display: flex;
        gap: 6px;
      }
      #oeZoom {
        margin-left: auto;
        display: flex;
        align-items: center;
        gap: 6px;
        font-size: 12px;
        color: #6b7280;
      }
      #oeZoom input {
        width: 90px;
        accent-color: #ff4fd0;
      }
      #oeHint {
        flex: none;
        padding: 6px 14px;
        font-size: 12px;
        color: #6b7280;
        border-bottom: 1px solid #dfe6f5;
      }
      #oeSheetScroll {
        flex: 1;
        overflow: auto;
        padding: 12px;
        min-height: 0;
        background: #fff;
      }
      #oeSheet {
        position: relative;
        image-rendering: pixelated;
        background-repeat: no-repeat;
        background-color: #fff;
        cursor: crosshair;
        user-select: none;
        touch-action: none;
      }
      /* one box per sprite, at its real pixel bounds */
      #oeBoxes {
        position: absolute;
        inset: 0;
      }
      .spriteBox {
        position: absolute;
        box-sizing: border-box;
        border: 1px solid rgba(43, 58, 103, 0.16);
        cursor: pointer;
      }
      .spriteBox:hover {
        border-color: #2b3a67;
        background: rgba(43, 58, 103, 0.12);
      }
      .spriteBox.on {
        border: 2px solid #ff4fd0;
        background: rgba(255, 79, 208, 0.18);
        box-shadow: 0 0 0 1px #fff;
      }
      #oeBrush {
        flex: none;
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 10px 14px;
        border-top: 1px solid #dfe6f5;
        font-size: 12px;
        color: #6b7280;
      }
      #oeBrushInfo b {
        color: #2b3a67;
        font-size: 14px;
        background: #fff0fb;
        border: 1px solid #ff4fd0;
        border-radius: 6px;
        padding: 2px 7px;
        margin-right: 4px;
      }
      #oeBrushPreview {
        display: none;
        image-rendering: pixelated;
        background-repeat: no-repeat;
        background-color: #fff;
        outline: 1px solid #dfe6f5;
      }
      #close {
        position: absolute;
        top: 16px;
        right: 20px;
        border: 0;
        background: #f3f4f8;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        font-size: 20px;
        cursor: pointer;
        color: #374151;
      }
      #close:hover {
        background: #e5e7ee;
      }
      #title {
        position: fixed;
        top: 16px;
        right: 16px;
        background: #fff;
        color: #2b3a67;
        padding: 14px 24px 10px;
        border-radius: 18px;
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: 30px;
        letter-spacing: 0.02em;
        line-height: 1;
        white-space: nowrap;
        box-shadow:
          0 6px 0 #c9d3ea,
          0 10px 24px rgba(0, 0, 0, 0.18);
        border: 3px solid #dfe6f5;
        pointer-events: none;
        transition:
          opacity 0.3s,
          transform 0.3s;
      }
      #title span {
        color: #ff4fd0;
      }
      body.inspecting #title {
        opacity: 0;
        transform: translateY(-8px);
      }
      /* mega tower placement banner, top centre */
      #megaPrompt {
        position: fixed;
        top: 18px;
        left: 50%;
        transform: translateX(-50%);
        z-index: 7;
        display: none;
        align-items: center;
        gap: 12px;
        background: #fff;
        color: #2b3a67;
        padding: 12px 20px;
        border-radius: 16px;
        border: 3px solid #dfe6f5;
        box-shadow: 0 6px 0 #c9d3ea, 0 10px 24px rgba(0, 0, 0, 0.18);
        font: 700 17px system-ui, sans-serif;
      }
      body.placingMega #megaPrompt {
        display: flex;
      }
      #megaPrompt button {
        display: none;
        border: 2px solid #ff4fd0;
        background: #ff4fd0;
        color: #fff;
        border-radius: 10px;
        padding: 6px 16px;
        font: 600 14px system-ui, sans-serif;
        cursor: pointer;
      }
      #megaPrompt button#megaMove {
        background: #fff;
        color: #2b3a67;
        border-color: #dfe6f5;
      }
      body.placingMega.megaPending #megaPrompt button {
        display: inline-block;
      }
      /* while placing, the rest of the chrome steps back */
      body.placingMega #editBar,
      body.placingMega #statBar,
      body.placingMega #title {
        opacity: 0;
        pointer-events: none;
      }
      /* edit controls under the title (right-aligned with it) */
      #editBar {
        position: fixed;
        top: 84px;
        right: 16px;
        z-index: 6;
        display: flex;
        align-items: center;
        gap: 10px;
        transition:
          opacity 0.3s,
          transform 0.3s;
      }
      /* ---- the stat bar: the city's readouts along the bottom-left edge. Every chip
         is a button into City Info (the panel opens directly above the bar), and the
         one whose pane is up stays pressed. --chipShadow is each chip's own colour for
         the 3D lip, so the pressed and hover states are written once. ---- */
      #statBar {
        position: fixed;
        left: 16px;
        bottom: 16px;
        z-index: 7;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 10px;
        max-width: calc(100vw - 32px);
        transition:
          opacity 0.3s,
          transform 0.3s;
      }
      #statBar > span {
        --chipShadow: #c9d3ea;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 8px 14px;
        font: 700 15px system-ui, sans-serif;
        box-shadow: 0 4px 0 var(--chipShadow);
        white-space: nowrap;
        cursor: pointer;
        user-select: none;
        transition: transform 0.1s, box-shadow 0.1s;
      }
      #statBar > span:hover {
        filter: brightness(1.03);
      }
      #statBar > span:active {
        transform: translateY(2px);
        box-shadow: 0 2px 0 var(--chipShadow);
      }
      #statBar > span.on {
        transform: translateY(3px);
        box-shadow: 0 1px 0 var(--chipShadow);
      }
      #labs {
        --chipShadow: #9db3f0;
        border-color: #c3d4ff;
        background: #eef2ff;
        color: #2b3a67;
      }
      #researchers {
        --chipShadow: #f28fd2;
        border-color: #ffbfe9;
        background: #fff0fb;
        color: #8a1b66;
      }
      #rfps {
        --chipShadow: #d9c9a8;
        border-color: #eee0c4;
        background: #fdf8ee;
        color: #6b4f1d;
      }
      #pop {
        --chipShadow: #86cfa3;
        border-color: #b7e4c7;
        background: #e9f9ef;
        color: #1b5e35;
      }
      /* the grid chip: green while the stations cover the city, red (and breathing) when
         they don't */
      #power {
        --chipShadow: #86cfa3;
        border-color: #b7e4c7;
        background: #e9f9ef;
        color: #1b5e35;
      }
      #power.short {
        --chipShadow: #f08a80;
        border-color: #ffb3ae;
        background: #ffeceb;
        color: #a11d13;
        animation: brownout 1.6s ease-in-out infinite;
      }
      /* a deficit is the city's lights dipping, so the chip dips too */
      @keyframes brownout {
        0%, 100% { opacity: 1; }
        45% { opacity: 0.55; }
      }
      .buildItem .price {
        margin-left: auto;
        flex: none;
        font: 600 13px system-ui, sans-serif;
        color: #7a5a00;
        background: #fff7d6;
        border-radius: 8px;
        padding: 4px 8px;
        white-space: nowrap;
      }
      .buildItem.poor {
        opacity: 0.55;
        cursor: not-allowed;
      }
      .buildItem.poor .price {
        color: #b42318;
        background: #fee4e2;
      }
      /* the pen: a square the width of the palette column, so the palette reads as
         unfolding from under it. Editing turns it pink and swaps the pen for an × */
      #editBtn {
        --lip: #c9d3ea;
        width: 62px;
        height: 46px;
        box-sizing: border-box;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 0;
        font: 700 22px/1 system-ui, sans-serif;
        box-shadow: 0 4px 0 var(--lip);
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
      }
      #editBtn:hover {
        background: #f3f6ff;
      }
      #editBtn:active {
        transform: translateY(2px);
        box-shadow: 0 2px 0 var(--lip);
      }
      #editBtn .x {
        display: none;
        font-size: 28px;
        margin-top: -3px;
      }
      body.editing #editBtn {
        --lip: #c23a9e;
        background: #ff4fd0;
        border-color: #ffb3ea;
        color: #fff;
      }
      body.editing #editBtn:hover {
        background: #ff66d8;
      }
      body.editing #editBtn .pen {
        display: none;
      }
      body.editing #editBtn .x {
        display: inline;
      }
      body.selecting #editBar,
      body.inspecting #editBar {
        opacity: 0;
        pointer-events: none;
        transform: translateY(-8px);
      }
      body.selecting #statBar,
      body.inspecting #statBar {
        opacity: 0;
        pointer-events: none;
        transform: translateY(8px);
      }
      /* city select mode: the chrome of the city view is hidden, a picker header takes its place */
      body.selecting #title,
      body.selecting #hud {
        opacity: 0;
        pointer-events: none;
      }
      #select {
        position: fixed;
        top: 18px;
        left: 0;
        right: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 14px;
        z-index: 6;
        pointer-events: none;
        transition:
          opacity 0.35s,
          transform 0.35s;
      }
      body:not(.selecting) #select {
        opacity: 0;
        transform: translateY(-12px);
        pointer-events: none;
      }
      /* the faded-out picker's buttons (which turn pointer events back on for themselves)
         sit right over the edit bar's chips: while hidden they must not catch a click */
      body:not(.selecting) #select *,
      body.loading #select * {
        pointer-events: none;
      }
      /* still loading: nothing of the picker shows until its cities are on the turntable */
      body.loading #select,
      body.loading .cityLabelContainer {
        opacity: 0;
        pointer-events: none;
      }
      /* start-up screen: a sky-blue cover with the title and a loading bar, up while
         body.loading and fading out with it (main.js fills #loadFill as assets arrive) */
      #loadScreen {
        position: fixed;
        inset: 0;
        z-index: 40;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 30px;
        background: #9ed2f5;
        opacity: 0;
        visibility: hidden;
        transition:
          opacity 0.45s,
          visibility 0.45s;
      }
      body.loading #loadScreen {
        opacity: 1;
        visibility: visible;
      }
      #loadScreen h1 {
        margin: 0;
        background: #fff;
        color: #2b3a67;
        padding: 20px 38px 14px;
        border-radius: 22px;
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: clamp(38px, 7vw, 58px);
        letter-spacing: 0.02em;
        line-height: 1;
        white-space: nowrap;
        border: 3px solid #dfe6f5;
        box-shadow:
          0 6px 0 #c9d3ea,
          0 10px 24px rgba(0, 0, 0, 0.18);
      }
      #loadByline {
        margin: -12px 0 0;
        color: #2b3a67;
        font: 600 17px system-ui, sans-serif;
        letter-spacing: 0.04em;
        opacity: 0.75;
      }
      #loadBar {
        width: min(340px, 70vw);
        height: 16px;
        box-sizing: border-box;
        background: #fff;
        border: 3px solid #dfe6f5;
        border-radius: 999px;
        box-shadow: 0 4px 0 #c9d3ea;
        overflow: hidden;
      }
      #loadFill {
        height: 100%;
        width: 4%;
        background: #ff4fd0;
        border-radius: inherit;
        transition: width 0.25s;
      }
      #select h1 {
        margin: 0;
        background: #fff;
        color: #2b3a67;
        padding: 14px 28px 10px;
        border-radius: 18px;
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: 34px;
        letter-spacing: 0.02em;
        line-height: 1;
        font-weight: normal;
        box-shadow:
          0 6px 0 #c9d3ea,
          0 10px 24px rgba(0, 0, 0, 0.18);
        border: 3px solid #dfe6f5;
      }
      #select .nav {
        display: flex;
        gap: 10px;
        pointer-events: auto;
      }
      #select button {
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 8px 18px;
        font:
          600 15px system-ui,
          sans-serif;
        cursor: pointer;
        box-shadow: 0 4px 0 #c9d3ea;
      }
      #select button:hover {
        background: #f3f6ff;
      }
      #select button:active {
        transform: translateY(2px);
        box-shadow: 0 2px 0 #c9d3ea;
      }
      body.selecting #select button[disabled] {
        opacity: 0.5;
        cursor: default;
      }
      #newCity {
        margin-top: 20px;
        pointer-events: auto;
      }
      #back {
        position: fixed;
        top: 18px;
        left: 18px;
        z-index: 6;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 8px 18px;
        font: 600 15px system-ui, sans-serif;
        cursor: pointer;
        box-shadow: 0 4px 0 #c9d3ea;
        transition: opacity 0.3s, transform 0.3s;
      }
      #back:hover {
        background: #f3f6ff;
      }
      /* the name card: a small bordered box in the bottom-left corner, just above the
         stat bar; while City Info is open it moves to the panel's right */
      #hoverName {
        position: fixed;
        left: 18px;
        bottom: 72px;
        z-index: 6;
        max-width: min(360px, calc(100vw - 36px));
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 8px 18px;
        font: 600 15px/1.3 system-ui, sans-serif;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        box-shadow: 0 4px 0 #c9d3ea;
        pointer-events: none;
      }
      #hoverName[hidden] {
        display: none;
      }
      body.infoOpen #hoverName {
        left: 394px;
      }
      /* the dashboard: the same card, bottom-centre, while a car is being driven */
      #drive {
        position: fixed;
        left: 50%;
        bottom: 18px;
        transform: translateX(-50%);
        z-index: 6;
        display: flex;
        align-items: center;
        gap: 16px;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 8px 12px 8px 18px;
        font: 600 15px/1.3 system-ui, sans-serif;
        white-space: nowrap;
        box-shadow: 0 4px 0 #c9d3ea;
      }
      #drive[hidden] {
        display: none;
      }
      #driveCar {
        text-transform: capitalize;
      }
      #driveDash {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        font-variant-numeric: tabular-nums;
      }
      #driveDash span {
        min-width: 5.5ch;
        text-align: center;
      }
      #driveDash b {
        color: #c9d3ea;
        transition: color 0.15s;
      }
      #driveDash b.on {
        color: #ffb020;
        animation: blink 0.8s steps(1) infinite;
      }
      @keyframes blink {
        50% {
          color: #c9d3ea;
        }
      }
      #driveKeys {
        font-weight: 500;
        font-size: 13px;
        color: #8a93a3;
      }
      #driveKeys kbd {
        font: 600 12px ui-monospace, SFMono-Regular, Menlo, monospace;
        color: #2b3a67;
        background: #eef2fa;
        border-radius: 5px;
        padding: 1px 5px;
      }
      #driveView,
      #driveExit {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 10px;
        padding: 5px 12px;
        font: 600 14px system-ui, sans-serif;
        cursor: pointer;
      }
      #driveView:hover,
      #driveExit:hover {
        border-color: #ff4fd0;
      }
      #driveView {
        margin-left: -6px;
      }
      /* the corner cards would sit under the dashboard on a narrow window */
      body.driving #hoverName,
      body.driving #statBar,
      body.driving #cityDate {
        display: none;
      }
      /* the date card: the same box, bottom-right; only the city view has a date */
      #cityDate {
        position: fixed;
        right: 18px;
        bottom: 18px;
        z-index: 6;
        border: 3px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 14px;
        padding: 8px 18px;
        font: 600 15px/1.3 system-ui, sans-serif;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
        box-shadow: 0 4px 0 #c9d3ea;
        pointer-events: none;
        transition: opacity 0.35s;
      }
      #cityDate[hidden] {
        display: none;
      }
      #cityDate {
        display: flex;
        align-items: center;
        gap: 10px;
      }
      /* the sun and the moon: dim until one is holding the time, and clickable either way */
      #cityDate button {
        pointer-events: auto;
        border: 2px solid transparent;
        border-radius: 8px;
        background: none;
        padding: 1px 4px;
        font-size: 17px;
        line-height: 1;
        cursor: pointer;
        opacity: 0.4;
        filter: grayscale(0.6);
        transition: opacity 0.2s, filter 0.2s;
      }
      #cityDate button:hover {
        opacity: 0.8;
        filter: none;
      }
      #cityDate button.on {
        opacity: 1;
        filter: none;
        border-color: #dfe6f5;
        background: #f2f5fc;
      }
      #dayBtn {
        margin-left: 4px;
      }
      body.selecting #cityDate {
        opacity: 0;
      }
      body.selecting #back,
      body.inspecting #back {
        opacity: 0;
        pointer-events: none;
        transform: translateY(-8px);
      }
      .cityLabelContainer {
        position: fixed;
        left: 0;
        top: 0;
        transform: translate(-50%, 0);
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 4px;
        pointer-events: auto;
        z-index: 4;
      }
      .cityLabel {
        background: #fff;
        color: #2b3a67;
        padding: 10px 18px 7px;
        border-radius: 14px;
        white-space: nowrap;
        pointer-events: none;
        user-select: none; /* the label is double-clicked to rename, not to select its text */
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: 22px;
        line-height: 1;
        letter-spacing: 0.02em;
        border: 3px solid #dfe6f5;
        box-shadow: 0 4px 0 #c9d3ea;
        transition: opacity 0.3s;
      }
      .cityLabel.front {
        color: #ff4fd0;
      }
      .cityDeleteBtn {
        width: 24px;
        height: 24px;
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #2b3a67;
        border-radius: 50%;
        padding: 0;
        font: bold 14px system-ui;
        cursor: pointer;
        pointer-events: auto;
        display: none;
        align-items: center;
        justify-content: center;
        transition: all 0.2s;
      }
      .cityDeleteBtn:hover {
        background: #f3f6ff;
        border-color: #ff4fd0;
      }
      /* a city with a ✎ beside it keeps the ✕'s slot even while the ✕ is hidden:
         hiding it with display would slide the ✎ sideways on hover, right out from
         under the pointer aiming at it */
      .cityLabelBtns:has(.cityRenameBtn) .cityDeleteBtn {
        display: flex;
        visibility: hidden;
      }
      .cityLabelContainer:hover .cityDeleteBtn {
        display: flex;
        visibility: visible;
      }
      /* outside the picker the whole label container is inert: the label fades and the
         delete button must not pop up when the mouse crosses where the label was */
      body:not(.selecting) .cityLabel {
        opacity: 0;
      }
      body:not(.selecting) .cityLabelContainer {
        pointer-events: none;
      }
      body:not(.selecting) .cityDeleteBtn {
        display: none !important;
      }

      /* ---- maverick aggregate bars: lab-header (renderLabMaverickBar) and city HUD
         (updateLabStats) — one shared gradient (maverickTint/applyMaverickTint), just
         drawn as a bar instead of a single tinted border. Both hidden when there is
         nothing provisioned yet to average. ---- */
      #labMaverickBar {
        display: flex;
        align-items: center;
        gap: 10px;
        margin: 4px 0 8px;
      }
      #labMaverickBarTrack {
        flex: 1 1 auto;
        height: 10px;
        border-radius: 999px;
        background: #eef1f8;
        overflow: hidden;
      }
      #labMaverickBarFill {
        display: block;
        height: 100%;
        border-radius: 999px;
        background: var(--maverick, #dfe6f5);
        transition: width 0.25s, background 0.25s;
      }
      #labMaverickBarLabel {
        flex: none;
        font: 700 12px system-ui, sans-serif;
        color: #6b7280;
        white-space: nowrap;
      }
      /* ---- past grants (tower panel): awarded RFPs, their winners, and — expanding a
         winner — that lab's projects and papers. Mirrors .labRfpRow / .grantsArea's
         card-and-row conventions; abandoned grants get the same grey palette as
         .chip-grant-abandoned. See syncPastGrantsSection / renderPastGrantsList. ---- */
      .pastGrantRow {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 8px;
        background: #fafbff;
      }
      .pastGrantTitle {
        font-weight: 700;
        color: #1f2937;
      }
      .pastGrantMeta {
        font-size: 12px;
        color: #6b7280;
        margin: 2px 0 4px;
      }
      .pastGrantWinners {
        display: none;
        flex-direction: column;
        margin-top: 8px;
      }
      .pastGrantWinners.open {
        display: flex;
      }
      .pastGrantWinnerRow {
        padding: 6px 0;
        border-top: 1px solid #eef1f8;
        cursor: pointer;
      }
      .pastGrantWinnerTop {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
      }
      .pastGrantWinnerWho {
        font-weight: 600;
        font-size: 13px;
        color: #374151;
        flex: 1 1 auto;
        min-width: 90px;
      }
      .pastGrantWinnerRow.abandoned {
        opacity: 0.65;
      }
      .pastGrantWinnerRow.abandoned .pastGrantWinnerWho {
        color: #6b7280;
      }
      .pastGrantWinnerNote {
        flex-basis: 100%;
        font-size: 12px;
        color: #6b7280;
      }
      .pastGrantWinnerDetail {
        display: none;
        margin: 8px 0 4px;
        padding-left: 4px;
        border-left: 3px solid #e3e8f5;
      }
      .pastGrantWinnerDetail.open {
        display: block;
      }
      .awardNote.pastGrantNote {
        border-top: 0;
        padding-top: 0;
        margin-top: 4px;
      }
      .pastGrantVanishedToggle {
        display: block;
        margin-top: 4px;
        padding: 0;
        border: 0;
        background: none;
        font-size: 12px;
        color: #6b7280;
        text-decoration: underline;
        cursor: pointer;
      }
      .pastGrantVanishedToggle:hover {
        color: #374151;
      }

      /* ---- lab panel "Work in progress" / "Papers", and the tower's per-winner project
         drill-down — both render the same project-row shape (see projectRowEl in
         main.js). The stages are a process flow (.projFlow): a named step per stage
         coloured by its state — "active" pulses like .chip-pending — with an arrow
         between steps; a vanished row gets .chip-grant-abandoned's grey. ---- */
      .projRow {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 8px;
        background: #fafbff;
      }
      .projRow.vanished {
        background: #f7f8fb;
        border-color: #eef1f8;
        opacity: 0.7;
      }
      .projTop {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
      }
      .projName {
        font-weight: 700;
        color: #1f2937;
        flex: 1 1 auto;
        min-width: 90px;
      }
      .projRow.vanished .projName {
        color: #6b7280;
      }
      .projPhase {
        font-size: 12px;
        color: #6b7280;
      }
      .projNote {
        flex-basis: 100%;
        font-size: 12px;
        color: #6b7280;
      }
      .projFlow {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 4px 0;
        margin-top: 8px;
      }
      .projStep {
        display: inline-flex;
        align-items: center;
        padding: 3px 8px;
        border: 1px solid transparent;
        border-radius: 6px;
        font: 600 11px system-ui, sans-serif;
        white-space: nowrap;
        cursor: default;
      }
      .projStep-done {
        background: #eafaf3;
        border-color: #bfeeda;
        color: #1a9c6a;
      }
      .projStep-active {
        background: #eef2ff;
        border-color: #6c7bff;
        color: #2b3a67;
        animation: chipPulse 1.6s ease-in-out infinite;
      }
      .projStep-pending {
        background: #fff;
        border-color: #e3e8f5;
        color: #9199b3;
      }
      .projStep-blocked {
        background: #fff1ea;
        border-color: #f7c6ad;
        color: #c2410c;
      }
      .projStep-skipped {
        background: #f3f4f8;
        border-color: #e3e8f5;
        color: #9ca3af;
        text-decoration: line-through;
      }
      .projArrow {
        padding: 0 4px;
        font: 700 12px system-ui, sans-serif;
        color: #cfd5e4;
      }
      .projArrow-done {
        color: #34c48a;
      }
      .projPaperLine {
        margin-top: 8px;
      }
      .projPaperLink {
        border: 0;
        background: none;
        padding: 0;
        font: 600 13px system-ui, sans-serif;
        color: #2b3a67;
        text-decoration: underline;
        cursor: pointer;
      }
      .projPaperLink:hover {
        color: #ff4fd0;
      }
      #labPaperFilters {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin-bottom: 8px;
      }
      .paperFilterChip {
        border: 2px solid #dfe6f5;
        background: #fff;
        color: #6b7280;
        border-radius: 999px;
        padding: 4px 12px;
        font: 600 12px system-ui, sans-serif;
        cursor: pointer;
      }
      .paperFilterChip.on {
        background: #eef2ff;
        border-color: #c3d4ff;
        color: #2b3a67;
      }
      .paperRow {
        border: 1px solid #e3e8f5;
        border-radius: 10px;
        padding: 8px 12px;
        margin-bottom: 6px;
        background: #fafbff;
      }
      .paperRowBy {
        font-size: 12px;
        color: #6b7280;
        margin-top: 2px;
      }

      /* ---- paper reader overlay: a dimmed backdrop, a single-column card, × to close ---- */
      #paperModal {
        position: fixed;
        inset: 0;
        z-index: 16; /* over the interior and the panel, under the office editor (20) */
        display: none;
        align-items: center;
        justify-content: center;
        background: rgba(31, 36, 48, 0.55);
        backdrop-filter: blur(3px);
      }
      body.paperOpen #paperModal {
        display: flex;
      }
      #pmCard {
        position: relative;
        width: min(860px, 92vw);
        height: 84vh;
        background: #fff;
        color: #1f2430;
        border-radius: 22px;
        box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
        overflow: hidden;
      }
      #pmClose {
        position: absolute;
        top: 16px;
        right: 20px;
        z-index: 2;
        border: 0;
        background: #f3f4f8;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        font-size: 22px;
        cursor: pointer;
        color: #374151;
      }
      #pmClose:hover {
        background: #e5e7ee;
      }
      #pmScroll {
        height: 100%;
        overflow-y: auto;
        box-sizing: border-box;
        padding: 40px 56px 48px;
      }
      /* Prev / Next across a list of proposals: a bar floating over the foot of the
         card, so the text scrolls beneath it */
      #pmNav {
        position: absolute;
        left: 50%;
        bottom: 18px;
        transform: translateX(-50%);
        z-index: 2;
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 6px 8px;
        background: #fff;
        border: 2px solid #dfe6f5;
        border-radius: 14px;
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
      }
      #pmNav button {
        border: 0;
        background: #f3f4f8;
        color: #2b3a67;
        border-radius: 10px;
        padding: 7px 14px;
        font: 700 14px system-ui, sans-serif;
        cursor: pointer;
      }
      #pmNav button:hover:not(:disabled) {
        background: #e5e7ee;
      }
      #pmNav button:disabled {
        color: #b3b9cc;
        cursor: default;
      }
      #pmNavPos {
        font: 600 12px system-ui, sans-serif;
        color: #6b7280;
        min-width: 60px;
        text-align: center;
      }
      #pmCard:has(#pmNav:not([hidden])) #pmScroll {
        padding-bottom: 96px; /* room under the last line for the bar */
      }
      #pmScroll h1 {
        margin: 0 0 6px;
        font-family:
          "Luckiest Guy", "Fredoka One", "Arial Rounded MT Bold",
          "Comic Sans MS", sans-serif;
        font-size: 30px;
        color: #2b3a67;
        letter-spacing: 0.02em;
        line-height: 1.15;
        padding-right: 48px;
      }
      #pmScroll h2 {
        font-size: 16px;
        margin: 22px 0 8px;
        color: #2b3a67;
      }
      #pmText {
        white-space: pre-wrap;
        word-break: break-word;
        font: 15px/1.65 system-ui, sans-serif;
        color: #374151;
        margin: 14px 0 0;
      }
      #pmArtifacts {
        list-style: none;
        margin: 0;
        padding: 0;
      }
      #pmArtifacts li {
        display: flex;
        justify-content: space-between;
        gap: 12px;
        padding: 6px 0;
        border-top: 1px solid #eef1f8;
        font-size: 13px;
        color: #374151;
      }
      #pmArtifacts li:first-child {
        border-top: 0;
      }
      #pmArtifacts .pmArtifactSize {
        flex: none;
        color: #9199b3;
        font-variant-numeric: tabular-nums;
      }

/* click-to-read proposal links (lab panel line + tower ranked-row detail) */
.proposalReadLink {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: #6c7bff;
  cursor: pointer;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.proposalReadLink:hover {
  color: #8a96ff;
}

/* rename button on a player city's picker label — the delete button's twin in size
   and border, but always on show: renaming is the one thing you go to a label to do,
   so it must not need a hover to be found. Only the hover colour differs. */
.cityRenameBtn {
  background: #fff;
  color: #2b3a67;
  border: 2px solid #dfe6f5;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  padding: 0;
  font: bold 13px system-ui;
  cursor: pointer;
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}
.cityRenameBtn:hover {
  background: #f3f6ff;
  border-color: #6c7bff;
}
/* both buttons share one row under the label, so ✎ sits beside ✕ rather than above it */
.cityLabelBtns {
  display: flex;
  gap: 6px;
}
body:not(.selecting) .cityRenameBtn {
  display: none;
}

/* ---- rename dialog: the card itself is the confirm dialog's (see #cmCard above),
   only the backdrop, the width and the Save button are its own ---- */
#renameModal {
  position: fixed;
  inset: 0;
  z-index: 40; /* same shelf as the delete confirmation: above the picker and the panel */
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(31, 36, 48, 0.6);
  backdrop-filter: blur(3px);
}
body.renaming #renameModal {
  display: flex;
}
#rnCard {
  width: min(440px, 92vw);
}
/* a refused name says why; an empty line takes up no room */
#rnError {
  color: #d7263d;
  font-size: 13px;
}
#rnError:empty {
  display: none;
}
#rnOk {
  border-color: #6c7bff;
  background: #6c7bff;
  color: #fff;
}
#rnOk:hover {
  background: #5765e8;
}
#rnOk:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: #6c7bff;
}
/* ---- new proposal dialog (the Call-for-Proposals Office's form): the confirm/rename
   card's shape, wider, with the RFP fields inside; Esc, × or the backdrop close it ---- */
#rfpModal {
  position: fixed;
  inset: 0;
  z-index: 40; /* same shelf as the rename dialog: above the interior and its floor */
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(31, 36, 48, 0.6);
  backdrop-filter: blur(3px);
}
body.rfpComposing #rfpModal {
  display: flex;
}
#rfpCard {
  position: relative;
  width: min(960px, 94vw);
  max-height: 92vh;
  overflow-y: auto;
  box-sizing: border-box;
  background: #fff;
  color: #1f2430;
  border-radius: 22px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
  padding: 28px 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: system-ui, sans-serif;
}
#rfpCard h1 {
  margin: 0;
  font-size: 24px;
  line-height: 1.2;
}
#rfpCard .rfpModalNote {
  margin: 0 0 6px;
  font-size: 13px;
  line-height: 1.5;
  color: #5b6478;
}
#rfpModalClose {
  position: absolute;
  top: 16px;
  right: 18px;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: #f0f2f8;
  color: #2b3a67;
  font: 600 18px system-ui, sans-serif;
  line-height: 32px;
  cursor: pointer;
}
#rfpModalClose:hover {
  background: #e3e8f5;
}
#rfpCard .settingsField {
  margin-bottom: 0;
}
#rfpCard #rfpBody {
  min-height: 340px;
  line-height: 1.5;
  tab-size: 2;
}
#rfpCard #rfpCriteria {
  min-height: 88px;
}
/* the Body field's head: the label and the Preview / Edit toggle on one line */
.rfpFieldHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}
.rfpFieldHead span {
  margin-bottom: 0;
}
/* the body, rendered: the textarea's box with the markdown inside */
#rfpBodyPreview {
  box-sizing: border-box;
  min-height: 340px;
  max-height: 60vh;
  overflow-y: auto;
  padding: 10px 12px;
  border: 2px solid #dfe6f5;
  border-radius: 10px;
  font: 500 14px system-ui, sans-serif;
  line-height: 1.5;
  color: #1f2430;
  background: #fafbff;
}
#rfpBodyPreview[hidden] {
  display: none;
}
#rfpBodyPreview:empty::before {
  content: "Nothing to preview.";
  color: #a3adc9;
}
#rfpStatus {
  font-size: 13px;
  color: #6b7280;
}
#rfpStatus:empty {
  display: none;
}
#rfpStatus.warn {
  color: #c2410c;
}
#rfpCard .rfpSave {
  border-color: #6c7bff;
  background: #6c7bff;
  color: #fff;
}
#rfpCard #rfpBody[hidden] {
  display: none; /* #rfpCard textarea's display: block would otherwise win over [hidden] */
}
#rfpCard .rfpSave:hover:not(:disabled) {
  background: #5765e8;
}
#rfpSubmit:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: #6c7bff;
}
/* ---- send to labs (the lab picker): the proposal dialog's shape, narrower, with the
   City Info Labs tab's list inside (.lRow rows, each with a checkbox) ---- */
#labPickModal {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(31, 36, 48, 0.6);
  backdrop-filter: blur(3px);
}
body.labPicking #labPickModal {
  display: flex;
}
#lpCard {
  position: relative;
  width: min(560px, 92vw);
  max-height: 88vh;
  box-sizing: border-box;
  background: #fff;
  color: #1f2430;
  border-radius: 22px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
  padding: 28px 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: system-ui, sans-serif;
}
#lpCard h1 {
  margin: 0;
  padding-right: 40px;
  font-size: 24px;
  line-height: 1.2;
}
#lpCard .rfpModalNote {
  margin: 0;
}
#lpClose {
  position: absolute;
  top: 16px;
  right: 18px;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: #f0f2f8;
  color: #2b3a67;
  font: 600 18px system-ui, sans-serif;
  line-height: 32px;
  cursor: pointer;
}
#lpClose:hover {
  background: #e3e8f5;
}
/* the tag filter: the lab panel's own chips; a lit chip narrows the list to labs
   carrying it (several lit: any of them) */
#lpTags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
#lpTags:empty {
  display: none;
}
#lpTools {
  display: flex;
  align-items: center;
  gap: 6px;
}
#lpTools .infoSearch {
  flex: 1;
  margin: 0;
}
#lpTools .ghostBtn {
  margin: 0;
  padding: 5px 10px;
  font-size: 12px;
}
#lpList {
  flex: 1 1 auto;
  min-height: 120px;
  max-height: 48vh;
  border: 1px solid #eef1f8;
  border-radius: 10px;
  padding: 2px 8px;
}
#lpList .lRow {
  margin: 0;
}
#lpList .lRow input {
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: #6c7bff;
  cursor: pointer;
}
#lpList .lRow.muted input {
  visibility: hidden;
}
#lpList .lRow .lpTag {
  color: #8a93a8;
  font-weight: 500;
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}
/* one group per lab: the lab's own .lRow (its checkbox toggles every researcher
   of it that can be picked), then a .lpRes row per researcher, indented under it */
#lpList .lpGroup {
  border-bottom: 1px solid #eef1f8;
  padding-bottom: 4px;
}
#lpList .lpGroup .lRow {
  border-bottom: 0;
}
#lpList .lpRes {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 4px 3px 30px;
  margin: 0 -4px;
  border-radius: 8px;
  font: 500 12px system-ui, sans-serif;
  color: #374151;
  cursor: pointer;
}
#lpList .lpRes:hover {
  background: #f3f4f8;
}
#lpList .lpRes.muted {
  color: #8a93a8;
  cursor: default;
}
#lpList .lpRes.muted input {
  visibility: hidden;
}
/* already has a proposal on this RFP: shown ticked and settled, with the status chip */
#lpList .lpRes.applied {
  color: #8a93a8;
  cursor: default;
}
#lpList .lpRes.applied input {
  cursor: default;
}
#lpList .lpRes .chip {
  flex: none;
}
#lpList .lpRes input {
  flex: none;
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: #6c7bff;
  cursor: pointer;
}
#lpList .lpRes .nm {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#lpList .lpRes .ct {
  color: #8a93a8;
  font-size: 11px;
  white-space: nowrap;
}
#lpList .pEmpty {
  padding: 18px 4px;
  color: #8a93a8;
  font: 600 12px system-ui, sans-serif;
}
#lpStatus {
  font-size: 13px;
  color: #6b7280;
}
#lpStatus:empty {
  display: none;
}
#lpStatus.warn {
  color: #c2410c;
}
#lpCard .rfpSave {
  border-color: #6c7bff;
  background: #6c7bff;
  color: #fff;
}
#lpCard .rfpSave:hover:not(:disabled) {
  background: #5765e8;
}
#lpCard .rfpSave:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
/* ---- the office's rows and the review board (both floors share .rfpRow) ---- */
/* a draft's row is not a door: its head is plain and its buttons do the work */
.rfpDraftRow .rfpRowHead {
  cursor: default;
}
.rfpDraftRow .rfpRowHead:hover {
  background: none;
}
.rfpRowActions {
  display: flex;
  gap: 8px;
  padding: 0 12px 12px;
}
.rfpRowActions .labAdd {
  margin-bottom: 0;
}
.rfpRowActions .inlineRowError {
  flex-basis: 100%;
}
/* a dispatched row on the office floor: the head says where it leads */
.rfpRowHead.rfpRowGo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.rfpRowGoHint {
  flex: none;
  font: 600 12px system-ui, sans-serif;
  color: #6c7bff;
}
/* the lifecycle bar at the top of a board row's detail: where the RFP is, and the
   one step it can take from there */
.rfpLifecycleBar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 10px;
  margin-bottom: 8px;
  background: #f3f6ff;
  border-radius: 10px;
}
.rfpLifecycleState {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: #4b5563;
}
.rfpLifecycleBar .ghostBtn {
  margin: 0;
}
.rfpLifecycleError {
  flex-basis: 100%;
  font-size: 12px;
  color: #c2410c;
}
.rfpLifecycleError:empty {
  display: none;
}
/* the RFP's own lifecycle chip (a different vocabulary from a proposal's .chip-*) */
.chip-life-draft {
  background: #f3f4f8;
  color: #6b7280;
}
.chip-life-open {
  background: #eafaf3;
  color: #1a9c6a;
}
.chip-life-closed {
  background: #fff4e0;
  color: #b45309;
}
.chip-life-awarding {
  background: #eef2ff;
  color: #2b3a67;
  animation: chipPulse 1.6s ease-in-out infinite;
}
.chip-life-awarded {
  background: #ecebff;
  color: #4c5bd9;
}
.chip-life-complete {
  background: #e6f4fb;
  color: #0e6f9c;
}
.chip-life-archived {
  background: #f3f4f8;
  color: #9ca3af;
}
/* on the lab panel: an RFP a researcher can no longer apply to */
.labRfpClosedNote {
  font-size: 12px;
  color: #9199b3;
}
/* the funded detail on the board: what moved, then the winners */
.fundedSummary {
  font-size: 12px;
  color: #6b7280;
  margin: 6px 0 4px;
}

/* rendered markdown inside the paper/proposal overlay */
#pmText { white-space: normal; }
#pmText p { margin: 0 0 0.8em; line-height: 1.55; }
#pmText h2, #pmText h3, #pmText h4 { margin: 1.1em 0 0.4em; line-height: 1.25; }
#pmText ul, #pmText ol { margin: 0 0 0.8em; padding-left: 1.4em; }
#pmText li { margin: 0.2em 0; }
#pmText blockquote { margin: 0 0 0.8em; padding: 0.2em 0.9em; border-left: 3px solid #c9d1ea; color: #555e78; }
#pmText code { background: #eef1fa; border-radius: 4px; padding: 0.05em 0.35em; font-size: 0.92em; }
#pmText pre.mdCode { background: #14151d; color: #e8e9f0; border-radius: 8px; padding: 12px 14px; overflow-x: auto; margin: 0 0 0.8em; white-space: pre; }

/* markdown tables + citation links in the overlay */
#pmText .mdTableWrap { overflow-x: auto; margin: 0 0 0.9em; }
#pmText table.mdTable { border-collapse: collapse; font-size: 0.93em; min-width: 60%; }
#pmText .mdTable th, #pmText .mdTable td { border: 1px solid #d5dbee; padding: 6px 10px; text-align: left; vertical-align: top; }
#pmText .mdTable th { background: #eef1fa; font-weight: 600; }
#pmText .mdTable tr:nth-child(even) td { background: #f7f8fd; }
#pmText .mdLink { color: #6c7bff; border-bottom: 1px dotted #6c7bff; cursor: help; }

/* what the money started: kickoff chips on grant rows */
.chip-kickoff-created { background: #e5f8ee; color: #157a4c; }
.chip-kickoff-pending, .chip-kickoff-waiting { background: #fdf3e2; color: #8a6116; }
.chip-kickoff-unavailable, .chip-kickoff-failed { background: #fdeaea; color: #a13030; }
/* ---- LabChat: the researcher modal's chat tab, styled after Slack ---- */
#slk {
  flex: 1;
  min-height: 0;
  display: flex;
  border-top: 1px solid #e3e8f5;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  color: #1d1c1d;
}
#slkSide {
  flex: none;
  width: 200px;
  background: #3f0e40;
  color: #cfc3cf;
  overflow-y: auto;
  padding-bottom: 12px;
}
#slkWorkspace {
  padding: 12px 16px;
  border-bottom: 1px solid #522653;
  color: #fff;
  font-weight: 800;
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#slkWorkspace .slkChevron { font-weight: 400; opacity: 0.7; }
.slkSection {
  padding: 14px 16px 4px;
  font-size: 13px;
  font-weight: 600;
  color: #cfc3cf;
  opacity: 0.85;
}
#slkSide ul { list-style: none; margin: 0; padding: 0; }
#slkSide li {
  padding: 4px 16px 4px 20px;
  font-size: 15px;
  line-height: 1.4;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 8px;
}
#slkSide li:hover { background: #350d36; color: #fff; }
#slkSide li.on { background: #1164a3; color: #fff; }
#slkSide li .slkHash { opacity: 0.7; font-weight: 400; }
#slkSide li.unread { color: #fff; font-weight: 700; }
#slkSide li .slkBadge {
  margin-left: auto;
  background: #cd2553;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 7px;
}
#slkSide li .slkPresence {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1.5px solid #cfc3cf;
  flex: none;
}
#slkSide li .slkPresence.on { background: #2bac76; border-color: #2bac76; }
#slkMain {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: #fff;
}
#slkHead {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid #e3e8f5;
  font-weight: 800;
  font-size: 16px;
}
#slkMembers {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: #616061;
  border: 1px solid #e3e8f5;
  border-radius: 6px;
  padding: 2px 8px 2px 4px;
}
#slkMembers .slkAvatar { width: 20px; height: 20px; border-radius: 4px; font-size: 8px; margin-right: -6px; }
#slkMembers .slkAvatar:last-of-type { margin-right: 4px; }
#slkMsgs {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 8px 0 12px;
}
.slkDay {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 10px 0 6px;
  color: #616061;
  font-size: 12px;
}
.slkDay::before, .slkDay::after { content: ""; flex: 1; border-top: 1px solid #e3e8f5; }
.slkDay span {
  border: 1px solid #e3e8f5;
  border-radius: 999px;
  padding: 3px 12px;
  font-weight: 700;
  color: #1d1c1d;
  background: #fff;
}
.slkMsg {
  display: flex;
  gap: 10px;
  padding: 5px 16px 5px 16px;
  align-items: flex-start;
}
.slkMsg:hover { background: #f8f8f8; }
.slkMsg.cont { padding-top: 1px; padding-bottom: 3px; }
.slkMsg .slkAvatar {
  width: 36px;
  height: 36px;
  border-radius: 6px;
  font-size: 13px;
}
.slkMsg.cont .slkAvatar { visibility: hidden; height: 0; }
.slkMsg .slkGutter {
  flex: none;
  width: 36px;
  font-size: 10px;
  color: #616061;
  text-align: right;
  padding-top: 3px;
  opacity: 0;
}
.slkMsg.cont:hover .slkGutter { opacity: 1; }
.slkBody { min-width: 0; flex: 1; }
.slkWho { display: flex; align-items: baseline; gap: 6px; }
.slkName { font-weight: 900; font-size: 15px; }
.slkApp {
  font-size: 10px;
  font-weight: 700;
  color: #616061;
  background: #e8e8e8;
  border-radius: 3px;
  padding: 0 4px;
  line-height: 1.5;
}
.slkTime { font-size: 12px; color: #616061; }
.slkText { font-size: 15px; line-height: 1.46; overflow-wrap: anywhere; }
.slkText .slkMention {
  background: #e8f5fa;
  color: #1264a3;
  border-radius: 3px;
  padding: 0 2px;
  font-weight: 600;
}
.slkText code {
  background: #f8f8f8;
  border: 1px solid #e3e8f5;
  border-radius: 3px;
  padding: 1px 4px;
  font-size: 12.5px;
  color: #e01e5a;
}
.slkReacts { display: flex; gap: 4px; margin-top: 4px; flex-wrap: wrap; }
.slkReact {
  border: 1px solid #e3e8f5;
  background: #f8f8f8;
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 12px;
  color: #1d1c1d;
}
.slkReact.mine { background: #e8f5fa; border-color: #1264a3; color: #1264a3; }
.slkThread {
  margin-top: 4px;
  font-size: 13px;
  color: #1264a3;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 6px;
}
.slkThread .slkAvatar { width: 20px; height: 20px; border-radius: 4px; font-size: 8px; }
.slkThread small { color: #616061; font-weight: 400; }
#slkCompose {
  flex: none;
  margin: 0 16px 16px;
  border: 1px solid #8d8d8d;
  border-radius: 8px;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "bar bar" "input send";
  overflow: hidden;
  opacity: 0.85;
}
#slkCompose .slkToolbar {
  grid-area: bar;
  display: flex;
  gap: 14px;
  padding: 6px 12px;
  background: #f8f8f8;
  color: #616061;
  font-size: 13px;
  border-bottom: 1px solid #e3e8f5;
}
#slkCompose .slkInput {
  grid-area: input;
  padding: 10px 12px;
  font-size: 15px;
  color: #8d8d8d;
  cursor: not-allowed;
}
#slkCompose .slkSend {
  grid-area: send;
  align-self: end;
  margin: 6px 8px;
  background: #007a5a;
  color: #fff;
  border-radius: 4px;
  padding: 2px 10px;
  font-size: 13px;
  opacity: 0.6;
}
#slkMsgs .none { padding: 24px 16px; color: #616061; }

/* the office's one-click proposal reader on each ranked row */
.rankedReadCell { display: flex; align-items: center; justify-content: center; }
.rankedReadCell .proposalReadLink { text-decoration: none; border-bottom: 0; font-size: 15px; }

/* the Research Library's shelves */
#libraryList .libraryShelf { margin: 0 0 18px; }
#libraryList .libraryShelf h3 { margin: 0 0 8px; font-size: 14px; }

/* the paper reader's typeset-PDF button */
#pmOpenPdf {
  margin: 8px 0 0;
  padding: 6px 14px;
  border: 1px solid #c9d1ea;
  border-radius: 8px;
  background: #f3f6ff;
  color: #2b3352;
  font: 600 13px system-ui, sans-serif;
  cursor: pointer;
}
#pmOpenPdf:hover { border-color: #6c7bff; }

/* the reproducibility kit on a project row */
.projReproLine { margin-top: 4px; }
.projReproToggle { background: none; border: 0; padding: 0; font: inherit; font-size: 12px; color: #6c7bff; cursor: pointer; }
.projReproList { margin: 6px 0 2px 14px; font-size: 12px; color: #555e78; }
.reproPkg { margin: 0 0 6px; }
.reproPkgHead { display: flex; gap: 10px; align-items: baseline; }
.reproPkgMeta { color: #9199b3; }
.reproDl { color: #6c7bff; text-decoration: none; border-bottom: 1px dotted #6c7bff; }
.reproDlAll { display: inline-block; margin-top: 2px; }

/* the embedded rendered paper */
#pmPdfFrame { width: 100%; height: min(75vh, 900px); border: 1px solid #d5dbee; border-radius: 8px; background: #fff; margin: 0 0 12px; }

/* Talk: the 1:1 chat with a researcher */
#rmTalkPane { background: #fff; color: #1f2430; font: 14px system-ui, sans-serif; padding: 4px 14px 8px; box-sizing: border-box; }
#talkMsgs { flex: 1; overflow-y: auto; padding: 12px 4px; display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.talkMsg { display: flex; gap: 8px; align-items: flex-end; }
.talkMsg.player { justify-content: flex-end; }
.talkMsg .talkBody { max-width: 78%; padding: 8px 12px; border-radius: 12px; font-size: 13px; line-height: 1.45; white-space: pre-wrap; }
.talkMsg.player .talkBody { background: #6c7bff; color: #fff; border-bottom-right-radius: 4px; }
.talkMsg.researcher .talkBody { background: #eef1fa; color: #1d2030; border-bottom-left-radius: 4px; }
.talkMsg.thinking .talkBody { color: #7a8098; font-style: italic; }
.talkAvatar { width: 26px; height: 26px; border-radius: 50%; background: var(--maverick, #6c7bff); display: flex; align-items: center; justify-content: center; font: 700 10px system-ui; color: #fff; flex-shrink: 0; }
#talkCompose { display: flex; gap: 8px; padding: 8px 4px 0; }
#talkCompose input { flex: 1; padding: 8px 12px; border-radius: 8px; border: 1px solid #c9d1ea; font: inherit; }
#talkStatus { color: #a13030; font-size: 12px; padding: 4px; min-height: 18px; }

/* The Mac folder and page icons: plain boxes, sized off --s so the same icon serves the
   desktop (in cq units, scaling with the glass) and the Finder's window (in px). */
.icoFolder {
  --s: 56px;
  position: relative;
  flex: none;
  width: var(--s);
  height: calc(var(--s) * 0.78);
}
.icoFolder span {
  position: absolute;
  left: 0;
  right: 0;
}
.icoFolder .tab {
  top: 0;
  right: 55%;
  height: calc(var(--s) * 0.2);
  border-radius: calc(var(--s) * 0.07) calc(var(--s) * 0.1) 0 0;
  background: #2f8ae4;
}
.icoFolder .back {
  top: calc(var(--s) * 0.12);
  bottom: 0;
  border-radius: calc(var(--s) * 0.1);
  background: linear-gradient(#3f9bf0, #1466c9);
}
.icoFolder .front {
  top: calc(var(--s) * 0.26);
  bottom: 0;
  border-radius: calc(var(--s) * 0.07) calc(var(--s) * 0.07) calc(var(--s) * 0.1) calc(var(--s) * 0.1);
  background: linear-gradient(#63bcfb, #1f7fe4);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.icoFile {
  --s: 46px;
  position: relative;
  flex: none;
  width: var(--s);
  height: calc(var(--s) * 1.28);
  border: 1px solid #d5d8e0;
  border-radius: 4px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(20, 30, 60, 0.12);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: calc(var(--s) * 0.16);
}
.icoFile .fold {
  position: absolute;
  top: -1px;
  right: -1px;
  border-top: calc(var(--s) * 0.3) solid #eef1f6;
  border-left: calc(var(--s) * 0.3) solid transparent;
  border-radius: 0 3px 0 0;
}
.icoFile b {
  font: 700 calc(var(--s) * 0.24) system-ui, sans-serif;
  letter-spacing: 0.04em;
}
.icoFile.pdf b {
  color: #d5372f;
}
.icoFile.tex b {
  color: #2f6fd5;
}

/* My Papers on the desktop: the one icon on the glass, under the windows */
#deskIcons {
  position: absolute;
  top: 5cqw;
  /* the left, not the Mac's right: the photo's glare falls on the glass's top right
     corner (#deskGlare) and washes an icon parked under it out */
  left: 2cqw;
  display: flex;
  flex-direction: column;
  gap: 1.5cqw;
  align-items: center;
}
.deskIcon {
  width: 9cqw;
  border: 0;
  background: none;
  padding: 0.5cqw;
  border-radius: 0.8cqw;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5cqw;
  cursor: pointer;
}
.deskIcon .icoFolder {
  filter: drop-shadow(0 0.3cqw 0.5cqw rgba(0, 25, 45, 0.55));
}
.deskIcon:hover {
  background: rgba(255, 255, 255, 0.22);
}
.deskIconLabel {
  font: 600 1.25cqw system-ui, sans-serif;
  color: #fff;
  text-shadow: 0 0.1cqw 0.25cqw rgba(0, 30, 50, 0.65);
}

/* the Finder window My Papers opens: a folder per paper, and in it the PDF and the LaTeX
   it was built from. Nothing opens — a click selects, and the footer names what is there. */
.deskZoom > .fndr {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  font: 14px system-ui, -apple-system, sans-serif;
  background: #fff;
  color: #1d1d1f;
}
.fndrBar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border-bottom: 1px solid #e3e3e6;
}
.fndrBack {
  border: 1px solid #d7d9e0;
  background: #fff;
  border-radius: 7px;
  padding: 2px 10px 4px;
  font: 15px system-ui;
  line-height: 1.1;
  color: #1d1d1f;
  cursor: pointer;
}
.fndrBack:disabled {
  color: #c3c6cf;
  cursor: default;
}
.fndrPath {
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fndrBody {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 10px;
  padding: 16px;
}
.fndrItem {
  width: 132px;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  padding: 8px 4px 6px;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  cursor: pointer;
}
.fndrItem:hover {
  background: #f2f4f8;
}
.fndrName {
  font-size: 12px;
  line-height: 1.25;
  text-align: center;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  padding: 1px 5px;
  border-radius: 5px;
}
.fndrItem.on .fndrName {
  background: #2f6fd5;
  color: #fff;
}
.fndrFoot {
  flex: none;
  padding: 7px 14px;
  border-top: 1px solid #e3e3e6;
  color: #8e8e93;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Schedule: the researcher's calendar, an app on their computer's desktop. A week (or a
   day) of the city's own calendar, drawn as a time grid: what is behind the city's now is
   ticked, what slipped is marked late. Built by buildDeskSchedule — it is the one desk app
   that isn't one of the modal's panes, so it styles its own window. */
.deskZoom > .deskCal {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  font: 14px system-ui, -apple-system, sans-serif;
  background: #fff;
  color: #1d1d1f;
}
.calBar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid #e3e3e6;
}
.calNav,
.calSeg {
  display: flex;
  gap: 4px;
}
.calNav button,
.calSeg button {
  border: 1px solid #d7d9e0;
  background: #fff;
  border-radius: 7px;
  padding: 4px 10px;
  font: inherit;
  line-height: 1.1;
  color: #1d1d1f;
  cursor: pointer;
}
.calNav button:hover,
.calSeg button:hover {
  background: #f3f4f8;
}
.calSeg button.on {
  background: #e8453c;
  border-color: #e8453c;
  color: #fff;
}
.calTitle {
  flex: 1;
  font-weight: 700;
  font-size: 16px;
}
/* the heads and the grid share one template, so a day's column lines up with its name */
.calHead,
.calGrid {
  display: grid;
  grid-template-columns: 54px repeat(var(--cols), minmax(0, 1fr));
}
.calHead {
  flex: none;
  border-bottom: 1px solid #e3e3e6;
  background: #fff;
}
.calDayHead {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 5px;
  padding: 6px 0 7px;
  border-left: 1px solid #eceef2;
  color: #8e8e93;
  font-size: 12px;
}
.calDate {
  font-size: 15px;
  font-weight: 600;
  color: #1d1d1f;
}
.calDayHead.today .calDate {
  background: #e8453c;
  color: #fff;
  border-radius: 999px;
  padding: 1px 7px;
}
.calWrap {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.calHours {
  position: relative;
}
.calHourLabel {
  height: var(--hour);
  padding-right: 7px;
  text-align: right;
  font-size: 11px;
  color: #8e8e93;
  transform: translateY(-6px);
}
.calCol {
  position: relative;
  border-left: 1px solid #eceef2;
  /* an hour a line, lightest on the half hour */
  background-image: repeating-linear-gradient(#eceef2 0 1px, transparent 1px var(--hour));
  background-position: 0 0;
}
.calCol.today {
  background-color: #fff8f7;
}
.calEv {
  position: absolute;
  overflow: hidden;
  border-radius: 5px;
  border-left: 3px solid;
  padding: 2px 5px;
  font-size: 12px;
  line-height: 1.25;
  cursor: default;
}
.calEvHead {
  display: flex;
  align-items: baseline;
  gap: 4px;
  white-space: nowrap;
}
.calEvTime {
  font-size: 11px;
  font-weight: 600;
  opacity: 0.7;
}
.calEvName {
  overflow: hidden;
  text-overflow: ellipsis;
}
.calEvNote {
  margin-top: 2px;
  font-size: 11.5px;
  opacity: 0.7;
  white-space: normal;
}
/* what is behind the city's now is struck through; what slipped is the red one */
.calEv.done .calEvName {
  text-decoration: line-through;
}
.calEv.done {
  opacity: 0.55;
}
.calEv.slip {
  border-left-color: #dc2626 !important;
  background: #fee2e2 !important;
  color: #991b1b !important;
}
.calEv.todo {
  border-left-style: dashed;
}
.calEv.read {
  background: #dbeafe;
  border-left-color: #2563eb;
  color: #1e3a8a;
}
.calEv.think {
  background: #ede9fe;
  border-left-color: #7c3aed;
  color: #4c1d95;
}
.calEv.social {
  background: #dcfce7;
  border-left-color: #16a34a;
  color: #14532d;
}
.calEv.admin {
  background: #fef3c7;
  border-left-color: #d97706;
  color: #78350f;
}
/* where the city's clock has got to today */
.calNow {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1.5px solid #e8453c;
  z-index: 3;
}
.calNow::before {
  content: "";
  position: absolute;
  left: -4px;
  top: -4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #e8453c;
}
.calFoot {
  flex: none;
  padding: 7px 14px;
  border-top: 1px solid #e3e3e6;
  color: #8e8e93;
  font-size: 12px;
}
.calEmpty {
  position: absolute;
  top: 12px;
  left: 0;
  right: 0;
  text-align: center;
  color: #b0b3b8;
  font-size: 12px;
}
.calNone {
  padding: 20px;
  color: #8e8e93;
  font-style: italic;
}

/* Memories: styled after Apple Notes — the list down the left with the open note
   highlighted in yellow, the note itself read on the right. A memory has no title,
   so its date heads the row. */
#rmMemoriesPane {
  font: 14px system-ui, -apple-system, sans-serif;
  background: #fff;
}
#rmMemoriesPane {
  flex-direction: row;
}
#notesList {
  flex: none;
  width: 250px;
  min-height: 0;
  overflow-y: auto;
  border-right: 1px solid #e3e3e6;
  background: #fff;
  padding: 0 8px 12px;
}
#notesListHead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 16px 12px 8px;
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 1;
}
#notesFolder {
  font-weight: 700;
  font-size: 17px;
  color: #1d1d1f;
}
#notesCount {
  font-size: 12px;
  color: #8e8e93;
}
.noteRow {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  font: inherit;
  padding: 10px 12px 9px;
  border-radius: 8px;
  cursor: pointer;
  position: relative;
}
.noteRow + .noteRow::before {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  top: 0;
  border-top: 1px solid #e7e7ea;
}
.noteRow.on,
.noteRow.on + .noteRow::before {
  border-top-color: transparent;
}
.noteRow.on {
  background: #fde49c;
}
.noteTitle {
  font-weight: 700;
  font-size: 14px;
  color: #1d1d1f;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.noteLine {
  display: flex;
  gap: 8px;
  margin-top: 2px;
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
}
.noteWhen {
  flex: none;
  color: #1d1d1f;
}
.notePreview {
  color: #8e8e93;
  overflow: hidden;
  text-overflow: ellipsis;
}
#rmMemories .none {
  padding: 14px 12px;
  color: #8e8e93;
  font-size: 12.5px;
  font-style: italic;
}
#notesRead {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  padding: 18px 36px 40px;
  background: #fff;
}
#notesRead.empty {
  visibility: hidden;
}
#notesReadWhen {
  text-align: center;
  font-size: 12px;
  color: #8e8e93;
  margin-bottom: 18px;
}
#notesReadTitle {
  margin: 0 0 14px;
  font-size: 24px;
  font-weight: 700;
  color: #1d1d1f;
}
#notesReadText {
  font-size: 15px;
  line-height: 1.6;
  color: #1d1d1f;
  white-space: pre-wrap;
}

/* ---------- read-only sessions: guest (viewer) and anonymous (public) ---------- */
/* The middleware enforces read-only; these rules just put the pens away so a
   guest is not offered buttons that would only 403. */
#viewerBadge {
  /* Below the title row, not level with it: #title ("Welcome to <city>") runs
     to 76px on the right and #back sits top-left, and a centre-anchored badge
     at 12px landed on top of the banner. 92px clears both; #hud (top 72px) is
     left-anchored, so the centre is free from here down. The Log in / Log out
     control this badge now carries only makes it wider, so it overlapped by
     more, not less. */
  position: fixed; top: 92px; left: 50%; transform: translateX(-50%);
  z-index: 4000; padding: 5px 6px 5px 14px; border-radius: 999px;
  background: #1d1f2bee; border: 1px solid #3a3e55; color: #c8cdE4;
  font: 600 12px system-ui, sans-serif;
  display: flex; align-items: center; gap: 10px;
}
#viewerBadge form { margin: 0; display: contents; }
#viewerBadge a, #viewerBadge button {
  font: inherit; color: #fff; background: #6c7bff; border: 0; border-radius: 999px;
  padding: 3px 10px; cursor: pointer; text-decoration: none; line-height: 1.4;
}
#viewerBadge a:hover, #viewerBadge button:hover { background: #7f8cff; }
/* On the city picker the badge's slot belongs to the "Select a City" heading
   (#select runs from 18px down to ~135px). Drop below that block: clear of the
   Prev/Next row, far above the city name label. */
body.selecting #viewerBadge { top: 148px; }
/* Foldable (main.js): × tucks the badge into a 👁 dot in the bottom-right
   corner, the dot unfolds it. The fold button is quiet, not a second pill. */
#viewerBadge button.vbFold {
  background: transparent; color: #8f95b3; padding: 0 6px; font-size: 15px; line-height: 1;
}
#viewerBadge button.vbFold:hover { background: transparent; color: #fff; }
#viewerBadge button.vbUnfold { display: none; background: transparent; padding: 2px 4px; font-size: 15px; }
#viewerBadge button.vbUnfold:hover { background: transparent; }
#viewerBadge.folded,
body.selecting #viewerBadge.folded {
  top: auto; bottom: 14px; left: auto; right: 14px; transform: none; padding: 3px; gap: 0;
}
#viewerBadge.folded > * { display: none; }
#viewerBadge.folded > button.vbUnfold { display: inline-block; }
#viewerBadge button:focus-visible { outline: 2px solid #9aa5ff; outline-offset: 2px; }
body.viewer #editBtn,
body.viewer #buildPanel,
body.viewer #csSave,
body.viewer #newCity,
/* Entry points, not just the submit buttons inside them: hiding #rfpSubmit but
   leaving #rfpNew opens a compose modal with no way to send, which reads as
   broken rather than as read-only. Same reasoning for the rest of this group —
   each one is a door, and its refusal would come from the far side of it. */
body.viewer #rfpNew,
body.viewer #addTag,
body.viewer #provisionRetry,
body.viewer #lpSend,
/* The city settings modal is an OPERATOR surface — it renders primusBaseUrl,
   the society key's prefix and the credit pool. Its GET is admin-only (403 for
   anyone else), so for a read-only session the button opens an empty panel
   advertising wiring they cannot see. */
body.viewer #csmAdd,
/* The office editor writes a lab's `office` JSON straight back through PUT
   /api/labs/:id. Hide the PEN that opens it (#officeEditor itself is only ever
   shown by body.officeEditing, so the door is the thing to take away) — and
   the editor with it, so no stray path can raise an invisible modal over the
   page. */
body.viewer .officeEdit,
body.viewer #officeEditor,
body.viewer #rfpSection .settingsField,
body.viewer #rfpSubmit,
body.viewer #rfpBodyPreviewBtn,
body.viewer .judgingSection > button,
body.viewer .awardControls,
body.viewer #labFound button,
body.viewer .labRfpResearcherRow button.labAdd,
body.viewer .labRfpMeta button,
body.viewer #talkCompose,
body.viewer .cityRenameBtn,
body.viewer .cityDeleteBtn,
body.viewer #levelUp,
body.viewer #levelDown,
body.viewer #tower,
body.viewer #megaOk,
body.viewer #blockMenu,
body.viewer #megaMove {
  display: none !important;
}
/* contenteditable surfaces (lab name, mandate, approach, researcher name)
   go inert rather than hidden — reading them is the point of the visit */
body.viewer [contenteditable] { pointer-events: none; }
/* The same treatment for the office row's other two pens, which are classes
   rather than contenteditable: the avatar picker saves through its own PUT
   /api/researchers/:id, and a trait becomes an input on click. Inert, not
   hidden — the portrait and the traits are worth looking at. */
body.viewer .officeAvatar.pickable,
body.viewer .officeTrait.editable { pointer-events: none; }

/* research continuation: follow-up on a project row, lineage on an RFP */
.projFollowUpLine { margin: 6px 0 0; }
.projFollowUpToggle { background: none; border: 1px solid #c9d1ea; border-radius: 6px; padding: 3px 10px; font: inherit; font-size: 12px; cursor: pointer; }
.projFollowUpToggle:hover { background: #f3f6ff; }
.projFollowUpForm { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; align-items: center; }
.projFollowUpForm select, .projFollowUpForm input { font: inherit; font-size: 12px; padding: 4px 6px; border: 1px solid #c9d1ea; border-radius: 6px; }
.projFollowUpForm input { flex: 1 1 180px; }
.projFollowUpStatus { font-size: 12px; color: #555e78; }
.rfpReferenceLine { margin: 4px 0; font-size: 13px; }
body.viewer .projFollowUpLine, body.viewer #rfpReferenceField, body.viewer #rfpReferenceSummaryField { display: none; }

/* ---- Zed: the society board, dressed as X ----
   Same convention as the LabChat block above: the parody is only funny if the
   palette is the real product's, so these are X's own values — #0f1419 ink,
   #536471 muted, #1d9bf0 blue, #eff3f4 / #cfd9de rules, #f7f9f9 hover — all
   scoped under #xf so none of it leaks into the city's own chunky-toy look. */
#xf {
  flex: 1;
  min-height: 0;
  display: flex;
  background: #fff;
  color: #0f1419;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  border-top: 1px solid #e3e8f5;
}

/* the icon rail: X at a narrow width, where the nav loses its labels */
#xfRail {
  flex: none;
  width: 68px;
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 0;
  border-right: 1px solid #eff3f4;
}
#xfRail .xfLogo {
  font-size: 26px;
  line-height: 1;
  padding: 8px;
  color: #0f1419;
}
#xfRail ul { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
#xfRail li {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-size: 19px;
  filter: grayscale(1);
  opacity: 0.55;
}
#xfRail li.on { opacity: 1; filter: none; }

/* X never lets the timeline run the full width of the window: it pins the
   column at 600px and lets the empty space fall outside. The auto margins on
   the rail and the sidebar centre the whole three-column group once the
   desktop window is maximised, and `flex: 1` still lets the column shrink
   below 600 when the window is small. */
#xfMain {
  flex: 1;
  min-width: 0;
  max-width: 600px;
  display: flex;
  flex-direction: column;
  border-right: 1px solid #eff3f4;
}
#xfHead {
  flex: none;
  position: sticky;
  top: 0;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid #eff3f4;
}
#xfTabs { display: flex; }
.xfTab {
  flex: 1;
  text-align: center;
  padding: 15px 0 14px;
  font-weight: 500;
  color: #536471;
  cursor: pointer;
  position: relative;
}
.xfTab:hover { background: #f7f9f9; }
.xfTab.on { color: #0f1419; font-weight: 700; }
.xfTab.on::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 0;
  width: 56px;
  height: 4px;
  border-radius: 999px;
  background: #1d9bf0;
}

/* the composer is scenery, exactly like LabChat's: nothing here is an input */
#xfCompose {
  flex: none;
  display: flex;
  gap: 12px;
  padding: 12px 16px 4px;
  border-bottom: 1px solid #eff3f4;
  cursor: default;
}
#xfCompose .xfAvatar { flex: none; }
.xfComposeBox { flex: 1; min-width: 0; }
.xfComposeHint { padding: 10px 0; font-size: 19px; color: #536471; }
.xfComposeBar { display: flex; align-items: center; gap: 14px; padding-bottom: 10px; }
.xfComposeBar span { font-size: 15px; opacity: 0.85; }
.xfPost {
  margin-left: auto;
  background: #0f1419;
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  padding: 7px 17px;
  border-radius: 999px;
  opacity: 0.45;
}

#xfFeed { flex: 1; min-height: 0; overflow-y: auto; }
#xfFeed .none { padding: 40px 24px; color: #536471; text-align: center; line-height: 1.5; }

/* one post. A thread is a stack of these inside .xfThread, joined by the rail
   that runs down behind the avatars. */
.xfThread { border-bottom: 1px solid #eff3f4; }
.xfPost0 {
  display: flex;
  gap: 12px;
  padding: 12px 16px 4px;
  position: relative;
}
.xfThread .xfPost0:last-child { padding-bottom: 10px; }
.xfPost0:hover { background: #f7f9f9; }
.xfCol { flex: none; width: 40px; display: flex; flex-direction: column; align-items: center; }
.xfPost0 .xfAvatar { flex: none; }
/* the connector: only drawn while something is still hanging below */
.xfCol .xfRail { flex: 1; width: 2px; margin: 4px 0 -4px; background: #cfd9de; border-radius: 1px; }
.xfBody { flex: 1; min-width: 0; padding-bottom: 8px; }
.xfWho { display: flex; align-items: baseline; gap: 5px; flex-wrap: wrap; line-height: 1.3; }
.xfName { font-weight: 700; color: #0f1419; }
.xfHandle, .xfDot, .xfAge { color: #536471; font-size: 15px; }
.xfBadge {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  background: #1d9bf0;
  border-radius: 4px;
  padding: 1px 5px;
  text-transform: uppercase;
}
.xfLab { color: #536471; font-size: 13px; margin-top: 1px; }
.xfText { margin-top: 2px; line-height: 1.35; white-space: pre-wrap; overflow-wrap: anywhere; }
.xfText .xfTag { color: #1d9bf0; }

/* the avatar: .officeAvatar's hue tint, but X's circle */
.xfAvatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  font: 700 15px system-ui, sans-serif;
  overflow: hidden;
}
.xfAvatar img { width: 100%; height: 100%; object-fit: cover; }

/* the quote card and the paper card are the same component: a bordered box
   under the text that stands for a row somewhere else in the city */
.xfCard {
  margin-top: 10px;
  border: 1px solid #cfd9de;
  border-radius: 16px;
  padding: 10px 12px;
  background: #fff;
}
.xfCard:hover { background: #f7f9f9; }
.xfCardWho { display: flex; align-items: baseline; gap: 5px; font-size: 14px; line-height: 1.3; }
.xfCardWho .xfName { font-size: 14px; }
.xfCardText { margin-top: 2px; font-size: 14px; color: #0f1419; line-height: 1.35; }
.xfCardKind { font-size: 12px; font-weight: 700; color: #536471; text-transform: uppercase; letter-spacing: 0.04em; }
a.xfCard { display: block; text-decoration: none; color: inherit; }
a.xfCard .xfCardText { color: #1d9bf0; }

/* the action bar. Nothing here is wired: there are no likes on this board,
   and a row of dead glyphs is what makes it read as X. */
.xfActions { display: flex; gap: 0; margin-top: 8px; color: #536471; font-size: 13px; max-width: 425px; }
.xfAct { flex: 1; display: flex; align-items: center; gap: 6px; }
.xfAct span { font-size: 14px; filter: grayscale(1); opacity: 0.6; }

/* trends: the city's lab tags, which is what this board has instead of
   channels. Clicking one filters the column. */
#xfSide { flex: none; width: 232px; margin-right: auto; padding: 12px 12px 12px 16px; overflow-y: auto; }
.xfSideCard { background: #f7f9f9; border-radius: 16px; padding: 12px 0 4px; }
.xfSideCard h3 { margin: 0 16px 8px; font: 800 19px system-ui, sans-serif; color: #0f1419; }
#xfTrends { list-style: none; margin: 0; padding: 0; }
#xfTrends li { padding: 8px 16px; cursor: pointer; }
#xfTrends li:hover { background: #eff3f4; }
#xfTrends li .xfTrendRank { display: block; font-size: 12px; color: #536471; }
#xfTrends li .xfTrendName { display: block; font-weight: 700; font-size: 14px; }
#xfTrends li .xfTrendN { display: block; font-size: 12px; color: #536471; }
#xfTrends li.on { background: #e8f5fd; box-shadow: inset 3px 0 0 #1d9bf0; }
#xfTrends .none { padding: 4px 16px 12px; color: #536471; font-size: 13px; }
.xfMore {
  padding: 4px 16px 12px 68px;
  color: #1d9bf0;
  font-size: 15px;
  cursor: pointer;
}
.xfMore:hover { background: #f7f9f9; }

/* Demo splash (main.js showDemoSplash): an anonymous visitor on a public
   deployment is told once that this is a frozen copy, not the live city. */
#demoSplash {
  position: fixed; inset: 0; z-index: 5000; display: grid; place-items: center;
  padding: 16px; background: #0f1119cc;
}
#demoSplash .demoCard {
  max-width: 440px; width: 100%; padding: 22px 24px 20px; border-radius: 14px;
  background: #1d1f2b; border: 1px solid #3a3e55; color: #c8cde4;
  font: 400 14px/1.55 system-ui, sans-serif; box-shadow: 0 18px 60px #0008;
}
#demoSplash .demoTag {
  display: inline-block; padding: 2px 9px; border-radius: 999px; background: #ffcf5c; color: #2a2100;
  font: 800 11px system-ui, sans-serif; letter-spacing: 0.12em; text-transform: uppercase;
}
#demoSplash h2 { margin: 12px 0 8px; color: #fff; font: 700 20px/1.25 system-ui, sans-serif; text-wrap: balance; }
#demoSplash p { margin: 0 0 18px; }
#demoSplash button {
  font: 600 13px system-ui, sans-serif; color: #fff; background: #6c7bff; border: 0; border-radius: 999px;
  padding: 7px 16px; cursor: pointer;
}
#demoSplash button:hover { background: #7f8cff; }
#demoSplash button:focus-visible { outline: 2px solid #9aa5ff; outline-offset: 2px; }
