  /* Google Sans — the app's own font, everywhere (not just the structure
     view, which used to be the only place it loaded). Variable font, one
     file per style, weights 100–900 in that one file each. */
  @font-face{font-family:"Google Sans";src:url("/fonts/google-sans/GoogleSans-Variable.ttf") format("truetype");
       font-weight:100 900;font-style:normal;font-display:swap}
  @font-face{font-family:"Google Sans";src:url("/fonts/google-sans/GoogleSans-Italic-Variable.ttf") format("truetype");
       font-weight:100 900;font-style:italic;font-display:swap}
  :root{
    --paper:#f7f8fa; --card:#ffffff; --ink:#102e4a; --ink-2:#3a526b; --ink-3:#6b7f96;
    --line:#e4e8ee; --line-2:#eef1f5;
    --accent:#004ba8; --accent-soft:#dce9fb;
    --gold:#d4a418; --gold-soft:#fdf3c8;
    --warn:#b0421a; --warn-soft:#fbe4dc;
    --grey:#9aa8b8; --grey-soft:#eef1f5;
    --r:10px;
    --sans:"Google Sans",ui-sans-serif,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    --mono:ui-monospace,SFMono-Regular,Menlo,monospace;
  }
  *{box-sizing:border-box}
  html{-webkit-text-size-adjust:100%}
  body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);
       font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
  .page{max-width:1180px;margin:0 auto;padding:44px 28px 92px}
  @media(max-width:620px){.page{padding:32px 16px 60px}h1{font-size:24px}}

  /* ── header ─────────────────────────────────────────── */
  header{margin-bottom:40px}
  .eyebrow{font-size:12px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}
  h1{font-size:32px;line-height:1.15;letter-spacing:-.02em;margin:12px 0 12px;font-weight:700}
  .standfirst{max-width:62ch;color:var(--ink-2);margin:0 0 20px}
  .meta-row{display:flex;flex-wrap:wrap;gap:8px}
  .chip{display:inline-flex;align-items:center;gap:8px;background:var(--card);border:1px solid var(--line);
        border-radius:100px;padding:4px 12px;font-size:12px;color:var(--ink-2)}
  .chip b{color:var(--ink);font-weight:650}
  .dot{width:8px;height:8px;border-radius:50%;flex:none}
  /* Neutral nav button — a plain outlined button, no accent fill, for links
     that move between pages (dashboard → structure, read view → structure)
     rather than performing an action. */
  .btn-neutral{display:inline-flex;align-items:center;gap:8px;appearance:none;border:1px solid var(--line);
       border-radius:8px;background:var(--card);color:var(--ink);font-family:var(--sans);font-size:12px;
       font-weight:650;padding:8px 16px;cursor:pointer;text-decoration:none;white-space:nowrap}
  .btn-neutral:hover{border-color:var(--accent);color:var(--accent)}
  .d-ok{background:var(--accent)} .d-flag{background:var(--gold)} .d-none{background:var(--warn)} .d-grey{background:var(--grey)}

  /* ── sections ───────────────────────────────────────── */
  section{margin-top:44px}
  .sec-label{font-size:12px;font-weight:650;color:var(--ink-2);margin:0 0 12px}
  .sec-note{font-size:12px;color:var(--ink-3);max-width:74ch;margin:-8px 0 16px}

  .grid{display:grid;gap:16px}
  .g2{grid-template-columns:repeat(2,1fr)}
  .g3{grid-template-columns:repeat(3,1fr)}
  .g4{grid-template-columns:repeat(4,1fr)}
  @media(max-width:960px){.g4{grid-template-columns:repeat(2,1fr)}.g3{grid-template-columns:1fr}}
  @media(max-width:620px){.g4,.g2{grid-template-columns:1fr}}

  .card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:16px 20px}
  .card h3{font-size:16px;margin:0 0 12px;font-weight:650;letter-spacing:-.005em}
  .card p{margin:0;font-size:14px;color:var(--ink-2);line-height:1.6}
  .card .k{font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin:0 0 8px}

  /* stat tile */
  .stat .bar{height:4px;border-radius:4px;background:var(--accent);margin:0 0 12px}
  .stat .bar.gold{background:var(--gold)} .stat .bar.warn{background:var(--warn)} .stat .bar.grey{background:var(--grey)}
  .stat .num{font-size:28px;font-weight:700;letter-spacing:-.02em;line-height:1.05}
  .stat .num small{font-size:16px;font-weight:600;color:var(--ink-3);letter-spacing:0}
  .stat .cap{font-size:12px;color:var(--ink-3);margin-top:4px}

  /* pipeline */
  .pipe{display:flex;gap:8px;flex-wrap:wrap}
  .step{flex:1 1 96px;background:var(--card);border:1px solid var(--line);border-radius:8px;padding:12px 12px;min-width:96px}
  .step .id{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--ink-3)}
  .step .nm{font-size:12px;font-weight:600;margin-top:4px;line-height:1.3}
  .step .st{font-size:12px;margin-top:8px;display:inline-flex;align-items:center;gap:4px;color:var(--ink-3)}
  .step.done{border-color:#c9dcf5;background:linear-gradient(0deg,#f6faff,#fff)}
  .step.skip{opacity:.62}

  /* phrase table */
  .tw{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:var(--r)}
  table{width:100%;min-width:560px;border-collapse:collapse;background:var(--card);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
  th,td{text-align:left;padding:12px 16px;font-size:12px;vertical-align:top;border-bottom:1px solid var(--line-2)}
  th{font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);background:#fbfcfd}
  tbody tr:last-child td{border-bottom:0}
  td.q{color:var(--ink);font-weight:550}
  td.n{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--ink-2)}
  .count{display:inline-flex;align-items:center;gap:8px}
  .pips{display:inline-flex;gap:4px}
  .pip{width:8px;height:16px;border-radius:4px;background:var(--line)}
  .pip.on{background:var(--accent)}
  tr.hot td{background:#fffaf7}
  tr.hot .pip.on{background:var(--warn)}

  /* sticky client column — comparison matrices, P28. Not part of the P06
     original (the matrices themselves are new); extends this stylesheet
     rather than forking a second one. Fixed width on the label column so
     the You column's left offset is a constant, not a measurement.

     table's own overflow:hidden (above, for rounded corners) clips
     position:sticky on any cell inside it — the sticky cell ends up
     scrolling with the table's own box instead of holding against the
     .tw viewport. .matrix-table opts the two comparison matrices out of
     that clip; they trade a hard-clipped corner for a working sticky
     column, which every other table here doesn't need. */
  table.matrix-table{overflow:visible}
  .matrix-label{position:sticky;left:0;width:200px;min-width:200px;max-width:200px;background:var(--card);z-index:2}
  /* P29: a third pinned column (You, edited) can follow You, so You now also
     needs a fixed width — its own left offset was already a constant, but
     matrix-you-edited's left offset needs You's width to be one too. */
  .matrix-you{position:sticky;left:200px;width:140px;min-width:140px;max-width:140px;background:var(--card);z-index:2}
  .matrix-you-edited{position:sticky;left:340px;width:140px;min-width:140px;max-width:140px;background:var(--card);z-index:2}
  /* Marks whichever pinned column is currently last (You when there's no
     edited copy, You-edited when there is) — the frozen edge is a property
     of "last pinned," not of a specific column, so it's a separate class
     applied dynamically rather than baked into .matrix-you. */
  .matrix-frozen-edge{box-shadow:2px 0 0 0 var(--line)}
  thead .matrix-label,thead .matrix-you,thead .matrix-you-edited{background:#fbfcfd;z-index:3}
  /* Three pinned columns leave little room to scroll on a narrow screen —
     unpin You-edited rather than pin more than the screen can hold. Matches
     the P06 CSS's own mobile breakpoint. */
  @media(max-width:620px){
    .matrix-you-edited{position:static;left:auto;width:auto;min-width:0;max-width:none;box-shadow:none;background:var(--card)}
    /* You-edited just unpinned, so You is the last pinned column again —
       give it back the frozen edge it would have if edited copy didn't exist. */
    .matrix-you{box-shadow:2px 0 0 0 var(--line)}
  }

  /* tags */
  .tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
  .tag{font-size:12px;font-weight:650;padding:4px 8px;border-radius:4px;background:var(--accent-soft);color:#0a3f83}
  .tag.gold{background:var(--gold-soft);color:#7a5c05}
  .tag.warn{background:var(--warn-soft);color:#8a3011}
  .tag.grey{background:var(--grey-soft);color:var(--ink-2)}

  /* insight cards — the rule above .insight-action is what separates what
     is true (the card's text) from what to do about it (the action). */
  .insight-action{margin-top:12px;padding-top:12px;border-top:1px solid var(--line);
    font-size:13px;color:var(--ink-2)}
  .insight-action b{color:var(--ink);font-weight:650}
  .insight-sources{display:flex;flex-wrap:wrap;gap:12px;margin-top:10px;font-size:12px}
  .insight-sources a{color:var(--accent);text-decoration:none;border-bottom:1px solid transparent}
  .insight-sources a:hover{border-bottom-color:var(--accent)}
  .insight-none{color:var(--ink-3);font-style:italic}

  /* empty state */
  .empty{background:var(--card);border:1px dashed #d9c6bd;border-radius:var(--r);padding:24px}
  .empty h3{margin:0 0 8px;font-size:16px}
  .empty .lede{color:var(--ink-2);font-size:16px;max-width:70ch;margin:0 0 16px}
  .tried{display:grid;gap:8px;margin:0;padding:0;list-style:none}
  .tried li{display:grid;grid-template-columns:112px 1fr;gap:12px;font-size:12px;padding:8px 0;border-top:1px solid var(--line-2)}
  @media(max-width:620px){.tried li{grid-template-columns:1fr;gap:4px}}
  .tried b{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--warn)}

  /* term blocks */
  .term{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:16px 16px}
  .term .w{font-size:16px;font-weight:700;letter-spacing:-.01em}
  .term .row{display:grid;grid-template-columns:88px 1fr;gap:12px;margin-top:8px;font-size:12px;line-height:1.55}
  @media(max-width:620px){.term .row{grid-template-columns:1fr;gap:4px}}
  .term .row span:first-child{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);padding-top:4px}
  .gapbar{height:4px;border-radius:4px;margin-top:12px;background:linear-gradient(90deg,var(--accent) 0 50%,var(--warn) 50% 100%)}

  /* quote */
  .quote{background:var(--card);border:1px solid var(--line);border-left:2px solid var(--accent);
         border-radius:0 var(--r) var(--r) 0;padding:16px 20px}
  .quote p{margin:0;font-size:16px;line-height:1.6;color:var(--ink)}
  .quote .src{margin-top:8px;font-size:12px;color:var(--ink-3)}

  /* fact list */
  .facts{display:grid;gap:0;background:var(--card);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
  @media(max-width:620px){.fact{grid-template-columns:1fr !important;gap:8px}}
  .fact{display:grid;grid-template-columns:1fr auto;gap:16px;padding:12px 16px;border-bottom:1px solid var(--line-2);align-items:baseline}
  .fact:last-child{border-bottom:0}
  .fact .l{font-size:16px}
  .fact .l em{font-style:normal;color:var(--ink-3);font-size:12px;display:block;margin-top:4px}
  .fact .v{font-size:12px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--accent);white-space:nowrap}
  .fact .v.gold{color:var(--gold)} .fact .v.warn{color:var(--warn)}


  /* tldr */
  .tldr{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:20px 24px;margin-top:28px}
  .tldr .hd{font-size:12px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:16px}
  .tldr ol{margin:0;padding:0;list-style:none;counter-reset:t}
  .tldr li{counter-increment:t;display:grid;grid-template-columns:28px 1fr;gap:16px;padding:12px 0;border-top:1px solid var(--line-2);align-items:baseline}
  .tldr li:first-of-type{border-top:0;padding-top:0}
  .tldr li::before{content:counter(t);font-family:var(--mono);font-size:12px;font-weight:700;color:var(--ink-3)}
  .tldr p{margin:0;font-size:16px;line-height:1.55;color:var(--ink-2)}
  .tldr b{color:var(--ink);font-weight:650}
  .tldr .lastline{margin-top:16px;padding-top:16px;border-top:1px solid var(--line);font-size:12px;color:var(--ink-3)}

  /* structure map */
  .smap{display:grid;grid-template-columns:120px 1fr;gap:12px 16px;align-items:center}
  @media(max-width:620px){.smap{grid-template-columns:1fr;gap:4px 0}.smap .who{margin-top:12px}}
  .smap .who{font-size:12px;font-weight:650;color:var(--ink-2)}
  .smap .who em{display:block;font-style:normal;font-size:12px;color:var(--ink-3);font-weight:500}
  .rail{display:flex;gap:4px;height:28px}
  .rail i{flex:1;border-radius:4px;background:var(--line-2)}
  .rail i.proof{background:var(--accent)}
  .rail i.ask{background:var(--gold)}
  .rail i.app{background:var(--warn)}
  .legend{display:flex;flex-wrap:wrap;gap:16px;margin-top:12px;font-size:12px;color:var(--ink-3)}
  .legend span{display:inline-flex;align-items:center;gap:8px}
  .sw{width:12px;height:12px;border-radius:4px;flex:none}

  /* two-panel compare */
  .cmp{display:grid;grid-template-columns:1fr 1fr;gap:16px}
  @media(max-width:760px){.cmp{grid-template-columns:1fr}}
  .panel{background:var(--card);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
  .panel .hd{padding:8px 16px;font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
             border-bottom:1px solid var(--line-2);color:var(--ink-3);background:#fbfcfd}
  .panel .bd{padding:16px 16px;font-size:12px;color:var(--ink-2);line-height:1.6}
  .panel.dim .bd{font-family:var(--mono);font-size:12px;color:var(--ink-3);white-space:pre-wrap}
  .panel .bd b{color:var(--ink)}

  /* timeline */
  .tl{display:flex;align-items:flex-end;gap:4px;height:76px;margin-top:8px}
  .tl div{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;gap:4px}
  .tl b{display:block;width:100%;background:var(--accent);border-radius:4px 4px 0 0;min-height:4px}
  .tl b.art{background:var(--gold)}
  .tl span{font-size:8px;color:var(--ink-3);letter-spacing:.02em}

  /* path map */
  .paths{display:grid;gap:8px}
  .path{display:grid;grid-template-columns:36px 1fr auto;gap:12px;align-items:center;background:var(--card);
        border:1px solid var(--line);border-radius:8px;padding:12px 16px}
  @media(max-width:620px){.path{grid-template-columns:28px 1fr;gap:8px}.path .end{grid-column:2}}
  .path .no{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--ink-3)}
  .path .what{font-size:12px}
  .path .what em{font-style:normal;display:block;font-size:12px;color:var(--ink-3);margin-top:4px}
  .path .end{font-size:12px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--warn);white-space:nowrap}
  .path .end.ok{color:var(--accent)}

  footer{margin-top:56px;padding-top:20px;border-top:1px solid var(--line);font-size:12px;color:var(--ink-3);
         display:flex;flex-wrap:wrap;gap:16px;justify-content:space-between}

  /* how we know — collapsed by default, no JS. .working-body has no
     inline style, so if this stylesheet fails to load it stays a plain
     <div> (block, visible) — the region fails open, same guarantee the
     see-more pattern already relies on for its own extra content. */
  .working{border-top:1px solid var(--line);margin-top:44px;padding-top:28px}
  .working-body{display:none}
  .working-toggle:checked ~ .working-body{display:block}
  .working-toggle:checked ~ .see-more-label{display:none}
  .working-toggle:checked ~ .see-more-label-less{display:inline-block}

  /* see more / see less — CSS-only, no JS (this app runs none beyond the
     native hover titles and the rerun form POST). A checkbox drives it,
     always placed as a sibling of whatever it reveals — three shapes:
       1. a table's extra rows: can't sit beside a checkbox (tables don't
          allow it), so they're a second <tbody>, reached through the .tw
          wrapper the checkbox is actually beside.
       2. extra items inside one card (e.g. one Questions "who" list): the
          checkbox sits in that same card, directly beside its own items.
       3. extra cards in a grid (e.g. Assumptions): never wrapped — wrapping
          would break the grid — so the checkbox sits beside the .grid
          itself and reaches its extra children by descendant. */
  /* .page prefix bumps specificity (0,2,0) past content rules like
     .tldr li{display:grid} (0,1,1) that would otherwise win and leave an
     "extra" item visible before its checkbox is ever checked. */
  .page .see-more-extra-rows{display:none}
  .page .see-more-extra{display:none}
  .see-more-toggle:checked ~ .tw .see-more-extra-rows{display:table-row-group}
  .see-more-toggle:checked ~ .see-more-extra{display:block}
  .see-more-toggle:checked ~ .grid .see-more-extra{display:block}
  /* li needs display:list-item (not block) to keep its marker/numbering. */
  .see-more-toggle:checked ~ ol .see-more-extra,
  .see-more-toggle:checked ~ ul .see-more-extra{display:list-item}
  .see-more-label,.see-more-label-less{cursor:pointer;display:inline-block;margin-top:12px;
       color:var(--accent);font-size:12px;font-weight:650}
  .see-more-label-less{display:none}
  .see-more-toggle:checked ~ .see-more-label{display:none}
  .see-more-toggle:checked ~ .see-more-label-less{display:inline-block}

  /* structure view — P31/P32. Read-only-by-default columns, each a stack of
     cards grouped into dashed zone containers. New UI, not part of the P06
     original, so it gets its own rules rather than stretching existing ones.

     Section 3's visual language (grey scale + single blue accent, cards
     with shadow not border) is scoped entirely to .structure-page by
     overriding the shared tokens at that one ancestor — nothing outside
     this view changes. Google Sans itself is no longer part of that
     scoping (see the base :root above — it's the whole app's font now);
     only the grey/blue token values below are still local to this view.
     Values are the owner's own reference (Pulse's boilerplate tokens.css:
     --color-blue-reference #2F4DA1, the tinted neutral-900/600/400 scale,
     the oklab shadow formula) transcribed, not reinvented; the elaborate
     multi-theme color-mix machinery around them was not ported — this
     view only ever needs the one theme. */
  .structure-page{
    --neutral-tint:#2F4DA1;
    --accent:#2F4DA1; --accent-dark:#152356;
    --accent-soft:color-mix(in oklab, var(--accent) 14%, white);
    --ink:color-mix(in oklab, var(--neutral-tint) 12%, #1a1d23);
    --ink-2:color-mix(in oklab, var(--neutral-tint) 10%, #5b626e);
    --ink-3:color-mix(in oklab, var(--neutral-tint) 8%, #868d99);
    --line:color-mix(in oklab, var(--neutral-tint) 14%, transparent);
    --grey-soft:color-mix(in oklab, var(--neutral-tint) 6%, #f4f4f2);
    --zone-bg:color-mix(in oklab, var(--neutral-tint) 3%, #fbfbfb);
    --card:#ffffff;
    --shadow-tint:color-mix(in oklab, var(--accent) 20%, #7f8b99);
    --shadow-card:0 8px 20px -6px color-mix(in oklab, var(--shadow-tint) 16%, transparent);
    /* "Banana cream" — Sandbox Hour Build 5's own token, reused here for
       this view's empty-state boxes only. */
    --banana:#f7f06d;
  }
  /* Page stretches with the viewport instead of the shared 1180px cap —
     four columns need the room. */
  .structure-page{max-width:none}
  /* Heads (label + selector row) and card lists are emitted as two
     separate runs of siblings (all four heads, then all four lists), so
     CSS Grid's own row-major auto-placement puts every head in row 1 and
     every list in row 2 — row 1's height becomes the tallest head
     automatically, no JS measurement needed for the columns to line up. */
  .structure-columns{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:auto;gap:12px 20px;margin-top:28px;align-items:start}
  @media(max-width:1200px){.structure-columns{grid-template-columns:repeat(2,1fr)}}
  @media(max-width:640px){.structure-columns{grid-template-columns:1fr}}
  .structure-column-head,.structure-column-body{min-width:0}
  .structure-column-head-top{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:12px}
  .structure-column-head-top .sec-label{margin:0}
  .structure-selector-buttons{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px}
  .structure-selector-btn{appearance:none;border:1px solid var(--line);border-radius:8px;background:var(--card);
       color:var(--ink-2);font-family:var(--sans);font-size:12px;font-weight:600;padding:8px 12px;
       cursor:pointer;text-decoration:none;line-height:1.3}
  .structure-selector-btn.is-active{background:var(--accent);border-color:var(--accent);color:#fff}
  /* Consecutive same-zone cards sit inside one dashed container; a zone
     that reappears later opens a second one. Sections with no known zone
     get no container — they're bare cards in .structure-list, same gap. */
  .structure-list{display:flex;flex-direction:column;gap:16px}
  .structure-zone{display:flex;flex-direction:column;gap:12px;border:1px dashed var(--line);
       background:var(--zone-bg);border-radius:var(--r);padding:16px}
  .structure-zone-label{align-self:flex-start;font-size:12px;font-weight:700;letter-spacing:.06em;
       text-transform:uppercase;color:var(--ink-3)}
  /* A playbook's own zone-budget card (P36 §2/§3) — the budget header is
     the primary frame; the scenes that occupy it nest inside as secondary
     detail, visually subordinate (dashed, tinted) but still their own real
     cards underneath, so they stay draggable. */
  .structure-playbook-zone-card{display:flex;flex-direction:column;gap:12px;border:1px dashed var(--line);
       background:var(--zone-bg);border-radius:var(--r);padding:16px}
  .structure-playbook-zone-scenes{display:flex;flex-direction:column;gap:12px}
  .structure-playbook-zone-scenes:empty{display:none}
  /* Cards: shadow, no border — overrides the shared .card rule, scoped to
     this page only (two-class selector beats the base .card rule's one). */
  .structure-page .card{border:0;box-shadow:var(--shadow-card)}
  /* Empty-state boxes ("No competitors mapped yet.", etc.) — light yellow,
     banana cream, scoped to this page only. */
  .structure-page .empty{background:color-mix(in oklab, var(--banana) 20%, white);
       border:1px dashed color-mix(in oklab, var(--banana) 65%, var(--ink-3))}
  /* Gap cards — render-time-only suggestions (P36 §3), never written into
     the version file. Same banana annotation language as .empty above, so
     it reads as "the app noticing something," not an alarm. Selector
     prefixed with .structure-page, same as .card/.empty just above — a
     bare .structure-gap-card loses to ".structure-page .card{border:0}"
     on specificity regardless of source order, which silently dropped the
     dashed border (caught live, in a throwaway-server visual check). */
  .structure-page .structure-gap-card{background:color-mix(in oklab, var(--banana) 20%, white);
       border:1px dashed color-mix(in oklab, var(--banana) 65%, var(--ink-3));cursor:pointer}
  .structure-gap-card .structure-card-lead{color:var(--ink-2);font-style:italic}
  .structure-page .structure-gap-card:hover{background:color-mix(in oklab, var(--banana) 32%, white)}
  /* A gap card's click-to-scroll target in column 1, briefly. */
  .structure-zone-highlight{outline:2px solid color-mix(in oklab, var(--banana) 70%, var(--ink-3));
       outline-offset:2px}
  .structure-card{padding:16px}
  /* Card header — a tag row: zone, type, position (only where the source
     has one). Replaces the old bold name/description pair; the type name
     that used to be a separate line is now one of these tags. */
  .structure-tag-row{display:flex;flex-wrap:wrap;gap:8px}
  .structure-tag{display:inline-flex;align-items:center;font-size:12px;font-weight:650;
       letter-spacing:.02em;padding:4px 8px;border-radius:8px;background:var(--grey-soft);color:var(--ink-2)}
  /* The position tag — same darker-background treatment as the read
     view's own number tag, so a card's "which one" reads a shade heavier
     than its zone/type siblings there too. */
  .structure-tag-number{background:color-mix(in oklab, var(--ink-3) 30%, var(--grey-soft))}
  /* The segment tag (P36 §4) — outline, not filled, so it reads as "seen
     through this lens" rather than as part of the card's own identity like
     the zone/type/position tags. Same component, scaled by treatment. */
  .structure-tag-segment{background:transparent;border:1px solid var(--line);color:var(--ink-2)}
  /* A script comparison's column-1 cards — a hybrid's unordered tail,
     named under the ordered beat it attaches to; a checklist's own muted
     coverage disclaimer. */
  .structure-segment-attached{margin:8px 0 0;font-size:12px;color:var(--ink-3)}
  .structure-checklist-note{margin:12px 0 0;font-size:12px;color:var(--ink-3);font-style:italic}
  /* Card body — only when the section has captured content; a section
     without it renders the tag row alone, no empty placeholder lines. */
  .structure-card-body{display:flex;flex-direction:column;gap:12px;margin-top:12px}
  .structure-card-title{margin:0;font-size:16px;font-weight:650;color:var(--ink)}
  .structure-card-lead{margin:0;font-size:12px;color:var(--ink-3);line-height:1.5}
  .structure-cta-row{display:flex;flex-wrap:wrap;gap:8px}
  .structure-tag-cta{background:var(--accent-soft);color:var(--accent-dark);font-weight:700}
  /* Image-break cards (no real type, no text — a pure photo slot) — a
     small mountains-and-sun glyph stands in for the missing photo, and the
     card gets extra vertical room so it doesn't look cramped around it. */
  .structure-card-image-break{padding-top:24px;padding-bottom:24px}
  .structure-card-image-break .structure-card-body{align-items:center;text-align:center}
  .structure-image-icon{width:20px;height:12px;color:color-mix(in oklab, var(--ink-3) 55%, white)}
  .structure-image-icon circle,.structure-image-icon path{fill:currentColor}
  /* Merged-competitors cards only — one line per contributing competitor's
     own transcribed content, under the card's tag row. */
  .structure-competitor-matches{display:flex;flex-direction:column;gap:12px;margin-top:12px;
       padding-top:12px;border-top:1px dashed var(--line)}
  .structure-competitor-match{margin:0;font-size:12px;color:var(--ink-2);line-height:1.5}
  /* A dashed divider between different competitors' entries, same style as
     the border separating this whole block from the tag row above it. */
  .structure-competitor-match + .structure-competitor-match{padding-top:12px;border-top:1px dashed var(--line)}
  .structure-competitor-name{font-weight:650;color:var(--ink)}
  .structure-draggable{cursor:grab}
  .structure-drop-target{outline:2px dashed var(--accent);outline-offset:2px}
  /* Drag handle — three light horizontal dashes, kept as a class for
     later; not rendered on any card today (see dragHandle() in
     views/structure.js). A hovered draggable card nudges itself instead
     — see the animation below. */
  .structure-card-row{display:flex;gap:12px;align-items:center}
  .structure-card-main{flex:1;min-width:0}
  .structure-drag-handle{position:relative;flex:none;width:12px;height:12px}
  .structure-drag-handle::before{content:"";position:absolute;left:0;top:4px;width:12px;height:4px;
       border-radius:4px;background:color-mix(in oklab, var(--ink-3) 55%, white);
       box-shadow:0 3.5px 0 color-mix(in oklab, var(--ink-3) 55%, white), 0 7px 0 color-mix(in oklab, var(--ink-3) 55%, white)}
  /* Hovering a draggable card a moment nudges it side to side once, as a
     "you can pick this up" cue that replaced the static handle icon.
     animation-delay holds it still for the first beat of the hover so a
     mouse just passing over doesn't twitch every card in its path; moving
     off before the delay elapses cancels it outright, since the
     :hover rule simply stops matching. */
  @keyframes structure-drag-nudge{0%,100%{transform:translateX(0)}25%{transform:translateX(-3px)}75%{transform:translateX(3px)}}
  .structure-draggable:hover,.structure-b-card:hover{animation:structure-drag-nudge 600ms ease-in-out 1;animation-delay:550ms}
  /* Delete (column 2 only) — top-right corner; opens the confirm modal
     below rather than removing on click. */
  .structure-b-card{position:relative;padding:16px 40px 16px 16px;cursor:grab}
  .structure-delete{position:absolute;right:12px;top:12px;
       width:20px;height:20px;display:flex;align-items:center;justify-content:center;
       border:0;background:transparent;color:var(--ink-3);font-size:16px;line-height:1;
       cursor:pointer;border-radius:4px}
  .structure-delete::before{content:"×"}
  .structure-delete:hover{background:var(--grey-soft);color:var(--warn)}
  /* Drop indicator — tracks the computed drop index live while dragging
     over column 2, so the user can see exactly where the card will land. */
  .structure-drop-indicator{height:4px;border-radius:4px;background:var(--accent);
       box-shadow:0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
       animation:structure-drop-pulse 1s ease-in-out infinite}
  @keyframes structure-drop-pulse{0%,100%{opacity:.5}50%{opacity:1}}
  /* The New column head's comparison-notes block (the notes-move fix) —
     lives under the selector row, above the first zone container. Nothing
     in the card flow interrupts the stack any more; this is the one place
     the comparison speaks in text. */
  .structure-comparison-notes{margin-top:12px;padding:12px 16px;border:1px dashed var(--line);
       border-radius:var(--r);background:var(--grey-soft)}
  .structure-comparison-notes-header{margin:0 0 4px;font-size:12px;font-weight:700;color:var(--ink-2)}
  .structure-comparison-notes-list{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px}
  .structure-comparison-notes-list li{margin:0;font-size:12px;color:var(--ink-3);padding-left:12px;position:relative}
  .structure-comparison-notes-list li::before{content:"·";position:absolute;left:0}
  .structure-modal{position:fixed;inset:0;background:rgba(20,24,32,.45);display:flex;
       align-items:center;justify-content:center;z-index:1000;padding:20px}
  .structure-modal[hidden]{display:none}
  .structure-modal-card{background:var(--card);border-radius:var(--r);padding:24px;max-width:360px;
       box-shadow:0 20px 55px rgba(0,0,0,.24);font-family:var(--sans)}
  .structure-modal-warning{margin:0 0 20px;font-size:16px;color:var(--ink);line-height:1.5}
  .structure-modal-actions{display:flex;gap:8px;justify-content:flex-end}
  .structure-modal-cancel,.structure-modal-confirm{padding:8px 16px;border-radius:8px;font-size:12px;
       font-weight:650;cursor:pointer;border:1px solid var(--line);font-family:var(--sans)}
  .structure-modal-confirm{background:var(--warn);border-color:var(--warn);color:#fff}
  .structure-modal-cancel{background:var(--card);color:var(--ink-2)}

  /* Read view — a wide prose column, the app's own typography, plus a
     sticky sidebar to the right for whatever this source's facts/note are
     (see .read-sidebar below). Toggling Edit (see .read-edit-toggle, a
     real switch) turns every field in the page into a bordered input at
     once — label above, placeholder guidance when empty — not a per-field
     click-to-edit step. */
  .read-page{max-width:1400px;margin:0 auto;padding:44px 28px 92px}
  .read-layout{display:flex;align-items:flex-start;gap:40px}
  /* Same dashed-container language as a zone container on the structure
     page (.structure-zone) — a loose dotted-bordered tray, not a solid
     card; the individual sections inside are the actual cards (white,
     shadowed — see .read-section below). --grey-soft here is the base
     scope's own token (the read view isn't inside .structure-page, which
     redefines it to a much fainter near-white — this one's meant to read
     as visibly grey, same as it does everywhere else in the base app). */
  .read-main{flex:1 1 auto;min-width:0;border:1px dashed var(--line);
       background:var(--grey-soft);border-radius:var(--r);padding:48px 56px}
  .read-back{margin-bottom:20px}
  .read-header{max-width:76ch;margin:0 0 32px}
  .read-header h1{font-size:20px;margin:12px 0 12px;line-height:1.25}
  .read-fidelity{font-size:12px;color:var(--gold);margin-left:10px}
  .read-toolbar{max-width:76ch;margin:0 0 32px;display:flex;align-items:center;justify-content:flex-end;gap:16px}
  /* A real toggle switch, top-right of the page. The checkbox sits inside
     the label (visually hidden, not display:none, so it stays keyboard/
     screen-reader reachable) — a click anywhere in the label already
     toggles it; the track/thumb below just render its checked state. */
  .read-edit-toggle{display:inline-flex;align-items:center;gap:12px;font-size:16px;font-weight:650;
       color:var(--ink-2);cursor:pointer;user-select:none}
  .read-edit-toggle-input{position:absolute;width:4px;height:4px;padding:0;margin:-4px;overflow:hidden;
       clip:rect(0,0,0,0);white-space:nowrap;border:0}
  .read-edit-toggle-track{position:relative;flex:none;width:48px;height:28px;border-radius:100px;
       background:var(--line);transition:background 150ms ease}
  .read-edit-toggle-thumb{position:absolute;top:4px;left:4px;width:20px;height:20px;border-radius:50%;
       background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform 150ms ease}
  .read-edit-toggle-input:checked ~ .read-edit-toggle-track{background:var(--accent)}
  .read-edit-toggle-input:checked ~ .read-edit-toggle-track .read-edit-toggle-thumb{transform:translateX(20px)}
  .read-edit-toggle-input:focus-visible ~ .read-edit-toggle-track{outline:2px solid var(--accent);outline-offset:2px}
  .read-save-btn{padding:8px 16px;border-radius:8px;font-size:12px;font-weight:650;cursor:pointer;
       border:1px solid var(--accent);background:var(--accent);color:#fff}
  .read-save-sticky{position:fixed;right:24px;bottom:24px;padding:12px 24px;border-radius:100px;
       font-size:16px;font-weight:650;cursor:pointer;border:1px solid var(--accent);background:var(--accent);
       color:#fff;box-shadow:0 8px 24px rgba(0,0,0,.22);z-index:500}
  /* Each section is its own white card, shadowed — sitting inside the
     dashed .read-main tray, same relationship a .card has to a
     .structure-zone container on the structure page. The zone/type/number
     tag row sits at the top, always visible, once per card (not repeated
     per field, which is how it worked before). */
  .read-section{background:var(--card);box-shadow:0 4px 14px -4px rgba(16,46,74,.12);
       border-radius:0;padding:24px 28px;margin-top:0;margin-bottom:4px}
  .read-section:last-child{margin-bottom:0}
  /* Only the outer corners of the whole stack round — the first card's
     top, the last card's bottom — so the run of cards reads as one
     rounded shape with seams, not a pile of separately-rounded boxes. */
  .read-section:first-child{border-top-left-radius:var(--r);border-top-right-radius:var(--r)}
  .read-section:last-child{border-bottom-left-radius:var(--r);border-bottom-right-radius:var(--r)}
  .read-section-tags{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px}
  .read-section-tags .structure-tag{font-size:12px;padding:4px 8px}
  /* The number tag reads first now (position before zone/type) and sits a
     shade darker than its siblings, so it registers as "which one" before
     "what kind." */
  .read-section-tag-number{background:color-mix(in oklab, var(--ink-3) 30%, var(--grey-soft))}
  .read-field{margin-bottom:24px}
  .read-field:last-child{margin-bottom:0}
  .read-title{font-size:24px;font-weight:700;color:var(--ink);margin:0;line-height:1.3}
  .read-lead{font-size:16px;color:var(--ink);margin:0;line-height:1.6}
  .read-copy{font-size:16px;color:var(--ink-2);margin:0;line-height:1.65}
  /* A section with nothing captured in any field renders its raw label,
     visibly muted — never invented copy in a reading surface. */
  .read-label-only{font-size:16px;font-style:italic;color:var(--ink-3);margin:0}
  /* CTAs render as buttons — bigger than the card view's own CTA tags,
     since this is the one place they're the main event, not a footnote on
     a small card. */
  .read-ctas{display:flex;flex-wrap:wrap;gap:8px;margin:0}
  .read-cta-pill{display:inline-flex;align-items:center;font-size:16px;font-weight:700;
       padding:8px 16px;border-radius:8px;background:var(--accent-soft);color:var(--accent)}
  /* Edit mode — every field becomes a clean bordered input at once, label
     above (hidden outside edit mode), placeholder guidance in place of the
     text when the field is empty. Outside edit mode, an editable-but-empty
     field simply isn't shown — the reading view still never displays
     invented content, only edit mode invites filling it in. */
  .read-field-label{display:none;font-size:12px;font-weight:600;color:var(--ink-3);margin-bottom:8px}
  .read-editing .read-field-label{display:block}
  .read-page:not(.read-editing) [data-field]:empty{display:none}
  .read-editing [data-field]{border:1px solid var(--line);border-radius:8px;padding:12px 12px;
       background:var(--card);transition:border-color 120ms ease}
  .read-editing [data-field]:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
  .read-editing [data-field]:empty:before{content:attr(data-placeholder);color:var(--ink-3);font-style:italic;font-weight:400}
  .read-editing .read-ctas{display:block}
  .structure-tag-lg{font-size:12px;padding:4px 12px}
  /* The sidebar — sticky, to the right of the reading column. Shape
     depends on the source's kind (see renderSidebar in
     views/structureRead.js): a version's own note; a competitor's auto
     facts + curated facts + note; merged's aggregate auto facts only, no
     note. Renders nothing at all when there's nothing honest to show. */
  .read-sidebar{flex:0 0 420px;position:sticky;top:24px;display:flex;flex-direction:column;gap:20px}
  .read-sidebar-auto-facts,.read-sidebar-curated{padding:12px 16px;
       background:var(--card);border:1px solid var(--line);border-radius:var(--r)}
  .read-sidebar-fact-line{margin:0 0 4px;font-size:12px;color:var(--ink-2);line-height:1.5}
  .read-sidebar-fact-line:last-child{margin-bottom:0}
  /* A version's own name + dates — same card treatment as the facts
     blocks below it, distinct from the dashed note block (an identity, not
     an opinion). */
  .read-sidebar-identity{display:flex;flex-direction:column;gap:8px;padding:12px 16px;
       background:var(--card);border:1px solid var(--line);border-radius:var(--r)}
  .read-sidebar-name-input{width:100%;padding:8px 12px;border:1px solid var(--line);border-radius:8px;
       font-family:var(--sans);font-size:16px;font-weight:650;color:var(--ink);box-sizing:border-box}
  .read-sidebar-date{margin:4px 0 0;font-size:12px;color:var(--ink-3)}
  .read-sidebar-note-block{display:flex;flex-direction:column;gap:8px;padding:12px 16px;
       background:var(--card);border:1px dashed var(--line);border-radius:var(--r)}
  .read-sidebar-note-label{font-size:12px;font-weight:700;letter-spacing:.06em;
       text-transform:uppercase;color:var(--ink-3)}
  .read-sidebar-note-textarea{width:100%;min-height:80px;padding:8px 12px;border:1px solid var(--line);
       border-radius:8px;font-family:var(--sans);font-size:16px;color:var(--ink);resize:vertical;box-sizing:border-box}
  .read-sidebar-note-save{align-self:flex-end;padding:8px 12px;border-radius:8px;font-size:12px;
       font-weight:650;cursor:pointer;border:1px solid var(--accent);background:var(--accent);color:#fff}
  @media(max-width:820px){
    .read-field-tags{display:none}
    .read-main{padding:28px 24px}
    /* Sidebar drops below the reading column rather than disappearing. */
    .read-layout{flex-direction:column}
    .read-sidebar{position:static;flex:none;width:100%}
  }

  @media print{body{background:#fff}.card,table,.term,.facts,.quote,.empty{break-inside:avoid}}
