1/** 2 * Annotations plugin — stylesheet. 3 * 4 * Colour tokens use DokuWiki's __xxx__ replacement syntax so the theme 5 * controls the palette. Hard-coded colours are limited to the annotation- 6 * specific highlights (amber / green) which are intentionally opinionated. 7 * 8 * FF78 ESR safe: no :has(), :not() with selectors, aspect-ratio, container 9 * queries, or CSS nesting. 10 * 11 * The two highlight hues are driven by CSS custom properties that action.php 12 * injects from the color_open / color_resolved config (as "r,g,b" triplets); 13 * every fill/border/marker/pill tint below is that hue at a different opacity. 14 * The :root fallbacks here keep the built-in amber/green palette when the 15 * injected <style> is absent (e.g. annotations off, or a stripped template). 16 * 17 * NOTE: every rgba() that contains var() is LESS-escaped as ~"rgba(var(…), a)". 18 * DokuWiki compiles plugin CSS through lesserphp, which otherwise evaluates 19 * rgba() at compile time, reads var() as 0, and bakes the colour to #000000. 20 * The escape makes lesserphp emit the declaration verbatim so the browser 21 * resolves the custom property at render time. Keep new var()-based colours 22 * escaped the same way. 23 */ 24 25:root { 26 --ann-open-rgb: 245, 158, 11; /* amber — open / unresolved (config default) */ 27 --ann-resolved-rgb: 74, 222, 128; /* green — resolved (config default) */ 28} 29 30/* ========================================================================= 31 Highlight spans 32 ========================================================================= */ 33 34.ann-highlight-open { 35 background-color: ~"rgba(var(--ann-open-rgb), 0.35)"; /* amber-300 @ 35% */ 36 border-bottom: 2px solid ~"rgba(var(--ann-open-rgb), 0.7)"; 37 border-radius: 2px; 38 cursor: pointer; 39 transition: background-color 0.15s ease; 40} 41 42.ann-highlight-open:hover { 43 background-color: ~"rgba(var(--ann-open-rgb), 0.55)"; 44} 45 46.ann-highlight-resolved { 47 background-color: ~"rgba(var(--ann-resolved-rgb), 0.30)"; /* green-300 @ 30% */ 48 border-bottom: 2px solid ~"rgba(var(--ann-resolved-rgb), 0.6)"; 49 border-radius: 2px; 50 cursor: pointer; 51 transition: background-color 0.15s ease; 52} 53 54.ann-highlight-resolved:hover { 55 background-color: ~"rgba(var(--ann-resolved-rgb), 0.50)"; 56} 57 58/* ========================================================================= 59 Counter bar 60 ========================================================================= */ 61 62#ann-counter-bar { 63 display: flex; 64 align-items: center; 65 flex-wrap: wrap; 66 gap: 0.5em; 67 padding: 0.4em 0.75em; 68 margin-bottom: 0.75em; 69 background: __background_alt__; 70 border: 1px solid __border__; 71 border-radius: 4px; 72 color: __text__; 73} 74 75.ann-orphan-link { 76 color: __link__; 77 text-decoration: underline; 78 cursor: pointer; 79} 80 81/* ========================================================================= 82 Gutter markers 83 ========================================================================= */ 84 85/* Markers are appended to document.body as position:absolute elements so 86 that no template overflow:hidden can clip them. Top/left are set inline 87 via JS using getBoundingClientRect() + scroll offsets. All markers share 88 the same X position (left edge of the .page column) so they form a tidy 89 vertical column in the document margin. */ 90.ann-gutter-marker { 91 position: absolute; 92 padding: 0; 93 border: none; 94 background: none; 95 color: ~"rgba(var(--ann-open-rgb), 0.8)"; /* amber — open */ 96 cursor: pointer; 97 display: flex; 98 align-items: center; 99 justify-content: center; 100 z-index: 1000; 101 transition: color 0.15s ease, transform 0.12s ease; 102} 103 104/* Suppress any UA button background on all interactive states. */ 105.ann-gutter-marker:hover, 106.ann-gutter-marker:focus, 107.ann-gutter-marker:active { 108 background: none; 109 outline: none; 110 box-shadow: none; 111} 112 113.ann-gutter-marker:hover { 114 color: ~"rgba(var(--ann-open-rgb), 1)"; 115} 116 117.ann-gutter-marker[data-status="resolved"] { 118 color: ~"rgba(var(--ann-resolved-rgb), 0.8)"; /* green — resolved */ 119} 120 121.ann-gutter-marker[data-status="resolved"]:hover { 122 color: ~"rgba(var(--ann-resolved-rgb), 1)"; 123} 124 125/* ========================================================================= 126 Annotation panel 127 ========================================================================= */ 128 129.ann-panel { 130 margin: 0.75em 0 1em; 131 border: 1px solid __border__; 132 border-left: 3px solid ~"rgba(var(--ann-open-rgb), 0.7)"; 133 background: __background_alt__; 134 box-shadow: 0 2px 8px rgba(0,0,0,0.10); 135 contain: layout; 136} 137 138/* ========================================================================= 139 Thread entries (annotation + replies) 140 ========================================================================= */ 141 142.ann-thread-entry { 143 padding: 0.65em 0.85em; 144 border-bottom: 1px solid __border__; 145} 146 147.ann-thread-entry:last-of-type { 148 border-bottom: none; 149} 150 151/* Root annotation entry: lighter background so it stands out from the panel. */ 152.ann-thread-entry.ann-annotation { 153 background: __background__; 154} 155 156/* Reply entries: inset card with the same lighter background. */ 157.ann-reply { 158 margin-left: 1.5em; 159 background: __background__; 160 border-left: 2px solid __border__; 161} 162 163/* ========================================================================= 164 Meta row (avatar, author, time, status, close button) 165 ========================================================================= */ 166 167.ann-meta { 168 display: flex; 169 align-items: center; 170 gap: 0.4em; 171 margin-bottom: 0.35em; 172 flex-wrap: wrap; 173} 174 175.ann-avatar { 176 display: inline-flex; 177 align-items: center; 178 justify-content: center; 179 width: 1.8em; 180 height: 1.8em; 181 border-radius: 50%; 182 background: __link__; 183 color: #fff; 184 font-size: 0.75em; 185 font-weight: 700; 186 flex-shrink: 0; 187} 188 189.ann-author { 190 font-weight: 600; 191 color: __text__; 192} 193 194.ann-time { 195 color: __text_alt__; 196 font-size: 0.85em; 197} 198 199.ann-status { 200 display: inline-block; 201 padding: 0.1em 0.45em; 202 border-radius: 10em; 203 font-size: 0.78em; 204 font-weight: 600; 205 letter-spacing: 0.02em; 206} 207 208.ann-status-open { 209 background: ~"rgba(var(--ann-open-rgb), 0.25)"; 210 color: #92400e; 211 border: 1px solid ~"rgba(var(--ann-open-rgb), 0.5)"; 212} 213 214.ann-status-resolved { 215 background: ~"rgba(var(--ann-resolved-rgb), 0.25)"; 216 color: #166534; 217 border: 1px solid ~"rgba(var(--ann-resolved-rgb), 0.4)"; 218} 219 220/* ========================================================================= 221 Body text and quoted selection 222 ========================================================================= */ 223 224.ann-body { 225 white-space: pre-wrap; 226 word-break: break-word; 227 color: __text__; 228 margin-bottom: 0.4em; 229} 230 231.ann-quote { 232 margin-bottom: 0.65em; 233 padding: 0.25em 0.6em; 234 border-left: 3px solid ~"rgba(var(--ann-open-rgb), 0.6)"; 235 color: __text__; 236 font-style: italic; 237 font-size: 0.9em; 238 background: ~"rgba(var(--ann-open-rgb), 0.08)"; 239 border-radius: 0 2px 2px 0; 240} 241 242/* ========================================================================= 243 Action buttons row 244 ========================================================================= */ 245 246.ann-actions { 247 display: flex; 248 gap: 0.5em; 249 flex-wrap: wrap; 250 margin-top: 0.65em; 251} 252 253.ann-btn { 254 display: inline-block; 255 padding: 0.2em 0.55em; 256 font-size: 0.85em; 257 border: 1px solid __border__; 258 border-radius: 3px; 259 background: __background__ !important; 260 color: __text__; 261 cursor: pointer; 262 line-height: 1.4; 263 transition: background-color 0.12s ease; 264} 265 266.ann-btn:hover { 267 background: __background_alt__ !important; 268} 269 270.ann-btn-primary { 271 background: __link__ !important; 272 border-color: __link__; 273 color: #fff; 274} 275 276.ann-btn-primary:hover { 277 background: __link__ !important; 278 color: #fff; 279 opacity: 0.88; 280} 281 282/* Disabled state: prevent UA-stylesheet background overrides and ensure 283 primary buttons keep their link colour. */ 284.ann-btn:disabled, 285.ann-btn[disabled] { 286 background: __background__; 287 opacity: 0.55; 288 cursor: not-allowed; 289} 290 291.ann-btn:disabled:hover, 292.ann-btn[disabled]:hover { 293 background: __background__; 294} 295 296.ann-btn-primary:disabled, 297.ann-btn-primary[disabled] { 298 background: __link__; 299 color: #fff; 300} 301 302.ann-btn-primary:disabled:hover, 303.ann-btn-primary[disabled]:hover { 304 background: __link__; 305 opacity: 0.55; 306} 307 308/* Spinner shown while an AJAX request is in flight (set by setBusy()). 309 The translate(-50%,-50%) is baked into every keyframe so it stays perfectly 310 centred regardless of sub-pixel rounding and never jigles. */ 311@keyframes ann-spin { 312 from { transform: translate(-50%, -50%) rotate(0deg); } 313 to { transform: translate(-50%, -50%) rotate(360deg); } 314} 315 316.ann-btn-busy { 317 position: relative; 318 color: transparent; 319} 320 321.ann-btn-busy::after { 322 content: ''; 323 position: absolute; 324 top: 50%; 325 left: 50%; 326 width: 0.75em; 327 height: 0.75em; 328 border: 2px solid rgba(0, 0, 0, 0.25); 329 border-top-color: rgba(0, 0, 0, 0.75); 330 border-radius: 50%; 331 animation: ann-spin 0.6s linear infinite; 332} 333 334.ann-btn-primary.ann-btn-busy::after { 335 border-color: rgba(255, 255, 255, 0.35); 336 border-top-color: rgba(255, 255, 255, 0.9); 337} 338 339.ann-btn-danger { 340 border-color: #dc2626; 341 color: #dc2626; 342} 343 344.ann-btn-danger:hover { 345 background: rgba(220, 38, 38, 0.08); 346} 347 348.ann-btn-admin { 349 border-color: __border__; 350 color: __text__; 351} 352 353/* Close button — lives inside .ann-meta, pushed right via margin-left:auto (set in JS). */ 354.ann-close { 355 font-size: 1.35em; 356 line-height: 1; 357 padding: 0.05em 0.3em; 358 border: none; 359 background: none !important; 360 color: __text_alt__; 361 cursor: pointer; 362 flex-shrink: 0; 363} 364 365.ann-close:hover { 366 color: __text__; 367 background: none !important; 368} 369 370/* ========================================================================= 371 Reply form + new-annotation form 372 ========================================================================= */ 373 374.ann-reply-form, 375.ann-new-form { 376 padding: 0.65em 0.85em; 377} 378 379.ann-new-form { 380 margin: 0.75em 0 1em; 381 border: 1px solid __border__; 382 border-left: 3px solid ~"rgba(var(--ann-open-rgb), 0.7)"; 383 background: __background_alt__; 384 contain: layout; 385} 386 387.ann-body-input { 388 display: block; 389 width: 100%; 390 box-sizing: border-box; 391 padding: 0.4em 0.6em; 392 font: inherit; 393 border: 1px solid __border__; 394 background: __background__; 395 color: __text__; 396 resize: vertical; 397 margin-bottom: 0.65em; 398} 399 400.ann-body-input:focus { 401 outline: 1px solid __link__; 402} 403 404.ann-form-row { 405 display: flex; 406 gap: 0.4em; 407} 408 409.ann-form-row + .ann-quote { 410 margin-top: 0.65em; 411} 412 413/* ========================================================================= 414 Selection tooltip 415 ========================================================================= */ 416 417.ann-tooltip { 418 position: absolute; 419 z-index: 9000; 420 border-radius: 4px; 421 box-shadow: 0 2px 8px rgba(0,0,0,0.15); 422} 423 424/* Static amber glow drawing the eye to the freshly-revealed "Annotate" button. 425 The rgba() is LESS-escaped (~"…") so DokuWiki's CSS compiler passes it through 426 verbatim instead of evaluating var() to black; the browser resolves the 427 custom property at render time. FF78 ESR safe. */ 428.ann-tooltip .ann-btn { 429 box-shadow: 0 0 8px 2px ~"rgba(var(--ann-open-rgb), 0.45)", 0 1px 4px rgba(0,0,0,0.25); 430} 431 432/* ========================================================================= 433 Orphan drawer 434 ========================================================================= */ 435 436.ann-orphan-drawer { 437 display: flow-root; /* BFC: shrinks to avoid overlapping the floated TOC */ 438 margin-bottom: 0.65em; 439 padding: 0.75em 1em; 440 border: 1px dashed __border__; 441 border-radius: 4px; 442 background: __background_alt__; 443} 444 445.ann-orphan-drawer h4 { 446 margin: 0 0 0.3em; 447 font-size: 0.95em; 448 color: __text__; 449} 450 451.ann-orphan-note { 452 font-size: 0.85em; 453 color: __text__; 454 margin-bottom: 0.75em; 455} 456 457/* ========================================================================= 458 Resolved annotation panels: shift to green accent 459 ========================================================================= */ 460 461.ann-panel[data-status="resolved"] { 462 border-left-color: ~"rgba(var(--ann-resolved-rgb), 0.6)"; 463} 464