torPreferences.css (26450B)
1 @import url("chrome://global/skin/tor-colors.css"); 2 3 #category-connection > .category-icon { 4 list-style-image: url("chrome://global/content/torconnect/tor-connect.svg"); 5 } 6 7 /* Make a button appear disabled, whilst still allowing it to keep keyboard 8 * focus. 9 * TODO: Replace with moz-button when it handles this for us. See 10 * tor-browser#43275. */ 11 button.spoof-button-disabled { 12 /* Borrow the :disabled rule from common-shared.css */ 13 opacity: 0.4; 14 /* Also ensure it does not get hover or active styling. */ 15 pointer-events: none; 16 } 17 18 .tor-loading-icon { 19 width: 16px; 20 height: 16px; 21 -moz-context-properties: fill; 22 /* Use --tor-text-color. This will have good contrast for this small icon 23 * against the background. And it will match the surrounding text for high 24 * contrast and forced colour themes. */ 25 fill: var(--tor-text-color); 26 content: url("chrome://global/skin/icons/loading.svg"); 27 } 28 29 .tor-toggle { 30 margin-block: 16px; 31 width: max-content; 32 } 33 34 /* Status */ 35 36 #network-status-internet-area { 37 margin-block: 16px; 38 } 39 40 #network-status-tor-area { 41 margin-block: 0 32px; 42 } 43 44 .network-status-area { 45 display: flex; 46 align-items: center; 47 white-space: nowrap; 48 } 49 50 .network-status-area > * { 51 flex: 0 0 auto; 52 } 53 54 .network-status-icon { 55 width: 18px; 56 height: 18px; 57 margin-inline-end: 8px; 58 -moz-context-properties: fill, stroke; 59 fill: var(--icon-color); 60 stroke: var(--icon-color); 61 } 62 63 #network-status-internet-area .network-status-icon { 64 content: url("chrome://browser/content/torpreferences/network.svg"); 65 } 66 67 #network-status-internet-area.status-offline .network-status-icon { 68 content: url("chrome://browser/content/torpreferences/network-broken.svg"); 69 } 70 71 #network-status-tor-area .network-status-icon { 72 content: url("chrome://global/content/torconnect/tor-connect.svg"); 73 } 74 75 #network-status-tor-area:not(.status-connected) .network-status-icon { 76 content: url("chrome://global/content/torconnect/tor-connect-broken.svg"); 77 } 78 79 #network-status-tor-area.status-blocked .network-status-icon { 80 /* Same as .tor-connect-status-potentially-blocked. */ 81 stroke: var(--icon-color-critical); 82 } 83 84 .network-status-label { 85 font-weight: var(--font-weight-bold); 86 margin-inline-end: 0.75em; 87 } 88 89 .network-status-result { 90 margin-inline-end: 0.75em; 91 } 92 93 #network-status-tor-area.status-connected #network-status-tor-connect-button { 94 /* Hide button when already connected. */ 95 display: none; 96 } 97 98 /* Bridge settings */ 99 100 .tor-medium-heading { 101 /* Same font size as mozilla preferences h2. */ 102 font-size: var(--font-size-large); 103 font-weight: var(--font-weight-bold); 104 margin: 0; 105 } 106 107 .tor-small-heading { 108 font-size: inherit; 109 font-weight: var(--font-weight-bold); 110 margin: 0; 111 } 112 113 /* Hide the tor-search-heading elements when the group's search header is 114 * hidden. These only appear in search results. 115 * See tor-browser#43320. 116 * NOTE: `.search-header[hidden] ~ :is(* .tor-search-heading)` will not match 117 * (possibly because the `~` selector is unsure how to integrate with the 118 * non-compound `* .tor-search-heading` selector). So we need to duplicate the 119 * `.search-header[hidden]` rule. */ 120 #torPreferences-bridges-group :is(.search-header[hidden] ~ * .tor-search-heading, .search-header[hidden] ~ .tor-search-heading) { 121 display: none; 122 } 123 124 /* Hide the tor-non-search-heading elements when the group's search header is 125 * not hidden. These only appear outside of search results. 126 * See tor-browser#43320. */ 127 #torPreferences-bridges-group :is(.search-header:not([hidden]) ~ * .tor-non-search-heading, .search-header:not([hidden]) ~ .tor-non-search-heading) { 128 display: none; 129 } 130 131 .tor-focusable-heading { 132 /* Do not occupy more horizontal space than necessary. */ 133 width: fit-content; 134 } 135 136 .tor-focusable-heading:focus-visible { 137 outline-offset: var(--focus-outline-offset); 138 } 139 140 .bridge-status-badge { 141 display: flex; 142 min-width: max-content; 143 align-items: center; 144 gap: 0.5em; 145 font-size: var(--font-size-small); 146 } 147 148 .bridge-status-badge:not(.bridge-status-connected, .bridge-status-none, .bridge-status-current-built-in) { 149 display: none; 150 } 151 152 @media not ((forced-colors) or (prefers-contrast)) { 153 /* Accent colors are usually only used for background colors. Here we are 154 * using it for text colors, so we only enable these rules when not using a 155 * high contrast theme or forced colors. */ 156 .bridge-status-badge.bridge-status-connected { 157 color: var(--tor-text-color); 158 } 159 160 .bridge-status-badge.bridge-status-current-built-in { 161 color: var(--color-accent-primary); 162 } 163 } 164 165 .bridge-status-badge > * { 166 flex: 0 0 auto; 167 } 168 169 .bridge-status-icon { 170 width: 16px; 171 height: 16px; 172 background-repeat: no-repeat; 173 background-position: center center; 174 -moz-context-properties: fill; 175 fill: currentColor; 176 } 177 178 .bridge-status-badge:is(.bridge-status-connected, .bridge-status-current-built-in) .bridge-status-icon { 179 background-image: url("chrome://global/skin/icons/check.svg"); 180 } 181 182 .bridge-status-badge.bridge-status-none .bridge-status-icon { 183 /* Hide the icon. */ 184 display: none; 185 } 186 187 #tor-bridges-update-area { 188 /* Still accessible to screen reader, but not visual. */ 189 position: absolute; 190 clip-path: inset(50%); 191 } 192 193 #torPreferences-bridges-group:not(.bridges-initialized) { 194 /* Hide bridge settings whilst not initialized. */ 195 display: none; 196 } 197 198 #tor-bridges-none, 199 #tor-bridges-current { 200 margin-inline: 0; 201 margin-block: 32px; 202 } 203 204 #tor-bridges-none:not([hidden]) { 205 display: grid; 206 justify-items: center; 207 text-align: center; 208 padding-block: 64px; 209 padding-inline: 32px; 210 gap: 16px; 211 border-radius: var(--border-radius-small); 212 color: var(--text-color-deemphasized); 213 border: 2px dashed var(--border-color-deemphasized); 214 } 215 216 #tor-bridges-none-icon { 217 width: 20px; 218 height: 20px; 219 content: url("chrome://browser/content/torpreferences/bridge.svg"); 220 -moz-context-properties: fill; 221 fill: currentColor; 222 } 223 224 .tor-bridges-box, 225 .tor-bridges-details-box { 226 padding: 16px; 227 border-radius: var(--border-radius-small); 228 background: var(--background-color-box-info); 229 border: 1px solid var(--border-color); 230 } 231 232 @media not forced-colors { 233 .tor-bridges-box { 234 border-color: transparent; 235 } 236 } 237 238 #tor-bridges-current-header-bar { 239 display: grid; 240 min-width: max-content; 241 grid-template: "heading source button" min-content / max-content 1fr max-content; 242 align-items: center; 243 border-block-end: 1px solid var(--border-color); 244 padding-block-end: 16px; 245 margin-block-end: 16px; 246 white-space: nowrap; 247 } 248 249 .tor-bridges-current-heading { 250 grid-area: heading; 251 } 252 253 .tor-bridges-source-label { 254 margin-inline-start: 2em; 255 margin-inline-end: 8px; 256 grid-area: source; 257 justify-self: end; 258 } 259 260 #tor-bridges-all-options-button { 261 grid-area: button; 262 } 263 264 #tor-bridges-lox-label:not([hidden]) { 265 display: flex; 266 align-items: center; 267 gap: 6px; 268 } 269 270 #tor-bridges-lox-label > * { 271 flex: 0 0 auto; 272 } 273 274 #tor-bridges-lox-label-icon { 275 content: url("chrome://browser/content/torpreferences/lox-bridge-pass.svg"); 276 width: 16px; 277 height: 16px; 278 -moz-context-properties: fill; 279 fill: var(--icon-color); 280 } 281 282 .tor-bridges-options-button { 283 padding: 3px; 284 margin: 0; 285 min-height: auto; 286 min-width: auto; 287 box-sizing: content-box; 288 width: 16px; 289 height: 16px; 290 background-image: url("chrome://global/skin/icons/more.svg"); 291 background-repeat: no-repeat; 292 background-position: center center; 293 background-origin: content-box; 294 background-size: contain; 295 -moz-context-properties: fill; 296 fill: currentColor; 297 } 298 299 #tor-bridges-built-in-display:not([hidden]) { 300 display: grid; 301 grid-template: 302 "type status" min-content 303 "description description" auto 304 / max-content 1fr; 305 gap: 12px 1.5em; 306 margin-block-end: 16px; 307 } 308 309 #tor-bridges-built-in-type-name { 310 font-weight: var(--font-weight-bold); 311 grid-area: type; 312 } 313 314 #tor-bridges-built-in-connected { 315 grid-area: status; 316 justify-self: end; 317 } 318 319 #tor-bridges-built-in-description { 320 grid-area: description; 321 } 322 323 .tor-bridges-grid:not([hidden]) { 324 display: grid; 325 grid-template-columns: max-content repeat(4, max-content) 1fr; 326 --tor-bridges-grid-column-gap: 8px; 327 --tor-bridges-grid-column-short-gap: 4px; 328 /* For #tor-bridges-grid-display we want each grid item to have the same 329 * height so that their focus outlines match. */ 330 align-items: stretch; 331 } 332 333 .tor-bridges-grid-row { 334 /* We want each row to act as a row of three items in the 335 * .tor-bridges-grid grid layout. 336 * We also want a 16px spacing between rows, and 8px spacing between columns, 337 * which are outside the .tor-bridges-grid-cell's border area. 338 * 339 * For #tor-bridges-grid-display this should ensure that clicking these gaps 340 * will not focus any item, and their focus outlines do not overlap. 341 * Moreover, we also want each row to show its .tor-bridges-options-cell when 342 * the .tor-bridges-grid-row has :hover. 343 * 344 * We could use "display: contents" on the row and set a "gap: 16px 8px" on 345 * the parent so that its items fall into the parent layout. However, the gap 346 * between the items would mean there are places where no row has :hover. So 347 * if the user glided across the grid, the options button would visibly 348 * disappear any time the pointer entered a gap, causing the display to feel 349 * "jumpy". 350 * 351 * Instead, we use a "subgrid" layout for each .tor-bridges-grid-row, and 352 * using padding, rather than a gap, for the vertical spacing. Therefore, 353 * every part of the grid is covered by a row, so moving the pointer over the 354 * grid will always have one row with :hover, so one of the options cell will 355 * always be visible. 356 */ 357 display: grid; 358 grid-column: 1 / -1; 359 grid-template-columns: subgrid; 360 /* Add 16px gap between rows, plus 8px at the start and end of the grid. */ 361 padding-block: 8px; 362 } 363 364 #tor-bridges-grid-display .tor-bridges-grid-cell:focus-visible { 365 /* #tor-bridges-grid-display has focus management for its cells. */ 366 outline: var(--focus-outline); 367 outline-offset: var(--focus-outline-offset); 368 } 369 370 .tor-bridges-grid-cell { 371 /* The cell is stretched to the height of the row, so that each focus outline 372 * shares the same height, but we want to center-align the content within, 373 * which is either a single Element or a TextNode. */ 374 display: grid; 375 align-content: center; 376 } 377 378 .tor-bridges-type-cell { 379 margin-inline-end: var(--tor-bridges-grid-column-gap); 380 } 381 382 .tor-bridges-emojis-block { 383 /* Emoji block occupies four columns, but with a smaller gap. */ 384 display: contents; 385 } 386 387 .tor-bridges-emoji-cell:not(:last-child) { 388 margin-inline-end: var(--tor-bridges-grid-column-short-gap); 389 } 390 391 .tor-bridges-emoji-icon { 392 display: block; 393 box-sizing: content-box; 394 width: 16px; 395 height: 16px; 396 /* color-light-gray-10, color-dark-gray-60 */ 397 background: light-dark(#f9f9fb, #2b2a33); 398 border-radius: var(--border-radius-small); 399 padding: 8px; 400 } 401 402 .tor-bridges-grid-end-block { 403 /* The last three cells all share a single grid item slot in the 404 * #tor-bridges-grid-display layout. 405 * This is because we do not want to align its cells between rows. */ 406 min-width: max-content; 407 display: flex; 408 /* Choose "stretch" instead of "center" so that focus outline is a consistent 409 * height between cells. */ 410 align-items: stretch; 411 margin-inline-start: var(--tor-bridges-grid-column-gap); 412 gap: var(--tor-bridges-grid-column-gap); 413 } 414 415 .tor-bridges-address-cell { 416 /* base size */ 417 width: 10em; 418 flex: 1 0 auto; 419 } 420 421 .tor-bridges-address-cell-text { 422 white-space: nowrap; 423 overflow: hidden; 424 text-overflow: ellipsis; 425 color: var(--text-color-deemphasized); 426 } 427 428 .tor-bridges-status-cell, 429 .tor-bridges-options-cell { 430 flex: 0 0 auto; 431 } 432 433 /* Hide the options button if the row does not have hover or focus. */ 434 .tor-bridges-grid-row:not( 435 :hover, 436 :focus-within 437 ) .tor-bridges-options-cell, 438 /* Hide the status cell when it shows "No status" if the cell does not have 439 * focus. */ 440 .tor-bridges-grid-row.hide-status .tor-bridges-status-cell:not(:focus) { 441 /* Still accessible to screen reader, but not visual and does not contribute 442 * to the parent flex layout. */ 443 /* NOTE: We assume that the height of these cell's content is equal to or less 444 * than the other cells, so there won't be a jump in row height when they 445 * become visual again and contribute to the layout. */ 446 position: absolute; 447 clip-path: inset(50%); 448 } 449 450 .tor-bridges-details-box { 451 margin-block-start: 24px; 452 } 453 454 #tor-bridges-share:not([hidden]) { 455 display: grid; 456 grid-template: 457 "heading heading heading" min-content 458 /* If the description spans one line, it will be center-aligned with the 459 * buttons, otherwise it will start to expand upwards. */ 460 "description . ." 1fr 461 "description copy qr" min-content 462 / 1fr max-content max-content; 463 gap: 0 8px; 464 align-items: center; 465 } 466 467 .tor-bridges-share-heading { 468 grid-area: heading; 469 margin-block-end: 4px; 470 } 471 472 #tor-bridges-share-description { 473 grid-area: description; 474 } 475 476 #tor-bridges-copy-addresses-button { 477 grid-area: copy; 478 margin: 0; 479 /* Match the QR height if it is higher than ours. */ 480 min-height: auto; 481 align-self: stretch; 482 } 483 484 #tor-bridges-qr-addresses-button { 485 grid-area: qr; 486 padding: 5px; 487 margin: 0; 488 min-height: auto; 489 min-width: auto; 490 box-sizing: content-box; 491 width: 24px; 492 height: 24px; 493 background-image: url("chrome://browser/content/torpreferences/bridge-qr.svg"); 494 background-repeat: no-repeat; 495 background-position: center center; 496 background-origin: content-box; 497 background-size: contain; 498 -moz-context-properties: fill; 499 fill: currentColor; 500 } 501 502 #tor-bridges-lox-status { 503 margin-block-start: 8px; 504 } 505 506 .tor-bridges-lox-box:not([hidden]) { 507 display: grid; 508 grid-template: 509 "image intro intro" min-content 510 ". list list" auto 511 ". invites button" min-content 512 / min-content 1fr max-content; 513 align-items: start; 514 gap: 8px; 515 } 516 517 .tor-bridges-lox-image-outer { 518 grid-area: image; 519 /* The ring is 36px by 36px, but has 4px of padding for a Gaussian blur. */ 520 width: 44px; 521 height: 44px; 522 margin: -4px; 523 align-self: center; 524 justify-self: center; 525 /* fill is the progress, stroke is the empty ring. */ 526 -moz-context-properties: fill, stroke; 527 fill: var(--icon-color-success); 528 stroke: var(--border-color); 529 content: url("chrome://browser/content/torpreferences/lox-progress-ring.svg"); 530 } 531 532 #tor-bridges-lox-unlock-alert.lox-unlock-upgrade .tor-bridges-lox-image-outer { 533 content: url("chrome://browser/content/torpreferences/lox-complete-ring.svg"); 534 } 535 536 .tor-bridges-lox-image-inner { 537 grid-area: image; 538 /* Extra 4px space for gaussian blur. */ 539 width: 16px; 540 height: 16px; 541 align-self: center; 542 justify-self: center; 543 -moz-context-properties: fill; 544 fill: var(--icon-color); 545 } 546 547 #tor-bridges-lox-details .tor-bridges-lox-image-inner { 548 content: url("chrome://browser/content/torpreferences/lox-bridge-pass.svg"); 549 } 550 551 #tor-bridges-lox-unlock-alert .tor-bridges-lox-image-inner { 552 content: url("chrome://browser/content/torpreferences/bridge.svg"); 553 } 554 555 #tor-bridges-lox-unlock-alert.lox-unlock-upgrade .tor-bridges-lox-image-inner { 556 content: url("chrome://browser/content/torpreferences/lox-success.svg"); 557 } 558 559 .tor-bridges-lox-intro { 560 grid-area: intro; 561 align-self: center; 562 justify-self: start; 563 } 564 565 .tor-bridges-lox-list { 566 grid-area: list; 567 margin: 0; 568 padding: 0; 569 display: grid; 570 /* Align the icons, as if list markers. */ 571 grid-template-columns: max-content 1fr; 572 align-items: start; 573 gap: 8px 0; 574 } 575 576 .tor-bridges-lox-list-item:not([hidden]) { 577 display: contents; 578 } 579 580 .tor-bridges-lox-list-item:not([hidden])::before { 581 /* We use ::before rather than list-style-image to have more control. */ 582 box-sizing: content-box; 583 width: 18px; 584 height: 18px; 585 margin-inline: 4px 6px; 586 /* We want the icons to be center-aligned relative to the *first* line. */ 587 margin-block-start: calc((1lh - 18px) / 2); 588 /* We use display: grid rather than display: block. Otherwise the content will 589 * be offset vertically by the line-height. */ 590 display: grid; 591 /* fill is the icon color, stroke is the border color. */ 592 -moz-context-properties: fill, stroke; 593 fill: var(--icon-color); 594 } 595 596 .tor-bridges-lox-list-item-bridge::before { 597 content: url("chrome://browser/content/torpreferences/lox-bridge-icon.svg"); 598 } 599 600 .tor-bridges-lox-list-item-invite::before { 601 content: url("chrome://browser/content/torpreferences/lox-invite-icon.svg"); 602 } 603 604 #tor-bridges-lox-details .tor-bridges-lox-list-item::before { 605 stroke: var(--border-color); 606 } 607 608 #tor-bridges-lox-unlock-alert .tor-bridges-lox-list-item::before { 609 stroke: var(--icon-color-success); 610 } 611 612 #tor-bridges-lox-remaining-invites { 613 grid-area: invites; 614 justify-self: end; 615 align-self: center; 616 } 617 618 .tor-bridges-lox-button { 619 grid-area: button; 620 margin: 0; 621 align-self: center; 622 } 623 624 .tor-bridges-provider-heading { 625 margin-block: 48px 8px; 626 } 627 628 #tor-bridges-provider-area { 629 display: grid; 630 grid-template-columns: 1fr 1fr; 631 gap: 16px; 632 align-items: start; 633 margin-block-start: 24px; 634 } 635 636 #tor-bridges-provider-list { 637 display: grid; 638 grid-template-columns: max-content max-content; 639 /* 24px gap between items. */ 640 gap: 24px 12px; 641 margin-block: 16px; 642 padding: 0; 643 } 644 645 .tor-bridges-provider-item { 646 grid-column: 1 / -1; 647 display: grid; 648 grid-template-columns: subgrid; 649 align-items: center; 650 justify-items: start; 651 /* 8px gap between the name and instruction. */ 652 gap: 8px 12px; 653 } 654 655 .tor-bridges-provider-icon { 656 width: 16px; 657 height: 16px; 658 -moz-context-properties: fill; 659 fill: var(--icon-color); 660 } 661 662 #tor-bridges-provider-icon-telegram { 663 content: url("chrome://browser/content/torpreferences/telegram-logo.svg"); 664 } 665 666 #tor-bridges-provider-icon-web { 667 content: url("chrome://browser/content/torpreferences/network.svg"); 668 } 669 670 #tor-bridges-provider-icon-email { 671 content: url("chrome://browser/content/torpreferences/mail.svg"); 672 } 673 674 .tor-bridges-provider-name { 675 font-weight: var(--font-weight-bold); 676 font-size: var(--font-size-small); 677 } 678 679 .tor-bridges-provider-instruction { 680 grid-column: 2 / 3; 681 } 682 683 #tor-bridges-request-box { 684 /* Take up the full height in the container. */ 685 align-self: stretch; 686 display: flex; 687 flex-direction: column; 688 align-items: center; 689 text-align: center; 690 justify-content: center; 691 } 692 693 #tor-bridges-request-box > * { 694 flex: 0 0 auto; 695 } 696 697 #tor-bridges-request-description { 698 margin-block: 12px 16px; 699 } 700 701 #tor-bridges-open-request-dialog-button { 702 margin: 0; 703 } 704 705 #torPreferences-bridges-location { 706 width: 280px; 707 } 708 709 #torPreferences-bridges-location menuitem[disabled="true"] { 710 color: var(--button-text-color, inherit); 711 font-weight: var(--font-weight-bold); 712 } 713 714 /* Request bridges */ 715 716 image#torPreferences-requestBridge-captchaImage { 717 margin: 16px 0 8px 0; 718 min-height: 140px; 719 } 720 721 button#torPreferences-requestBridge-refreshCaptchaButton { 722 min-width: initial; 723 } 724 725 #torPreferences-requestBridge-refreshCaptchaButton image { 726 -moz-context-properties: fill; 727 fill: currentColor; 728 } 729 730 #torPreferences-requestBridge-captchaTextbox { 731 flex: 1 0 auto; 732 } 733 734 dialog#torPreferences-requestBridge-dialog > hbox { 735 margin-bottom: 1em; 736 } 737 738 /* 739 Various elements that really should be lining up don't because they have inconsistent margins 740 */ 741 .torMarginFix { 742 margin-left: 4px; 743 margin-right: 4px; 744 } 745 746 /* Show bridge QR dialog */ 747 748 #bridgeQr { 749 flex: 0 0 auto; 750 align-self: center; 751 /* Some readers don't recognize QRs with inverted colors, so let's make 752 the ones are darker than zeroes. See 753 https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/41049 */ 754 --qr-one: black; 755 --qr-zero: white; 756 background: var(--qr-zero); 757 /* Padding is needed in case the dark theme is used so the bits don't blend 758 with whatever the default background color is. */ 759 padding: 10px; 760 margin-block: 4px 8px; 761 border-radius: var(--border-radius-small); 762 display: grid; 763 align-items: center; 764 justify-items: center; 765 grid-template: "qr" max-content / max-content; 766 } 767 768 #bridgeQr-target { 769 width: 300px; 770 height: 300px; 771 background: var(--qr-zero); 772 color: var(--qr-one); 773 grid-area: qr; 774 } 775 776 #bridgeQr-icon { 777 /* Share the same grid area as #bridgeQr-target. */ 778 grid-area: qr; 779 content: url("chrome://browser/content/torpreferences/bridge.svg"); 780 padding: 10px; 781 border-radius: var(--border-radius-medium); 782 box-sizing: content-box; 783 width: 52px; 784 height: 52px; 785 background: var(--qr-zero); 786 -moz-context-properties: fill; 787 fill: var(--qr-one); 788 } 789 790 /* Lox invite dialog */ 791 792 #lox-invite-dialog-generate-area { 793 flex: 0 0 auto; 794 display: grid; 795 grid-template: 796 ". remaining button" min-content 797 "message message message" auto 798 / 1fr max-content max-content; 799 gap: 8px; 800 margin-block: 16px 8px; 801 align-items: center; 802 } 803 804 #lox-invite-dialog-remaining { 805 grid-area: remaining; 806 } 807 808 #lox-invite-dialog-generate-button { 809 grid-area: button; 810 } 811 812 #lox-invite-dialog-message-area { 813 grid-area: message; 814 justify-self: end; 815 display: flex; 816 align-items: center; 817 } 818 819 #lox-invite-dialog-message-area::after { 820 /* Zero width space, to ensure we are always one line high. */ 821 content: "\200B"; 822 } 823 824 #lox-invite-dialog-error-message { 825 color: var(--text-color-error); 826 } 827 828 #lox-invite-dialog-generate-area:not(.show-error) #lox-invite-dialog-error-message { 829 display: none; 830 } 831 832 #lox-invite-dialog-connecting { 833 color: var(--text-color-deemphasized); 834 /* Gap with #user-provide-bridge-loading-icon. */ 835 margin-inline-start: 0.5em; 836 } 837 838 #lox-invite-dialog-generate-area:not(.show-connecting) #lox-invite-dialog-connecting { 839 display: none; 840 } 841 842 #lox-invite-dialog-loading-icon { 843 flex: 0 0 auto; 844 } 845 846 #lox-invite-dialog-generate-area:not(.show-connecting) #lox-invite-dialog-loading-icon { 847 /* Use width:0 to effectively hide, but still occupy vertical space. */ 848 width: 0; 849 } 850 851 #lox-invite-dialog-list-label { 852 font-weight: var(--font-weight-bold); 853 } 854 855 #lox-invite-dialog-list { 856 flex: 1 1 auto; 857 /* basis height */ 858 height: 10em; 859 margin-block: 8px; 860 } 861 862 .lox-invite-dialog-list-item { 863 white-space: nowrap; 864 overflow-x: hidden; 865 /* FIXME: ellipsis does not show. */ 866 text-overflow: ellipsis; 867 padding-block: 6px; 868 padding-inline: 8px; 869 } 870 871 /* Builtin bridge dialog */ 872 #torPreferences-builtinBridge-header { 873 margin: 8px 0 10px 0; 874 } 875 876 #torPreferences-builtinBridge-description { 877 margin-bottom: 18px; 878 } 879 880 #torPreferences-builtinBridge-typeSelection { 881 margin-bottom: 16px; 882 } 883 884 #torPreferences-builtinBridge-typeSelection radio label { 885 font-weight: var(--font-weight-bold); 886 } 887 888 /* Request bridge dialog */ 889 /* 890 This hbox is hidden by css here by default so that the 891 xul dialog allocates enough screen space for the error message 892 element, otherwise it gets cut off since dialog's overflow is hidden 893 */ 894 hbox#torPreferences-requestBridge-incorrectCaptchaHbox { 895 visibility: hidden; 896 } 897 898 image#torPreferences-requestBridge-errorIcon { 899 list-style-image: url("chrome://global/skin/icons/warning.svg"); 900 -moz-context-properties: fill; 901 fill: var(--icon-color-warning); 902 } 903 904 groupbox#torPreferences-bridges-group textarea { 905 white-space: pre; 906 overflow: auto; 907 } 908 909 /* Provide bridge dialog */ 910 911 #user-provide-bridge-dialog:not(.show-entry-page) #user-provide-bridge-entry-page { 912 display: none; 913 } 914 915 #user-provide-bridge-dialog:not(.show-result-page) #user-provide-bridge-result-page { 916 display: none; 917 } 918 919 #user-provide-bridge-entry-page { 920 flex: 1 0 auto; 921 display: flex; 922 flex-direction: column; 923 } 924 925 #user-provide-bridge-description { 926 flex: 0 0 auto; 927 } 928 929 #user-provide-bridge-textarea-label { 930 margin-block: 16px 6px; 931 flex: 0 0 auto; 932 align-self: start; 933 } 934 935 #user-provide-bridge-textarea { 936 flex: 1 0 auto; 937 align-self: stretch; 938 /* Only expect ASCII input, so can set a line-height. */ 939 line-height: 1.3; 940 margin: 0; 941 } 942 943 #user-provide-bridge-message-area { 944 flex: 0 0 auto; 945 margin-block: 8px 12px; 946 align-self: end; 947 display: flex; 948 align-items: center; 949 } 950 951 #user-provide-bridge-message-area::after { 952 /* Zero width space, to ensure we are always one line high. */ 953 content: "\200B"; 954 } 955 956 #user-provide-bridge-textarea.invalid-input { 957 border-color: var(--outline-color-error); 958 outline-color: var(--outline-color-error); 959 } 960 961 #user-provide-bridge-error-message { 962 color: var(--text-color-error); 963 } 964 965 #user-provide-bridge-dialog:not(.show-error) #user-provide-bridge-error-message { 966 display: none; 967 } 968 969 #user-provide-bridge-connecting { 970 color: var(--text-color-deemphasized); 971 /* Gap with #user-provide-bridge-loading-icon. */ 972 margin-inline-start: 0.5em; 973 } 974 975 #user-provide-bridge-dialog:not(.show-connecting) #user-provide-bridge-connecting { 976 display: none; 977 } 978 979 #user-provide-bridge-loading-icon { 980 flex: 0 0 auto; 981 } 982 983 #user-provide-bridge-dialog:not(.show-connecting) #user-provide-bridge-loading-icon { 984 /* Use width:0 to effectively hide, but still occupy vertical space. */ 985 width: 0; 986 } 987 988 #user-provide-bridge-result-page { 989 flex: 1 1 0; 990 min-height: 0; 991 display: flex; 992 flex-direction: column; 993 } 994 995 #user-provide-result-description { 996 flex: 0 0 auto; 997 } 998 999 #user-provide-bridge-grid-display { 1000 flex: 0 1 auto; 1001 overflow: auto; 1002 margin-block: 8px; 1003 } 1004 1005 #user-provide-bridge-grid-display:focus-visible { 1006 outline: var(--focus-outline); 1007 outline-offset: var(--focus-outline-offset); 1008 } 1009 1010 /* Connection settings dialog */ 1011 #torPreferences-connection-dialog label { 1012 /* Do not wrap the labels. */ 1013 white-space: nowrap; 1014 } 1015 1016 #torPreferences-connection-header { 1017 margin: 4px 0 14px 0; 1018 } 1019 1020 #torPreferences-connection-grid { 1021 display: grid; 1022 grid-template-columns: auto 1fr; 1023 } 1024 1025 #torPreferences-localProxy-textboxAddress, 1026 #torPreferences-localProxy-textboxUsername, 1027 #torPreferences-localProxy-textboxPassword, 1028 #torPreferences-connection-textboxAllowedPorts { 1029 flex: 1 0 auto; 1030 } 1031 1032 #torPreferences-connection-firewall { 1033 display: flex; 1034 } 1035 1036 #torPreferences-connection-hboxAllowedPorts { 1037 flex: 1; 1038 } 1039 1040 /* Tor logs dialog */ 1041 #tor-log-table { 1042 flex: 1 0 auto; 1043 overflow: auto; 1044 min-height: 20em; 1045 height: 20em; 1046 display: flex; 1047 flex-direction: column; 1048 padding: var(--space-small); 1049 margin-block-end: 4px; 1050 border: 1px solid var(--border-color); 1051 border-radius: var(--border-radius-small); 1052 font-size: var(--font-size-small); 1053 } 1054 1055 #tor-log-body, 1056 #tor-log-table tr { 1057 display: contents; 1058 } 1059 1060 #tor-log-table td { 1061 flex: 0 0 auto; 1062 padding: 0; 1063 } 1064 1065 #tor-log-table td.time { 1066 color: var(--text-color-deemphasized); 1067 margin-block-end: var(--space-xsmall); 1068 } 1069 1070 #tor-log-table td.message { 1071 overflow-wrap: anywhere; 1072 } 1073 1074 #tor-log-table tr:not(:last-of-type) td.message { 1075 margin-block-end: var(--space-medium); 1076 }