privateboard 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/public/index.html CHANGED
@@ -560,7 +560,7 @@
560
560
  .agent-row .agent-row-title {
561
561
  color: var(--text);
562
562
  font-family: var(--font-human);
563
- font-weight: 600;
563
+ font-weight: 400;
564
564
  font-size: 14px;
565
565
  letter-spacing: -0.005em;
566
566
  /* Truncate long agent names with ellipsis instead of wrapping
@@ -1219,7 +1219,7 @@
1219
1219
  }
1220
1220
  .row-title {
1221
1221
  font-size: 14px;
1222
- font-weight: 600;
1222
+ font-weight: 400;
1223
1223
  color: var(--text);
1224
1224
  overflow: hidden;
1225
1225
  text-overflow: ellipsis;
@@ -2664,43 +2664,47 @@
2664
2664
  border-bottom: 0.5px solid var(--line);
2665
2665
  }
2666
2666
  .notes-item:last-child { border-bottom: none; }
2667
- .notes-item-delete {
2668
- position: absolute;
2669
- top: 16px;
2670
- right: 6px;
2671
- width: 22px;
2672
- height: 22px;
2673
- background: var(--panel-2);
2674
- border: 0.5px solid var(--line-bright);
2667
+ /* Action row beneath each note · Share + Unfavorite. The row was
2668
+ hover-revealed for a while, but the actions are now always-on so
2669
+ a glance at the note tells the user how to act on it. Buttons
2670
+ use the same flat-pill register as `.bento-director-model` (mono
2671
+ kicker text, 0.5px hairline border, no rounded corners). Clicks
2672
+ funnel through the global click delegator via data-attrs. */
2673
+ /* Bare icon + label, no pill chrome · reads as quiet metadata
2674
+ not as a CTA. The note itself is the primary surface; these
2675
+ actions are secondary affordances revealed on inspection. */
2676
+ .notes-item-actions {
2677
+ display: flex;
2678
+ align-items: center;
2679
+ gap: 16px;
2680
+ padding: 0 4px 14px;
2681
+ margin-top: -4px;
2682
+ }
2683
+ .notes-item-action {
2684
+ display: inline-flex;
2685
+ align-items: center;
2686
+ gap: 5px;
2687
+ padding: 0;
2688
+ background: transparent;
2689
+ border: 0;
2675
2690
  color: var(--text-faint);
2676
2691
  font-family: var(--mono);
2677
- font-size: 11px;
2678
- line-height: 1;
2692
+ font-size: 10px;
2693
+ font-weight: 700;
2694
+ letter-spacing: 0.14em;
2695
+ text-transform: uppercase;
2696
+ line-height: 1.2;
2679
2697
  cursor: pointer;
2680
- display: none;
2681
- align-items: center;
2682
- justify-content: center;
2683
- padding: 0;
2684
- transition: color 0.12s, border-color 0.12s, background 0.12s;
2685
- z-index: 2;
2698
+ transition: color 0.14s;
2686
2699
  }
2687
- .notes-item:hover .notes-item-delete { display: flex; }
2688
- .notes-item-delete:hover {
2689
- color: var(--red);
2690
- border-color: var(--red);
2691
- background: var(--bg);
2700
+ .notes-item-action:hover { color: var(--text); }
2701
+ .notes-item-share:hover { color: var(--lime); }
2702
+ .notes-item-unfav:hover { color: var(--red); }
2703
+ .notes-action-glyph {
2704
+ font-size: 11px;
2705
+ letter-spacing: 0;
2706
+ opacity: 0.9;
2692
2707
  }
2693
- /* Reserve the right-edge gutter ALWAYS (not only on hover) so the
2694
- passage text doesn't reflow when the delete button appears. An
2695
- earlier version applied `padding-right: 30px` only on hover —
2696
- the text visibly jumped each time the user mousemoved across
2697
- rows. Cost: a fixed 30px of empty space at the right edge of
2698
- every passage; cheap compared to the jitter. */
2699
- .notes-item-passage { padding-right: 30px; }
2700
- /* On hover · hide the trailing time tag so the delete button
2701
- occupies the right-edge slot cleanly. visibility:hidden keeps
2702
- the layout box (the meta row doesn't reflow either). */
2703
- .notes-item:hover .notes-item-time { visibility: hidden; }
2704
2708
  .notes-item-link {
2705
2709
  display: block;
2706
2710
  padding: 18px 4px;
@@ -2796,6 +2800,542 @@
2796
2800
  transition: text-decoration-color 0.14s;
2797
2801
  }
2798
2802
 
2803
+ /* ═══════════════════════════════════════════════════════════════
2804
+ SHARE-CARD OVERLAY · the modal mounted when the user clicks the
2805
+ Share button on a note in All Notes. CHROME (overlay + modal
2806
+ + classification strip + head + foot) is shared with the
2807
+ room-settings overlay via the `.room-settings-overlay /
2808
+ .room-settings-modal / .rs-classification / .rs-head / .rs-body
2809
+ / .rs-foot` classes (defined in `room-settings.css`). Only the
2810
+ template chips + preview viewport + the cards themselves are
2811
+ local to this feature.
2812
+
2813
+ PNG export uses the same html-to-image CDN loader as
2814
+ `public/magazine.html` (lazy-fetched on first export). Native
2815
+ render 540×675 at pixelRatio: 2 → 1080×1350 PNG, IG/Weibo/
2816
+ WeChat-friendly. Templates carry hard-coded palettes (NOT
2817
+ `var(--bg)` / `var(--lime)`) so the exported image looks the
2818
+ same regardless of the user's active theme.
2819
+ ═══════════════════════════════════════════════════════════════ */
2820
+ /* Hoist the share-card overlay z-index above other UI · room-
2821
+ settings reserves 950 but the share-card may need to sit over
2822
+ in-room toasts. Same vertical-scroll behaviour as the rs-modal. */
2823
+ .room-settings-overlay#share-card-overlay { z-index: 9700; }
2824
+ /* The All Notes view's share-card needs a slightly wider modal
2825
+ than room-settings (540px card + 32px gutters fits at 640). */
2826
+ .room-settings-overlay#share-card-overlay .room-settings-modal {
2827
+ max-width: 640px;
2828
+ }
2829
+ /* Template chip row · 4 chips, click to swap the preview's
2830
+ `data-share-template` attribute (the preview re-renders
2831
+ instantly because each template's visual is CSS-keyed off
2832
+ the attr). */
2833
+ .share-card-templates {
2834
+ display: flex;
2835
+ gap: 6px;
2836
+ flex-wrap: wrap;
2837
+ margin-bottom: 14px;
2838
+ }
2839
+ .share-card-template-chip {
2840
+ appearance: none;
2841
+ background: var(--panel-2, #1A1A18);
2842
+ border: 0.5px solid var(--line-bright, #2A2A26);
2843
+ color: var(--text-soft, #8E8B83);
2844
+ font-family: var(--mono);
2845
+ font-size: 9.5px;
2846
+ letter-spacing: 0.14em;
2847
+ text-transform: uppercase;
2848
+ font-weight: 700;
2849
+ padding: 5px 10px;
2850
+ cursor: pointer;
2851
+ transition: color 0.14s, border-color 0.14s, background 0.14s;
2852
+ }
2853
+ .share-card-template-chip:hover {
2854
+ color: var(--text, #C8C5BE);
2855
+ border-color: var(--line-strong, #3A3A35);
2856
+ }
2857
+ .share-card-template-chip.active {
2858
+ color: var(--bg, #0A0A0A);
2859
+ background: var(--lime, #6FB572);
2860
+ border-color: var(--lime, #6FB572);
2861
+ }
2862
+ /* Preview viewport · centers the native 540×675 card and scales
2863
+ it down with `transform: scale()` so it fits inside the modal
2864
+ on smaller viewports. The native size is preserved so the
2865
+ html-to-image export captures crisp text at the full
2866
+ resolution; the visual scale-down is cosmetic. */
2867
+ .share-card-preview {
2868
+ /* Width is the MIN of three caps so the preview always stays
2869
+ a perfect 540:800 rectangle — container width (100%), the
2870
+ absolute 540px ceiling, and a viewport-height-derived cap
2871
+ (height * 540/800). The third cap is what shrinks the
2872
+ preview proportionally on short displays without breaking
2873
+ the aspect ratio — and that's what makes the image stay
2874
+ centered in the modal body. With `aspect-ratio: 540/800`,
2875
+ height is derived and matches the preview perfectly.
2876
+ `margin: 0 auto` then centres the whole block in `.rs-body`. */
2877
+ width: min(100%, 540px, calc((100vh - 260px) * 0.675));
2878
+ aspect-ratio: 540 / 800;
2879
+ position: relative;
2880
+ overflow: hidden;
2881
+ background: #0A0A0A;
2882
+ border: 0.5px solid var(--line, #2A2A26);
2883
+ margin: 0 auto;
2884
+ }
2885
+ .share-card-preview-inner {
2886
+ width: 540px;
2887
+ height: 800px;
2888
+ transform-origin: top left;
2889
+ /* JS sets `--share-card-scale` based on the rendered viewport
2890
+ width so a small viewport sees a 100%-fit preview without
2891
+ sacrificing the native render resolution. */
2892
+ transform: scale(var(--share-card-scale, 1));
2893
+ }
2894
+ /* Tighten room-settings's default rs-foot padding for the share
2895
+ card's single hint + download row. */
2896
+ .room-settings-overlay#share-card-overlay .rs-foot {
2897
+ padding: 10px 16px;
2898
+ }
2899
+ .share-card-hint {
2900
+ font-family: var(--mono);
2901
+ font-size: 9.5px;
2902
+ letter-spacing: 0.18em;
2903
+ text-transform: uppercase;
2904
+ color: var(--text-faint, #5C5A52);
2905
+ font-weight: 700;
2906
+ }
2907
+
2908
+ /* ─── Card template base · everything inside the 540×800 frame ─── */
2909
+ .share-card {
2910
+ position: relative;
2911
+ width: 540px;
2912
+ height: 800px;
2913
+ box-sizing: border-box;
2914
+ overflow: hidden;
2915
+ font-family: var(--font-human, "Inter", "Helvetica Neue", system-ui, sans-serif);
2916
+ }
2917
+ .share-card-watermark {
2918
+ position: absolute;
2919
+ bottom: 22px;
2920
+ left: 32px;
2921
+ font-family: var(--mono, "JetBrains Mono", "Menlo", monospace);
2922
+ font-size: 10px;
2923
+ letter-spacing: 0.22em;
2924
+ text-transform: uppercase;
2925
+ opacity: 0.85;
2926
+ }
2927
+ .share-card-stamp {
2928
+ position: absolute;
2929
+ bottom: 22px;
2930
+ right: 32px;
2931
+ font-family: var(--mono, "JetBrains Mono", "Menlo", monospace);
2932
+ font-size: 9.5px;
2933
+ letter-spacing: 0.18em;
2934
+ text-transform: uppercase;
2935
+ opacity: 0.55;
2936
+ }
2937
+
2938
+ /* ── Template A · BOARDROOM · 8-bit pixel-art (DEFAULT) ───────
2939
+ Dribbble-inspired warm-sunset palette: striped horizontal
2940
+ gradient bands climbing from near-black purple at the top
2941
+ through magenta/coral/orange into warm cream at the horizon,
2942
+ where a tiny 8-bit boardroom (table + chairs + mod chair +
2943
+ plants) sits as the brand anchor. The user's quote lives in
2944
+ the centre in a chunky pixel-art dialog box — cream interior,
2945
+ thick dark outline, theme-accent inner band — that reads as
2946
+ "system message in an 8-bit game".
2947
+
2948
+ Pixel-perfect render: `image-rendering: pixelated` on every
2949
+ SVG + `shape-rendering: crispEdges` on every rect keeps the
2950
+ export reading as authentic 8-bit rather than anti-aliased
2951
+ vector graphics.
2952
+
2953
+ Reference: https://dribbble.com/userupload/13578237 (WorkOS
2954
+ Launch Week 8-bit poster). */
2955
+ .share-card[data-share-template="boardroom"] {
2956
+ /* 8 hard-stop bands · near-black purple → deep purple →
2957
+ mauve → rose → coral → orange → peach → cream. Each band
2958
+ is a fixed-percentage stripe so the transitions are sharp
2959
+ (8-bit "no anti-alias" feel), not a smooth gradient. */
2960
+ background: linear-gradient(180deg,
2961
+ #1B0A35 0%, #1B0A35 5%,
2962
+ #2D1452 5%, #2D1452 11%,
2963
+ #4A2070 11%, #4A2070 18%,
2964
+ #6B2B6E 18%, #6B2B6E 25%,
2965
+ #A03B5E 25%, #A03B5E 33%,
2966
+ #D85F4C 33%, #D85F4C 41%,
2967
+ #ED8E48 41%, #ED8E48 49%,
2968
+ #F4C078 49%, #F4C078 57%,
2969
+ #F8D898 57%, #F8D898 100%);
2970
+ color: #1B0A35;
2971
+ image-rendering: pixelated;
2972
+ image-rendering: crisp-edges;
2973
+ }
2974
+ /* Brand strip · top kicker mirrors the WorkOS-style "◇ BRAND"
2975
+ at the very top of the reference image. Cream-on-purple so
2976
+ it reads against the deepest band. */
2977
+ .share-card[data-share-template="boardroom"] .sc-header {
2978
+ position: absolute;
2979
+ top: 22px;
2980
+ left: 28px;
2981
+ right: 28px;
2982
+ display: flex;
2983
+ justify-content: space-between;
2984
+ align-items: baseline;
2985
+ font-family: var(--mono, monospace);
2986
+ font-size: 10.5px;
2987
+ letter-spacing: 0.24em;
2988
+ text-transform: uppercase;
2989
+ color: #F4D898;
2990
+ font-weight: 700;
2991
+ z-index: 4;
2992
+ }
2993
+ .share-card[data-share-template="boardroom"] .sc-header-right {
2994
+ color: var(--lime, #6FB572);
2995
+ }
2996
+ /* Sky decorations · pixel moon + stars + clouds + floating
2997
+ balloons, painted inline by the renderer as an SVG layer that
2998
+ fills the WHOLE card so the atmosphere wraps the dialog box
2999
+ on every side (not just the top). z-index keeps decorations
3000
+ behind the dialog and the header but in front of the gradient. */
3001
+ .share-card[data-share-template="boardroom"] .sc-sky-deco {
3002
+ position: absolute;
3003
+ inset: 0;
3004
+ z-index: 1;
3005
+ pointer-events: none;
3006
+ image-rendering: pixelated;
3007
+ shape-rendering: crispEdges;
3008
+ }
3009
+ .share-card[data-share-template="boardroom"] .sc-heart {
3010
+ display: inline-block;
3011
+ color: var(--lime, #6FB572);
3012
+ margin-left: 8px;
3013
+ font-size: 11px;
3014
+ transform: translateY(0.5px);
3015
+ }
3016
+ /* Wooden 8-bit signpost · cream parchment interior framed by a
3017
+ chunky 8px wood-tone border, with a 2px pixel bevel inside
3018
+ the wood (sun-side highlight + shadow-side darker tone), a
3019
+ 2px dark outline outside the wood ("ink line"), and a hard
3020
+ 6px drop shadow on the ground for the 8-bit sticker feel.
3021
+ Four pixel "nails" pin the frame at each corner (added
3022
+ inline by the renderer; styled below).
3023
+
3024
+ The tail is intentionally absent — a wooden sign doesn't
3025
+ speech-bubble. The two pseudo-elements that used to draw the
3026
+ tail are hidden. */
3027
+ .share-card[data-share-template="boardroom"] .sc-bubble {
3028
+ position: absolute;
3029
+ top: 200px;
3030
+ left: 32px;
3031
+ right: 32px;
3032
+ max-height: 260px;
3033
+ min-height: 160px;
3034
+ background: #FFF6D9;
3035
+ /* 8px wood-tone border carries the bevel inset highlights */
3036
+ border: 8px solid #7A5230;
3037
+ box-shadow:
3038
+ inset 2px 2px 0 #C8A877, /* top-left wood highlight */
3039
+ inset -2px -2px 0 #4A2E18, /* bottom-right wood shadow */
3040
+ 0 0 0 2px #1B0A35, /* outer ink-line outline */
3041
+ 6px 6px 0 0 #1B0A35; /* 8-bit drop shadow */
3042
+ padding: 24px 28px;
3043
+ color: #1B0A35;
3044
+ font-family: "Tiempos Text", "Charter", "Iowan Old Style", "Georgia", serif;
3045
+ font-style: italic;
3046
+ line-height: 1.42;
3047
+ text-align: left;
3048
+ z-index: 3;
3049
+ overflow: hidden;
3050
+ }
3051
+ /* Tail removed for the wooden plank · clean rectangular frame. */
3052
+ .share-card[data-share-template="boardroom"] .sc-bubble::before,
3053
+ .share-card[data-share-template="boardroom"] .sc-bubble::after {
3054
+ display: none;
3055
+ }
3056
+ /* Pixel nails · 4×4 dark squares pinned to the middle of the
3057
+ 8px wood border at each corner. Reads as the iron nails
3058
+ holding the wooden plank together. */
3059
+ .share-card[data-share-template="boardroom"] .sc-nail {
3060
+ position: absolute;
3061
+ width: 4px;
3062
+ height: 4px;
3063
+ background: #1B0A35;
3064
+ z-index: 4;
3065
+ }
3066
+ .share-card[data-share-template="boardroom"] .sc-nail.tl { top: 2px; left: 2px; }
3067
+ .share-card[data-share-template="boardroom"] .sc-nail.tr { top: 2px; right: 2px; }
3068
+ .share-card[data-share-template="boardroom"] .sc-nail.bl { bottom: 2px; left: 2px; }
3069
+ .share-card[data-share-template="boardroom"] .sc-nail.br { bottom: 2px; right: 2px; }
3070
+ .share-card[data-share-template="boardroom"] .sc-bubble-text { margin: 0; }
3071
+ /* Topic annotation above the quote · small monospace kicker
3072
+ showing what question the room was convened around (the
3073
+ note's `roomSubject`). Reads as a hand-written marginalia /
3074
+ code-comment on the wooden plank: `// re: <subject>`. A
3075
+ 1-px dashed underline separates it from the main quote with
3076
+ comfortable padding on both sides so the line never sits
3077
+ flush against the text. No line-clamp · long subjects wrap
3078
+ naturally, and the bubble's font-size tier-down keeps the
3079
+ quote readable even when the meta block takes a few lines. */
3080
+ .share-card[data-share-template="boardroom"] .sc-bubble-meta {
3081
+ display: block;
3082
+ font-family: var(--mono, "JetBrains Mono", "Menlo", monospace);
3083
+ font-size: 10px;
3084
+ letter-spacing: 0.14em;
3085
+ text-transform: uppercase;
3086
+ color: #6B5A48;
3087
+ font-style: normal;
3088
+ /* Annotation reads as quiet marginalia — regular weight, no
3089
+ bold. The CJK override below keeps Chinese in regular
3090
+ weight too (overriding the default `.cjk { weight: 700 }`). */
3091
+ font-weight: 400;
3092
+ line-height: 1.5;
3093
+ margin: 0 0 16px 0;
3094
+ padding-bottom: 14px;
3095
+ border-bottom: 1px dashed rgba(27, 10, 53, 0.32);
3096
+ word-break: break-word;
3097
+ overflow-wrap: anywhere;
3098
+ }
3099
+ .share-card[data-share-template="boardroom"] .sc-bubble-meta .cjk {
3100
+ font-weight: 400;
3101
+ }
3102
+ /* Mixed-script typography for share cards · Latin / English keeps
3103
+ the serif italic register (Tiempos / Charter / Georgia); CJK
3104
+ runs that the renderer wraps in `<span class="cjk">` switch to
3105
+ PingFang at a heavier weight so Chinese characters print bold
3106
+ and upright (italic-skew on CJK reads as a rendering glitch).
3107
+ Scoped to `.share-card` so other parts of the UI keep their
3108
+ own typography. */
3109
+ .share-card .cjk {
3110
+ /* Prefer the macOS-native Heiti family · STHeiti and Hiragino
3111
+ Sans GB both render Chinese with a slightly warmer, more
3112
+ editorial weight than PingFang. PingFang stays in the stack
3113
+ as a fallback for systems without the Heiti faces. */
3114
+ font-family: "STHeiti", "Heiti SC", "Hiragino Sans GB",
3115
+ "PingFang SC", "PingFang TC", "Microsoft YaHei", sans-serif;
3116
+ font-weight: 700;
3117
+ font-style: normal;
3118
+ letter-spacing: 0;
3119
+ }
3120
+ /* Byline · stone-textured pixel plaque holding the director
3121
+ name. Same three-tone stone palette as the river-bank rocks
3122
+ (mid-grey body / lighter top-left highlight / darker bottom-
3123
+ right rim) plus a 2px dark outline + a 4px hard drop shadow,
3124
+ so the label reads as a chunky 8-bit name-plate carved
3125
+ from the same rock vocabulary. Centred horizontally below
3126
+ the wooden bubble. CJK director names inside it render in
3127
+ PingFang bold via the `.cjk` rule above (italic skew is
3128
+ intentionally not applied to CJK glyphs). */
3129
+ .share-card[data-share-template="boardroom"] .sc-byline {
3130
+ position: absolute;
3131
+ top: 488px;
3132
+ left: 50%;
3133
+ transform: translateX(-50%);
3134
+ display: inline-flex;
3135
+ align-items: center;
3136
+ padding: 8px 22px;
3137
+ background: #7A6F62;
3138
+ border: 2px solid #1B0A35;
3139
+ box-shadow:
3140
+ inset 2px 2px 0 #9F9388,
3141
+ inset -2px -2px 0 #4A4038,
3142
+ 4px 4px 0 0 #1B0A35;
3143
+ color: #FFF6D9;
3144
+ font-family: "Tiempos Text", "Charter", "Iowan Old Style", "Georgia", serif;
3145
+ font-style: italic;
3146
+ font-size: 16px;
3147
+ letter-spacing: 0.04em;
3148
+ font-weight: 600;
3149
+ text-align: center;
3150
+ white-space: nowrap;
3151
+ max-width: 380px;
3152
+ z-index: 4;
3153
+ }
3154
+ /* Watermark + stamp · dark purple chrome on the warm-cream
3155
+ bottom band so they read like a stamped postal mark. */
3156
+ .share-card[data-share-template="boardroom"] .share-card-watermark {
3157
+ color: #4A2070;
3158
+ bottom: 16px;
3159
+ left: 28px;
3160
+ font-size: 10.5px;
3161
+ letter-spacing: 0.22em;
3162
+ opacity: 1;
3163
+ }
3164
+ .share-card[data-share-template="boardroom"] .share-card-stamp {
3165
+ color: #4A2070;
3166
+ bottom: 16px;
3167
+ right: 28px;
3168
+ opacity: 0.7;
3169
+ }
3170
+ /* Mod chair · cyan rails / gem follow the user's `--cyan` theme
3171
+ token (matches the live round-table moderator chair). Local
3172
+ to this card so the other templates aren't affected. */
3173
+ .share-card[data-share-template="boardroom"] .mod-rail { fill: var(--cyan, #6A9B97); }
3174
+ .share-card[data-share-template="boardroom"] .mod-rail-hi { fill: color-mix(in srgb, var(--cyan, #6A9B97) 60%, #FFFFFF 40%); }
3175
+ .share-card[data-share-template="boardroom"] .mod-gem { fill: var(--cyan, #6A9B97); }
3176
+ .share-card[data-share-template="boardroom"] .mod-gem-hi { fill: color-mix(in srgb, var(--cyan, #6A9B97) 50%, #FFFFFF 50%); }
3177
+
3178
+ /* ── Template B · EDITORIAL · warm cream, pull-quote, serif ─── */
3179
+ .share-card[data-share-template="editorial"] {
3180
+ background: #F4EFE3;
3181
+ color: #2A2620;
3182
+ padding: 56px 52px;
3183
+ display: flex;
3184
+ flex-direction: column;
3185
+ justify-content: space-between;
3186
+ }
3187
+ .share-card[data-share-template="editorial"] .sc-quotemark {
3188
+ font-family: "Tiempos Headline", "Charter", "Georgia", serif;
3189
+ font-size: 120px;
3190
+ line-height: 0.6;
3191
+ color: #B5704A;
3192
+ margin: 0 0 -28px;
3193
+ user-select: none;
3194
+ }
3195
+ .share-card[data-share-template="editorial"] .sc-quote {
3196
+ font-family: "Tiempos Headline", "Charter", "Iowan Old Style", "Georgia", serif;
3197
+ line-height: 1.32;
3198
+ color: #2A2620;
3199
+ margin: 0;
3200
+ font-weight: 500;
3201
+ /* Font-size set inline by the renderer for length-based step-down. */
3202
+ }
3203
+ .share-card[data-share-template="editorial"] .sc-quote em {
3204
+ font-style: italic;
3205
+ color: #B5704A;
3206
+ }
3207
+ .share-card[data-share-template="editorial"] .sc-byline {
3208
+ margin-top: 24px;
3209
+ padding-top: 18px;
3210
+ border-top: 0.5px solid #B5A893;
3211
+ font-family: var(--mono, monospace);
3212
+ font-size: 10.5px;
3213
+ letter-spacing: 0.18em;
3214
+ text-transform: uppercase;
3215
+ color: #6F6354;
3216
+ }
3217
+ .share-card[data-share-template="editorial"] .sc-byline strong {
3218
+ color: #B5704A;
3219
+ font-weight: 700;
3220
+ }
3221
+ .share-card[data-share-template="editorial"] .share-card-watermark { color: #6F6354; }
3222
+ .share-card[data-share-template="editorial"] .share-card-stamp { color: #8E8270; }
3223
+
3224
+ /* ── Template C · TERMINAL · monospace CRT ──────────────────── */
3225
+ .share-card[data-share-template="terminal"] {
3226
+ background: #0E1414;
3227
+ color: #C9F2C2;
3228
+ padding: 44px 38px;
3229
+ display: flex;
3230
+ flex-direction: column;
3231
+ font-family: var(--mono, "JetBrains Mono", "Menlo", monospace);
3232
+ }
3233
+ .share-card[data-share-template="terminal"] .sc-frame {
3234
+ flex: 1;
3235
+ border: 1px solid var(--lime, #6FB572);
3236
+ padding: 28px 26px;
3237
+ position: relative;
3238
+ display: flex;
3239
+ flex-direction: column;
3240
+ }
3241
+ .share-card[data-share-template="terminal"] .sc-frame::before {
3242
+ content: "// excerpt";
3243
+ position: absolute;
3244
+ top: -7px;
3245
+ left: 24px;
3246
+ background: #0E1414;
3247
+ color: var(--lime, #6FB572);
3248
+ font-family: var(--mono, monospace);
3249
+ font-size: 10px;
3250
+ letter-spacing: 0.28em;
3251
+ text-transform: uppercase;
3252
+ padding: 0 8px;
3253
+ }
3254
+ .share-card[data-share-template="terminal"] .sc-prompt {
3255
+ font-family: var(--mono, monospace);
3256
+ font-size: 10.5px;
3257
+ letter-spacing: 0.18em;
3258
+ text-transform: uppercase;
3259
+ color: var(--lime, #6FB572);
3260
+ margin-bottom: 18px;
3261
+ }
3262
+ .share-card[data-share-template="terminal"] .sc-quote {
3263
+ font-family: var(--mono, "JetBrains Mono", "Menlo", monospace);
3264
+ line-height: 1.55;
3265
+ color: #DDF6D7;
3266
+ margin: 0;
3267
+ flex: 1;
3268
+ /* Font-size set inline by the renderer for length-based step-down. */
3269
+ }
3270
+ .share-card[data-share-template="terminal"] .sc-byline {
3271
+ margin-top: 22px;
3272
+ font-family: var(--mono, monospace);
3273
+ font-size: 10px;
3274
+ letter-spacing: 0.18em;
3275
+ text-transform: uppercase;
3276
+ color: var(--lime, #6FB572);
3277
+ }
3278
+ .share-card[data-share-template="terminal"] .sc-byline-dim { color: #8E9D89; }
3279
+ .share-card[data-share-template="terminal"] .share-card-watermark { color: var(--lime, #6FB572); left: 24px; bottom: 18px; }
3280
+ .share-card[data-share-template="terminal"] .share-card-stamp { color: #8E9D89; right: 24px; bottom: 18px; }
3281
+
3282
+ /* ── Template D · MAGAZINE · mixed serif + sans, pull-quote ─── */
3283
+ .share-card[data-share-template="magazine"] {
3284
+ background: linear-gradient(180deg, #FFFFFF 0%, #F2EFE9 100%);
3285
+ color: #1A1A1A;
3286
+ padding: 56px 52px;
3287
+ display: flex;
3288
+ flex-direction: column;
3289
+ }
3290
+ .share-card[data-share-template="magazine"] .sc-stripe {
3291
+ height: 3px;
3292
+ width: 56px;
3293
+ background: #1A1A1A;
3294
+ margin-bottom: 22px;
3295
+ }
3296
+ .share-card[data-share-template="magazine"] .sc-kicker {
3297
+ font-family: var(--mono, monospace);
3298
+ font-size: 10.5px;
3299
+ letter-spacing: 0.22em;
3300
+ text-transform: uppercase;
3301
+ color: #1A1A1A;
3302
+ margin-bottom: 26px;
3303
+ }
3304
+ .share-card[data-share-template="magazine"] .sc-quote {
3305
+ font-family: "Tiempos Headline", "Charter", "Iowan Old Style", "Georgia", serif;
3306
+ line-height: 1.22;
3307
+ color: #0A0A0A;
3308
+ font-weight: 600;
3309
+ letter-spacing: -0.01em;
3310
+ margin: 0;
3311
+ flex: 1;
3312
+ /* Font-size set inline by the renderer for length-based step-down. */
3313
+ }
3314
+ .share-card[data-share-template="magazine"] .sc-byline {
3315
+ margin-top: 24px;
3316
+ padding-top: 18px;
3317
+ border-top: 1px solid #1A1A1A;
3318
+ font-family: var(--mono, monospace);
3319
+ font-size: 10.5px;
3320
+ letter-spacing: 0.16em;
3321
+ text-transform: uppercase;
3322
+ color: #555050;
3323
+ display: flex;
3324
+ justify-content: space-between;
3325
+ align-items: center;
3326
+ }
3327
+ .share-card[data-share-template="magazine"] .sc-byline strong {
3328
+ color: #1A1A1A;
3329
+ font-weight: 700;
3330
+ }
3331
+ .share-card[data-share-template="magazine"] .share-card-watermark { color: #1A1A1A; }
3332
+ .share-card[data-share-template="magazine"] .share-card-stamp { color: #777070; }
3333
+
3334
+ @media (max-width: 580px) {
3335
+ .share-card-modal { padding: 18px 14px 14px; }
3336
+ .share-card-preview { max-width: 100%; }
3337
+ }
3338
+
2799
3339
  /* In-room highlight overlay · injected into director-message
2800
3340
  `.msg-bubble` text by app.applyNoteHighlightsForMessage. Same
2801
3341
  visual register as `.note-quote` so a saved span reads with the
@@ -7647,8 +8187,15 @@
7647
8187
  width: 80px;
7648
8188
  height: 18px;
7649
8189
  border-radius: 50%;
8190
+ /* Themed glow · matches the speech-bubble border above this
8191
+ seat. Previously hardcoded `rgba(111, 181, 114, 0.55)` (the
8192
+ legacy lime green) which stayed green even when the active
8193
+ theme remapped --lime (e.g. Pinterest red, Apple blue,
8194
+ Nintendo Mario red). color-mix folds the live --lime token
8195
+ to 55% alpha so the floor halo always reads as the same
8196
+ accent as the bubble border. */
7650
8197
  background: radial-gradient(ellipse at center,
7651
- rgba(111, 181, 114, 0.55) 0%,
8198
+ color-mix(in srgb, var(--lime) 55%, transparent) 0%,
7652
8199
  transparent 70%);
7653
8200
  z-index: 0;
7654
8201
  animation: rt-glow 0.9s ease-in-out infinite;
@@ -7656,8 +8203,13 @@
7656
8203
  transition: background 0.18s;
7657
8204
  }
7658
8205
  .rt-seat-thinking::before {
8206
+ /* Thinking glow tracks the same primary --lime as the bubble
8207
+ above (see `.rt-bubble.is-thinking`). Dimmer alpha than the
8208
+ speaking glow (35% vs 55%) is the visual "warming up" cue
8209
+ paired with the dashed bubble border + slower dot rhythm —
8210
+ all theme-aware. */
7659
8211
  background: radial-gradient(ellipse at center,
7660
- rgba(181, 149, 96, 0.50) 0%,
8212
+ color-mix(in srgb, var(--lime) 35%, transparent) 0%,
7661
8213
  transparent 70%);
7662
8214
  animation-duration: 1.4s;
7663
8215
  }
@@ -7706,7 +8258,11 @@
7706
8258
  font-weight: 700;
7707
8259
  letter-spacing: 0.06em;
7708
8260
  text-transform: uppercase;
7709
- color: var(--text-soft);
8261
+ /* Hardcoded light name text · plate background is fixed dark
8262
+ regardless of theme (visibility over the stage floor). On
8263
+ light themes (pinterest / atrium) var(--text-soft) is mid-
8264
+ grey and the name disappears into the plate. */
8265
+ color: #D8D8DC;
7710
8266
  white-space: nowrap;
7711
8267
  text-align: center;
7712
8268
  pointer-events: none;
@@ -7734,7 +8290,9 @@
7734
8290
  font-size: 10px;
7735
8291
  font-weight: 600;
7736
8292
  letter-spacing: 0.04em;
7737
- color: var(--text-soft);
8293
+ /* Hardcoded light · same rationale as .rt-name above (dark
8294
+ plate is fixed regardless of theme). */
8295
+ color: rgba(216, 216, 220, 0.78);
7738
8296
  margin-top: 3px;
7739
8297
  }
7740
8298
  /* Chair-seat name colour follows the room's tone via the
@@ -7797,9 +8355,20 @@
7797
8355
  transform-origin: 50% 100%;
7798
8356
  transition: border-color 0.18s, color 0.18s;
7799
8357
  }
8358
+ /* Thinking variant · same theme primary as speaking
8359
+ (`var(--lime)`), differentiated by softer opacity + slower
8360
+ dot rhythm (set further down). Previously used `var(--amber)`
8361
+ for border/text — but amber is a separate accent (Pinterest =
8362
+ orange, Nintendo = coin gold, etc.) that doesn't match the
8363
+ primary theme colour, so thinking bubbles looked "off-brand"
8364
+ in light themes. Tying both states to --lime keeps the seat
8365
+ indicators on-theme; the visual state read still works
8366
+ because the dimmer opacity + slower dots + status word
8367
+ "thinking" carry the "warming up" cue. */
7800
8368
  .rt-bubble.is-thinking {
7801
- border-color: var(--amber, #B59560);
7802
- color: var(--amber, #B59560);
8369
+ border-color: var(--lime);
8370
+ color: var(--lime);
8371
+ opacity: 0.78;
7803
8372
  }
7804
8373
  .rt-bubble::after {
7805
8374
  content: "";
@@ -7815,7 +8384,10 @@
7815
8384
  transition: border-top-color 0.18s;
7816
8385
  }
7817
8386
  .rt-bubble.is-thinking::after {
7818
- border-top-color: var(--amber, #B59560);
8387
+ /* Tail tracks the bubble's themed primary too · see the
8388
+ .rt-bubble.is-thinking rule above for why thinking switched
8389
+ from --amber to --lime. */
8390
+ border-top-color: var(--lime);
7819
8391
  }
7820
8392
  /* Speaker name (primary) + status (secondary) inside the bubble.
7821
8393
  Both lines centred · monospace sticks to the kicker register
@@ -7854,7 +8426,10 @@
7854
8426
  transition: background 0.18s;
7855
8427
  }
7856
8428
  .rt-bubble.is-thinking .rt-bubble-dots i {
7857
- background: var(--amber, #B59560);
8429
+ /* Dots track the bubble's themed primary too. The slower
8430
+ animation (1.4s vs the speaking 1s) is the kinetic state
8431
+ cue alongside the dashed border + dimmed opacity. */
8432
+ background: var(--lime);
7858
8433
  animation-duration: 1.4s;
7859
8434
  }
7860
8435
  .rt-bubble-dots i:nth-child(2) { animation-delay: 0.15s; }
@@ -8000,6 +8575,94 @@
8000
8575
  }
8001
8576
  .rt-bubble-user-close:hover { color: var(--lime); }
8002
8577
 
8578
+ /* ─── Chair clarify bubble · prose question pinned above the chair
8579
+ avatar in voice-mode round-1 ───────────────────────────────────
8580
+ When the chair asks a clarifying question (meta.kind === "clarify")
8581
+ the user sees the question text in a speech bubble over the chair
8582
+ seat with a 10s border countdown — same conic-gradient mechanic
8583
+ as the user's bubble (see `.rt-bubble-user`). On timeout (or `×`
8584
+ click) the bubble auto-dismisses. The user-bubble's lime palette
8585
+ is reused intentionally: same countdown grammar, same speech-
8586
+ bubble register, only the anchor seat differs.
8587
+
8588
+ The chair seat sits at the BOTTOM of the stage, so the bubble
8589
+ grows upward over the table — which is fine visually because the
8590
+ bubble has its own `panel-3` interior and z-index: 5 keeps it
8591
+ above table props. Multi-line questions stay legible at any
8592
+ reasonable length. */
8593
+ .rt-bubble-chair-clarify {
8594
+ display: flex;
8595
+ align-items: flex-start;
8596
+ gap: 6px;
8597
+ width: max-content;
8598
+ max-width: 240px;
8599
+ pointer-events: auto;
8600
+ white-space: normal;
8601
+ padding: 5px 9px;
8602
+ text-transform: none;
8603
+ letter-spacing: 0;
8604
+ font-size: 11px;
8605
+ font-weight: 500;
8606
+ color: var(--text);
8607
+ animation: none;
8608
+ transform: translateX(-50%);
8609
+ top: auto;
8610
+ bottom: calc(100% + 4px);
8611
+ border-width: 2px;
8612
+ border-color: transparent;
8613
+ --rt-bubble-chair-progress: 0;
8614
+ background:
8615
+ linear-gradient(var(--panel-3), var(--panel-3)) padding-box,
8616
+ conic-gradient(
8617
+ from -90deg,
8618
+ var(--lime) 0,
8619
+ var(--lime) calc(var(--rt-bubble-chair-progress) * 360deg),
8620
+ var(--lime-dim, #2D5532) 0
8621
+ ) border-box;
8622
+ }
8623
+ .rt-bubble-chair-clarify-text {
8624
+ min-width: 0;
8625
+ color: var(--text);
8626
+ line-height: 1.4;
8627
+ word-break: break-word;
8628
+ overflow-wrap: anywhere;
8629
+ }
8630
+ /* Same heftier downward tail as the user bubble · keeps the speech
8631
+ bubble visually anchored to the seat below at the stage's scale. */
8632
+ .rt-bubble-chair-clarify::after {
8633
+ border-left-width: 7px;
8634
+ border-right-width: 7px;
8635
+ border-top-width: 7px;
8636
+ border-top-color: var(--lime);
8637
+ bottom: -7px;
8638
+ }
8639
+ .rt-bubble-chair-clarify::before {
8640
+ content: "";
8641
+ position: absolute;
8642
+ bottom: -8px;
8643
+ left: 50%;
8644
+ transform: translateX(-50%);
8645
+ width: 0;
8646
+ height: 0;
8647
+ border-left: 8px solid transparent;
8648
+ border-right: 8px solid transparent;
8649
+ border-top: 8px solid var(--lime-dim, #2D5532);
8650
+ pointer-events: none;
8651
+ }
8652
+ .rt-bubble-chair-clarify-close {
8653
+ appearance: none;
8654
+ background: none;
8655
+ border: 0;
8656
+ color: var(--text-faint);
8657
+ cursor: pointer;
8658
+ font-size: 11px;
8659
+ line-height: 1;
8660
+ padding: 2px 4px;
8661
+ margin-top: -1px;
8662
+ transition: color 0.12s;
8663
+ }
8664
+ .rt-bubble-chair-clarify-close:hover { color: var(--lime); }
8665
+
8003
8666
  /* Wait-marker · small flat pixel pill on the user seat shown
8004
8667
  ONLY when the user has picked "wait — flush after current
8005
8668
  speaker finishes" in the interrupt-or-queue modal. Slow
@@ -8020,10 +8683,16 @@
8020
8683
  font-weight: 700;
8021
8684
  letter-spacing: 0.18em;
8022
8685
  text-transform: uppercase;
8023
- color: var(--amber, #B59560);
8686
+ /* Themed primary · matches the speech bubble border family
8687
+ (speaking/thinking/wait all read off the same --lime so the
8688
+ seat indicators stay on-brand across themes). Dashed border
8689
+ + blink animation differentiates "queued, holding" from the
8690
+ solid speaking border. Was --amber (Pinterest = orange,
8691
+ Nintendo = coin gold) which clashed with the primary theme. */
8692
+ color: var(--lime);
8024
8693
  padding: 3px 6px;
8025
8694
  background: var(--panel-3);
8026
- border: 1px solid var(--amber, #B59560);
8695
+ border: 1px dashed var(--lime);
8027
8696
  white-space: nowrap;
8028
8697
  animation: rt-seat-wait-blink 1.6s steps(1) infinite;
8029
8698
  }
@@ -8242,7 +8911,13 @@
8242
8911
  font-family: var(--font-human);
8243
8912
  font-size: 14px;
8244
8913
  line-height: 1.5;
8245
- color: var(--text);
8914
+ /* Hardcoded light caption text · the subtitle panel uses a
8915
+ fixed near-black background regardless of theme (cinema-
8916
+ caption aesthetic for legibility over a busy stage), so the
8917
+ body text can't follow var(--text). On light themes
8918
+ (pinterest / atrium / etc.) var(--text) is near-black and
8919
+ collides with the panel — black-on-black caption. */
8920
+ color: #F4F4F6;
8246
8921
  word-break: break-word;
8247
8922
  /* The renderer slices `text` to a ~140-char window ending at
8248
8923
  the current TTS cursor (`audio.currentTime / duration`), so
@@ -8440,7 +9115,9 @@
8440
9115
  font-weight: 700;
8441
9116
  letter-spacing: 0.18em;
8442
9117
  text-transform: uppercase;
8443
- color: var(--text-soft);
9118
+ /* Hardcoded light · rate-btn label over the fixed dark HUD
9119
+ glass; var(--text-soft) is mid-grey in light themes. */
9120
+ color: rgba(216, 216, 220, 0.85);
8444
9121
  cursor: pointer;
8445
9122
  pointer-events: auto;
8446
9123
  transition: background 0.08s, color 0.08s;
@@ -8487,7 +9164,10 @@
8487
9164
  padding: 5px 10px;
8488
9165
  font-size: 9px;
8489
9166
  letter-spacing: 0.04em;
8490
- color: var(--text-soft);
9167
+ /* Hardcoded light · the HUD body sits on a fixed dark frosted-
9168
+ glass background, so log entries can't follow var(--text-soft)
9169
+ which is dark grey in light themes (pinterest / atrium). */
9170
+ color: rgba(216, 216, 220, 0.78);
8491
9171
  border-top: 1px solid var(--line);
8492
9172
  /* `steps(4)` so the entry materialises in 4 discrete frames —
8493
9173
  reads as a pixel-game tile flip, not a smooth fade. */
@@ -8512,7 +9192,9 @@
8512
9192
  }
8513
9193
  .rt-hud-log-text em {
8514
9194
  font-style: italic;
8515
- color: var(--text);
9195
+ /* Hardcoded light · emphasis word (speaker name) over the
9196
+ fixed dark HUD glass; var(--text) is dark in light themes. */
9197
+ color: #F4F4F6;
8516
9198
  font-weight: 700;
8517
9199
  }
8518
9200
  .rt-hud-log-entry.rt-hud-log-add .rt-hud-log-glyph { color: var(--lime, #6FB572); }
@@ -9991,7 +10673,13 @@
9991
10673
  overflow-y: auto;
9992
10674
  }
9993
10675
  .chat.chat--composer.chat--composer-overflow .cmp {
9994
- padding-top: max(32px, calc(50vh - 110px));
10676
+ /* Overflow mode · the starters tray (now augmented with
10677
+ topic recommendations + the "+ N more" button) can push
10678
+ total content past one viewport, at which point the
10679
+ composer can't stay centred. Pin the hero a fixed 120px
10680
+ from the top so it sits comfortably above the fold and
10681
+ the tray scrolls underneath. */
10682
+ padding-top: 120px;
9995
10683
  }
9996
10684
  .cmp-hero {
9997
10685
  text-align: center;
@@ -10570,6 +11258,126 @@
10570
11258
  transform: translateX(3px);
10571
11259
  }
10572
11260
 
11261
+ /* ─── Topic recommendations · home composer "or try a starter"
11262
+ tray.
11263
+ · `.cmp-recs-trigger-card` · disguised as the FIRST row
11264
+ in the starters grid. Click → SSE-driven loading +
11265
+ animated dots happen INSIDE the same card (no separate
11266
+ progress strip). Dashed lime-dim bottom rule + ✦ glyph
11267
+ distinguish it from regular starters at a glance.
11268
+ · `.cmp-rec` · each AI-generated topic. Tag is the
11269
+ synthesiser's category (e.g. "strategy", "product").
11270
+ Tray shows exactly 6 cards — every generation wipes
11271
+ the previous batch, no pagination surface.
11272
+ Theme-token only · no hardcoded colors. ─── */
11273
+ .cmp-recs-trigger-card {
11274
+ position: relative;
11275
+ /* Dashed lime-dim bottom rule reads as "this row is the
11276
+ generator" before any click. Override .cmp-starter's
11277
+ solid var(--line) baseline; the progress bar lives on
11278
+ this same edge during the busy state. */
11279
+ border-bottom-style: dashed !important;
11280
+ border-bottom-color: var(--lime-dim) !important;
11281
+ }
11282
+ .cmp-recs-trigger-card .cmp-starter-tag {
11283
+ color: var(--lime);
11284
+ }
11285
+ .cmp-recs-trigger-card .cmp-starter-arrow {
11286
+ color: var(--lime);
11287
+ font-weight: 700;
11288
+ transition: transform 0.18s ease;
11289
+ }
11290
+ .cmp-recs-trigger-card:hover:not(.is-busy) .cmp-starter-arrow {
11291
+ transform: rotate(90deg);
11292
+ }
11293
+ .cmp-recs-trigger-card.is-busy {
11294
+ cursor: progress;
11295
+ }
11296
+ .cmp-recs-trigger-card.is-busy .cmp-starter-text {
11297
+ color: var(--text-soft);
11298
+ }
11299
+ /* Progress bar · sits flush along the card's dashed bottom
11300
+ edge. Lime fill grows left-to-right as the pipeline ticks. */
11301
+ .cmp-recs-trigger-bar {
11302
+ position: absolute;
11303
+ left: 0;
11304
+ right: 0;
11305
+ bottom: -1px;
11306
+ height: 2px;
11307
+ background: transparent;
11308
+ pointer-events: none;
11309
+ overflow: hidden;
11310
+ }
11311
+ .cmp-recs-trigger-fill {
11312
+ height: 100%;
11313
+ background: var(--lime);
11314
+ width: 0;
11315
+ transition: width 0.4s ease-out;
11316
+ }
11317
+ /* Three-dot loading glyph · matches the round-table
11318
+ speech-bubble dots' rhythm; lime accent, compact, sits
11319
+ inline next to the phase-detail text inside the busy
11320
+ card so the user reads "<dots> scanning 3/10 keywords". */
11321
+ .cmp-recs-trigger-dots {
11322
+ display: inline-flex;
11323
+ align-items: center;
11324
+ gap: 3px;
11325
+ margin-right: 6px;
11326
+ vertical-align: middle;
11327
+ }
11328
+ .cmp-recs-trigger-dots i {
11329
+ width: 4px;
11330
+ height: 4px;
11331
+ background: var(--lime);
11332
+ border-radius: 50%;
11333
+ display: inline-block;
11334
+ animation: cmp-trec-dot 1s ease-in-out infinite;
11335
+ }
11336
+ .cmp-recs-trigger-dots i:nth-child(2) { animation-delay: 0.15s; }
11337
+ .cmp-recs-trigger-dots i:nth-child(3) { animation-delay: 0.30s; }
11338
+ @keyframes cmp-trec-dot {
11339
+ 0%, 80%, 100% { opacity: 0.25; transform: scale(0.7); }
11340
+ 40% { opacity: 1; transform: scale(1); }
11341
+ }
11342
+ /* Topic-rec card · extends .cmp-starter. The tag is the
11343
+ synthesiser-produced category; the data-source attribute
11344
+ drives a subtle colour cue (lime for web-grounded recs,
11345
+ text-faint for memory-only) without taking real estate
11346
+ away from the actual tag text. */
11347
+ .cmp-rec {
11348
+ /* `.cmp-starter` base is `auto 1fr auto`. The rec card adds
11349
+ a hint row spanning the middle column so the middle column
11350
+ stacks subject / hint. `align-items: start` so tag + arrow
11351
+ anchor to the subject line, not the centre of the taller
11352
+ block. */
11353
+ align-items: start;
11354
+ padding-top: 12px;
11355
+ padding-bottom: 12px;
11356
+ }
11357
+ .cmp-rec[data-source="web"] .cmp-starter-tag {
11358
+ color: var(--lime);
11359
+ }
11360
+ .cmp-rec[data-source="memory"] .cmp-starter-tag {
11361
+ color: var(--text-faint);
11362
+ }
11363
+ /* Subtitle · synthesiser's "why this fits you" rationale.
11364
+ Sits under the subject in the middle column, italic +
11365
+ text-faint so it reads as caption-tier without competing
11366
+ with the subject line above. ALSO travels into the room
11367
+ as hidden seed context (see `applyTopicRec`). */
11368
+ .cmp-rec-hint {
11369
+ grid-column: 2;
11370
+ margin-top: 4px;
11371
+ font-family: var(--font-human);
11372
+ font-size: 11.5px;
11373
+ line-height: 1.4;
11374
+ color: var(--text-faint);
11375
+ display: -webkit-box;
11376
+ -webkit-line-clamp: 2;
11377
+ -webkit-box-orient: vertical;
11378
+ overflow: hidden;
11379
+ font-style: italic;
11380
+ }
10573
11381
  /* ─── New-agent composer · variant of the new-room composer.
10574
11382
  Reuses .cmp / .cmp-* classes for the hero + input frame; adds
10575
11383
  ag-cmp-* for agent-specific bits and ag-prev-* for the editable