tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }