    :root {
      --bg: #0d0d0f; --ink: #ede9df; --muted: #bcb8ae; --jade: #5aaf96; --jade-strong: #8fd0bc; --sand: #d9c8a0;
      /* measured rendered height of #topbar (brand 30px + menu 12.5px content, 15px 24px padding),
         same at desktop and the 700px mobile breakpoint — single source of truth so the bar's
         own height and everything that must clear it (editor, ghost) can never drift apart. */
      --bar-h: 79px;
    }
    [data-theme="light"] { --bg: #f4f1ea; --ink: #1c1c1e; --muted: #5f5c55;
                           --jade: #21694a; --jade-strong: #1c5f45; --sand: #83642a; }
    html, body { margin: 0; background: var(--bg); color: var(--ink); }
    body { font-family: Inter, system-ui, sans-serif; font-size: 15px; line-height: 1.6; }
    #bg-canvas { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 0; }
    /* light mode doesn't dim the canvas — the sketches draw light-native colors (see THEME in machine.js) */
    /* .page only ever wraps #topbar. It must establish its own stacking context (to sit above
       #bg-canvas) but its z-index needs to beat #stage-root's (4, below) — #topbar's own
       z-index:5 is otherwise trapped inside .page's stacking context and can never win against
       a HIGHER z-index sibling of .page itself, no matter what #topbar declares (this was the
       bug: the editor painted over the logo/nav despite #topbar: z-index 5). */
    .page { position: relative; z-index: 5; }
    #topbar { position: fixed; top: 0; left: 0; right: 0; z-index: 5; display: flex;
              justify-content: space-between; align-items: center; padding: 15px 24px;
              min-height: var(--bar-h); box-sizing: border-box;
              background: color-mix(in srgb, var(--bg) 84%, transparent);
              -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
              border-bottom: 1px solid color-mix(in srgb, var(--jade) 14%, transparent); }
    #brand { font-family: 'EB Garamond', Georgia, serif; font-size: 30px; color: var(--ink); text-decoration: none; }
    #brand .slash { color: var(--jade); font-style: italic; font-size: 0.74em; position: relative; top: -0.075em;
                    margin-left: 0.04em; margin-right: 0.05em; }
    #brand .br { color: transparent; font-size: 0.62em; position: relative; top: -0.1em;
                 transition: color 0.28s ease; }
    #brand:hover .br { color: color-mix(in srgb, var(--jade) 42%, transparent); }
    #menu { display: flex; align-items: center; gap: 22px; }
    #menu a { font-family: Inter, system-ui, sans-serif; font-size: 12.5px; font-weight: 500;
              letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); text-decoration: none; }
    #menu a:hover { color: var(--jade); }
    .theme-btn { background: none; border: 1px solid color-mix(in srgb, var(--muted) 40%, transparent);
                 color: var(--muted); border-radius: 99px; padding: 3px 10px; font: 10px Inter, sans-serif; cursor: pointer; }
    .theme-btn svg { display: block; width: 15px; height: 15px; }
    .theme-btn:hover { color: var(--jade); }
    a { color: var(--jade); text-decoration: none; }
    a:hover { text-decoration: underline; }
    ul { list-style: none; padding: 0; margin: 0; }
    button:focus-visible { outline: 2px solid var(--jade); outline-offset: 2px; }
    /* machine ui (built by machine.js) */
    html.intro-pending .page, html.intro-pending #bg-canvas { visibility: hidden; }
    html.intro-pending #pill, html.intro-pending #placard, html.intro-pending #pl-list { visibility: hidden; }
    /* intro-pending hides .page/#topbar entirely (rule above), so #ghost has nothing to clear
       yet — pin it back to the viewport top and keep its own pre-existing intro spacing. */
    html.intro-pending #ghost { top: 0; padding-top: 46px; } /* room for the status caption */
    #stage-root { position: fixed; inset: 0; z-index: 4; pointer-events: none; }
    /* top: var(--bar-h) (not inset: 0) — the ghost's scrollable area itself starts below the
       bar, same fix and same reasoning as #editor-host below (Task 19 QA: editor/ghost content
       must not paint under the topbar even though it's technically "under" it in z-order). */
    #ghost { position: absolute; top: var(--bar-h); right: 0; bottom: 0; left: 0; overflow: auto;
             padding: 18px 20px; scrollbar-width: thin;
             font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px; line-height: 1.55;
             opacity: 0.30; filter: blur(2.5px); pointer-events: none;
             transition: opacity 0.3s ease, filter 0.3s ease; }
    .gline { display: flex; width: fit-content; border-radius: 4px; padding: 0 9px 0 5px; margin: 1px 0;
             white-space: pre; color: color-mix(in srgb, var(--ink) 85%, transparent);
             transition: background 0.3s ease; }
    .gno { min-width: 26px; text-align: right; margin-right: 12px; color: #4a4e55; user-select: none; }
    #gcaret { position: sticky; display: inline-block; width: 7px; height: 12px; background: var(--jade);
              animation: caret-blink 1.1s steps(1) infinite; }
    @keyframes caret-blink { 50% { opacity: 0; } }
    .gline #gcaret { align-self: center; } /* write-head caret sits mid-line during the intro */
    #intro-caption { position: fixed; top: 16px; left: 20px; z-index: 6; pointer-events: none;
                     font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px;
                     color: var(--muted); opacity: 0; transition: opacity 0.4s ease; }
    #intro-caption.on { opacity: 0.8; }
    #pill { position: fixed; bottom: 14px; right: 18px; pointer-events: auto; cursor: pointer;
            font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px; color: var(--muted);
            border: 1px solid color-mix(in srgb, var(--jade) 35%, transparent);
            background: color-mix(in srgb, var(--bg) 72%, transparent); border-radius: 99px; padding: 5px 12px; }
    body.code-focus .page { filter: blur(3px) brightness(0.75); }
    .page { transition: filter 0.3s ease; }
    body.code-focus #ghost { opacity: 1; filter: none; pointer-events: auto; }
    body.code-focus .gline { background: rgba(10,10,12,0.87); }
    [data-theme="light"] body.code-focus .gline { background: color-mix(in srgb, var(--bg) 85%, white 15%); }
    @media (prefers-reduced-motion: reduce) {
      #ghost, .gline { transition: none; }
      #gcaret { animation: none; }
      .page { transition: none; }
      #intro-caption { transition: none; }
      #brand .br { transition: none; }
      #editor-host .cm-line.cm-sketch-focus { transition: none; }
      ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
    }
    /* editorial pagination — bare text, no pill (layout amendment 2026-08-13) */
    #placard { position: fixed; left: 16px; bottom: 14px; pointer-events: auto; display: flex; gap: 6px;
               align-items: baseline; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px;
               color: var(--muted); text-shadow: 0 1px 6px rgba(0,0,0,0.9);
               background: color-mix(in srgb, var(--bg) 84%, transparent);
               -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
               border: 1px solid color-mix(in srgb, var(--jade) 14%, transparent);
               border-radius: 99px; padding: 6px 14px; }
    #placard button { background: none; border: 0; cursor: pointer; font: inherit; padding: 0 2px;
                      text-shadow: inherit; }
    #pl-prev, #pl-next { color: var(--jade-strong); font-size: 13px; }
    #pl-count { color: var(--ink); }
    #pl-name { color: var(--muted); }
    #pl-name:hover { color: var(--jade-strong); }
    [data-theme="light"] #placard { text-shadow: 0 1px 6px rgba(244,241,234,0.85); }
    #pl-list { position: fixed; left: 16px; bottom: 52px; pointer-events: auto; display: none;
               max-height: 60vh; overflow-y: auto; min-width: 240px; padding: 8px 6px;
               background: color-mix(in srgb, var(--bg) 94%, transparent);
               border: 1px solid color-mix(in srgb, var(--jade) 30%, transparent); border-radius: 10px;
               font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px; }
    #pl-list.open { display: block; }
    .pl-group { color: var(--muted); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; padding: 7px 10px 3px; }
    .pl-item { padding: 4px 10px; cursor: pointer; color: var(--muted); border-radius: 6px; }
    .pl-item:hover { background: color-mix(in srgb, var(--jade) 14%, transparent); color: var(--ink); }
    .pl-item.current { color: var(--jade-strong); }
    /* top: var(--bar-h) (not inset: 0) — the editor's own scrollable area starts below the bar,
       so the first code line renders under it rather than through/over the logo and nav (QA fix:
       .page's stacking context was trapping #topbar's z-index, see .page above; this half is the
       companion fix — even with stacking corrected, the editor's content still needs an actual
       top offset so it doesn't merely sit *behind a translucent bar* but starts clear of it). */
    #editor-host { position: absolute; top: var(--bar-h); right: 0; bottom: 0; left: 0; display: none; pointer-events: auto; }
    body.editing #editor-host { display: block; }
    /* editor-host is appended last inside #stage-root, so without this its cm-content
       (full-viewport) paints over — and swallows clicks meant for — the fixed controls below
       (QA fix: pill/reset/share/scope/placard were all unclickable while editing) */
    #pill, #placard, #pl-list, #reset-btn, #share-btn, #scope-btn, #remix-banner { z-index: 2; }
    body.editing #ghost { display: none; }
    #editor-host .cm-editor { height: 100%; background: transparent; font-size: 11.5px; }
    #editor-host .cm-line { background: rgba(10,10,12,0.87); border-radius: 4px; width: fit-content; padding: 0 9px; }
    [data-theme="light"] #editor-host .cm-line { background: color-mix(in srgb, var(--bg) 85%, white 15%); }
    #editor-host .cm-gutters { background: transparent; border: 0; }
    /* Task 18: the beat — a quiet highlight on the sketch region while the editor gathers.
       Specificity/selector must match (or beat) the .cm-line rule above and mix against its
       own base color, not "transparent" — background doesn't layer across cascade rules, so a
       lower-specificity "transparent" mix would either lose outright or, if it won, strip the
       dark plate and leave editor text illegible over a light theme. */
    #editor-host .cm-line.cm-sketch-focus { background: color-mix(in srgb, var(--jade) 7%, rgba(10,10,12,0.87)); transition: background 0.4s ease; }
    [data-theme="light"] #editor-host .cm-line.cm-sketch-focus { background: color-mix(in srgb, var(--jade) 10%, color-mix(in srgb, var(--bg) 85%, white 15%)); }
    #preview-frame { position: fixed; inset: 0; z-index: 1; width: 100vw; height: 100vh; border: 0; background: var(--bg); }
    body.previewing .page, body.previewing #bg-canvas { visibility: hidden; }
    /* remix banner — only for a #s/ shared-view load (body.remixed, set once in boot()), never
       for an in-session editing preview (body.previewing alone gets no banner). Persistent and
       non-dismissible on purpose; the link is a real href (not a click handler) so it still works
       even if something else on the page has broken. */
    #remix-banner { display: none; position: fixed; top: 0; left: 0; right: 0; pointer-events: auto;
                    text-align: center; padding: 10px 16px;
                    font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; color: var(--sand);
                    background: color-mix(in srgb, var(--bg) 92%, transparent);
                    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
                    border-bottom: 1px solid color-mix(in srgb, var(--sand) 35%, transparent); }
    #remix-banner a { color: var(--sand); text-decoration: underline; }
    #remix-banner a:focus-visible { outline: 2px solid var(--jade); outline-offset: 2px; }
    body.remixed #remix-banner { display: block; }
    #reset-btn { position: fixed; bottom: 14px; right: 108px; pointer-events: auto; display: none;
                 font: 11px 'JetBrains Mono', monospace; color: var(--sand); background: none;
                 border: 1px solid color-mix(in srgb, var(--sand) 35%, transparent); border-radius: 99px;
                 padding: 5px 12px; cursor: pointer; }
    body.editing #reset-btn, body.previewing #reset-btn { display: block; }
    #share-btn { position: fixed; bottom: 14px; right: 178px; pointer-events: auto; display: none;
                 font: 11px 'JetBrains Mono', monospace; color: var(--jade); background: none;
                 border: 1px solid color-mix(in srgb, var(--jade) 35%, transparent); border-radius: 99px;
                 padding: 5px 12px; cursor: pointer; }
    body.editing #share-btn { display: block; }
    #scope-btn { position: fixed; bottom: 14px; right: 248px; pointer-events: auto; display: none;
                 font: 11px 'JetBrains Mono', monospace; color: var(--muted); background: none;
                 border: 1px solid color-mix(in srgb, var(--muted) 35%, transparent); border-radius: 99px;
                 padding: 5px 12px; cursor: pointer; }
    body.editing #scope-btn { display: block; }

    /* ---- reading pages (About / Playground) ---- */
    main { max-width: 640px; margin: 0 auto; padding: 92px 24px 12vh; }
    h1 { font-family: Newsreader, Georgia, serif; font-style: italic; font-weight: 500; font-size: 38px; margin: 0; }
    h2 { font-family: Newsreader, Georgia, serif; font-style: italic; font-weight: 400; font-size: 21px; color: var(--jade); margin: 40px 0 12px; }
    .co-head { display: flex; justify-content: space-between; margin-top: 18px; }
    .co-name { font-weight: 500; }
    .co-years { color: var(--muted); font-size: 13px; }
    .products li { color: var(--muted); padding: 2px 0 2px 14px; }
    .product-type { font-size: 11px; color: var(--jade); border: 1px solid color-mix(in srgb, var(--jade) 40%, transparent); border-radius: 4px; padding: 0 6px; margin-left: 8px; }
    .entry-list li { display: flex; gap: 14px; padding: 4px 0; }
    .entry-list .date { color: var(--muted); font-size: 13px; min-width: 64px; }
    .entry-list .kind { color: var(--muted); font-size: 12px; margin-left: auto; }
    .contact-line { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 13px; }
    h1 + .contact-line { margin-top: 6px; }
    .sep { color: var(--muted); padding: 0 8px; }
    blockquote { margin: 14px 0; padding: 2px 0 2px 16px; border-left: 2px solid color-mix(in srgb, var(--jade) 40%, transparent); color: var(--muted); }
    blockquote p { margin: 0; }
    blockquote cite { display: block; margin-top: 6px; font-size: 13px; font-style: normal; }
    #menu a[aria-current] { color: var(--ink); }

    /* mobile — kept last so its overrides win the cascade */
    @media (max-width: 700px) {
      #ghost { display: none; }
      body.editing #ghost { display: none; }
      #editor-host { background: var(--bg); }
      #placard { font-size: 11px; }
      #pl-list { max-height: 50vh; }
      /* QA fix (item 8): placard (left) and reset/share/scope (right:108-248px) collide into
         jumbled text once the editor opens on a narrow phone — pagination is meaningless
         mid-edit there anyway, so hide placard + its list instead of trying to fit both rows. */
      body.editing #placard, body.editing #pl-list { display: none; }
      /* Mobile control cluster fix: reduce offsets and padding/font so all four controls fit on one row */
      #reset-btn { right: 96px; }
      #share-btn { right: 158px; }
      #scope-btn { right: 218px; }
      #reset-btn, #share-btn, #scope-btn, #pill { padding: 4px 9px; font-size: 10px; }
    }
