/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
 * Rules for everything related to XUL except scrollbars can be found in this
 * file.
 *
 * This file should also not contain any app specific styling.  Defaults for
 * widgets of a particular application should be in that application's style
 * sheet.  For example, style definitions for browser can be found in
 * browser.css.
 */

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
@namespace html url("http://www.w3.org/1999/xhtml"); /* namespace for HTML elements */

* {
  -moz-user-focus: ignore;
  display: flex;
  box-sizing: border-box;
}

/* hide the content and destroy the frame */
[hidden="true"] {
  display: none;
}

/* hide the content, but don't destroy the frames */
[collapsed="true"] {
  visibility: collapse;
}

:root {
  text-rendering: optimizeLegibility;
  -moz-control-character-visibility: visible;
  -moz-box-collapse: legacy;
  width: 100%;
  height: 100%;
  user-select: none;
}

:root:-moz-locale-dir(rtl) {
  direction: rtl;
}

/* XUL doesn't show outlines by default */
:focus-visible {
  outline: initial;
}

/*
 * Native anonymous popups and tooltips in html are document-level, which means
 * that they don't inherit from the root, so this is needed.
 */
popupgroup:-moz-native-anonymous:-moz-locale-dir(rtl),
tooltip:-moz-native-anonymous:-moz-locale-dir(rtl) {
  direction: rtl;
}

/* ::::::::::
   :: Rules for forcing direction for entry and display of URIs
   :: or URI elements
   ::::: */

.uri-element {
  direction: ltr !important;
}

/****** elements that have no visual representation ******/

script, data, commandset, command,
broadcasterset, broadcaster, observes,
keyset, key, toolbarpalette, template,
treeitem, treeseparator, treerow, treecell {
  display: none;
}

/********** focus rules **********/

button,
checkbox,
menulist,
radiogroup,
richlistbox,
tree,
browser,
editor,
iframe,
label:is(.text-link, [onclick]),
tab[selected="true"]:not([ignorefocus="true"]) {
  -moz-user-focus: normal;
}

/* Avoid losing focus on tabs by keeping them focusable, since some browser
 * tests rely on this.
 *
 * TODO(emilio): Remove this and fix the tests / front-end code:
 *  * browser/base/content/test/general/browser_tabfocus.js
 */
tab:focus {
  -moz-user-focus: normal;
}

/******** window & page ******/

window {
  overflow: clip;
  flex-direction: column;
}

/******** box *******/

vbox {
  flex-direction: column;
}

/********** label **********/

label {
  display: inline-block;
}

description {
  display: flow-root;
}

label html|span.accesskey {
  text-decoration: underline;
  text-decoration-skip-ink: none;
}

description:where([value]) {
  /* Preserves legacy behavior, maybe could be removed */
  display: flex;
}

label:where([value]) {
  /* Preserves legacy behavior, maybe could be removed */
  display: inline-flex;
}

:is(label, description)[value] {
  white-space: nowrap;
}

:is(label, description)[value]::before {
  /* This displays the value attribute, along with the underlined
   * accesskey if needed */
  content: -moz-label-content;
  display: block;
}

label[value=""]::before {
  content: "\200b" !important; /* zwsp */
}

:is(label, description)[value][crop] {
  min-width: 0;
}

:is(label, description)[value][crop]::before {
  min-width: 0;
  max-width: 100%;
  /* This implements crop=end */
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Invert the direction to clip at the start rather than end */
:is(label, description)[value][crop="start"]::before {
  direction: rtl;
  /* Mark text as ltr to preserve punctuation/numeric order */
  content: "\200e" -moz-label-content;
}

:is(label, description)[value][crop="start"]:-moz-locale-dir(rtl)::before {
  direction: ltr;
  /* Mark text as rtl to preserve punctuation/numeric order */
  content: "\200f" -moz-label-content;
}

.checkbox-label-box,
.radio-label-box {
  min-width: 0;
}

/********** toolbarbutton **********/

toolbarbutton {
  align-items: center;
  justify-content: center;
}

toolbarbutton.tabbable {
  -moz-user-focus: normal !important;
}

toolbarbutton[crop] {
  min-width: 0;
}

.toolbarbutton-text {
  display: block;
  text-align: center;
}

toolbar[mode="icons"] .toolbarbutton-text,
toolbar[mode="text"] .toolbarbutton-icon,
html|label.toolbarbutton-badge:empty {
  display: none;
}

.toolbarbutton-icon,
.toolbarbutton-text,
.toolbarbutton-badge-stack,
.toolbarbutton-menu-dropmarker,
.treecol-text,
.treecol-sortdirection,
.menubar-left,
.menubar-text,
.menu-text,
.menu-iconic-text,
.menu-iconic-highlightable-text,
.menu-iconic-left,
.menu-right,
.menu-accel-container,
.button-box {
  /* Preserves legacy behavior */
  pointer-events: none;
}

/********** button **********/

button {
  -moz-default-appearance: button;
  appearance: auto;
}

dropmarker {
  -moz-default-appearance: -moz-menulist-arrow-button;
  appearance: auto;
}

/******** browser, editor, iframe ********/

browser,
editor,
iframe {
  display: inline;
}

/* Allow the browser to shrink below its intrinsic size, to match legacy
 * behavior */
browser {
  align-self: stretch;
  justify-self: stretch;
  min-height: 0;
  min-width: 0;
  contain: size;
}

/*********** popup notification ************/
popupnotification {
  flex-direction: column;
}

.popup-notification-menubutton:not([label]) {
  display: none;
}

/********** radio **********/

radiogroup {
  flex-direction: column;
}

/******** groupbox *********/

groupbox {
  flex-direction: column;
}

/******** draggable elements *********/

toolbar:not([nowindowdrag], [customizing]) {
  -moz-window-dragging: drag;
}

/* The list below is non-comprehensive and will probably need some tweaking. */
toolbaritem,
toolbarbutton,
toolbarseparator,
button,
search-textbox,
html|input,
tab,
radio,
splitter,
menu,
menulist {
  -moz-window-dragging: no-drag;
}

titlebar {
  pointer-events: auto !important;
}

/******* toolbar *******/

toolbox {
  flex-direction: column;
}

@media (-moz-platform: macos) {
  toolbar[type="menubar"] {
    min-height: 0 !important;
    border: 0 !important;
  }
}

toolbarspring {
  flex: 1000 1000;
}

/********* menu ***********/

menubar > menu:empty {
  visibility: collapse;
}

.menu-text {
  flex: 1;
}

/********* menupopup, panel, & tooltip ***********/

menupopup,
panel,
tooltip {
  position: fixed;
  -moz-top-layer: auto;
  width: fit-content;
  height: fit-content;
  /* Make sure that popups are interactable when shown, since they escape the
   * usual layering rules */
  -moz-inert: none;
  /* Popups can't have overflow */
  contain: paint;
  z-index: 2147483647;
  text-shadow: none;
}

tooltip {
  appearance: auto;
  -moz-default-appearance: tooltip;

  white-space: pre-wrap;

  background-color: InfoBackground;
  color: InfoText;
  font: message-box;
  padding: 2px 3px;
  max-width: 40em;
  overflow: clip;
  pointer-events: none;
}

/**
 * It's important that these styles are in a UA sheet, because the default
 * tooltip is native anonymous content
 */
@media (-moz-platform: linux) {
  tooltip {
    padding: 6px 10px; /* Matches Adwaita. */
    line-height: 1.4;  /* For Noto Sans; note that 1.2 may clip descenders. */
  }
}

@media (-moz-platform: macos) {
  tooltip {
    padding: 2px 6px; /* Matches native metrics. */
  }
}

@media (-moz-platform: windows) {
  tooltip {
    appearance: none;
    border: 1px solid;
  }

  /* TODO(emilio): Probably make InfoText/InfoBackground do the right thing and
   * remove this? */
  @media not (prefers-contrast) {
    tooltip {
      background-color: #f9f9fb;
      color: black;
      border-color: #67676c;
      border-radius: 4px;
    }

    @media (prefers-color-scheme: dark) {
      tooltip {
        background-color: #2b2a33;
        color: white;
        border-color: #f9f9fb;
      }
    }
  }
}

/******** tree ******/

treecolpicker {
  order: 2147483646;
}

treechildren {
  display: flex;
  flex: 1;
}

tree {
  flex-direction: column;
}

tree[hidecolumnpicker="true"] treecolpicker {
  display: none;
}

treecol {
  min-width: 16px;
  /* This preserves the behavior of -moz-box-ordinal-group. To change this we'd
   * need to migrate the persisted ordinal values etc. */
  order: 1;
}

treecol[hidden="true"] {
  visibility: collapse;
  display: flex;
}

/* ::::: lines connecting cells ::::: */
tree:not([treelines="true"]) treechildren::-moz-tree-line {
  visibility: hidden;
}

treechildren::-moz-tree-cell(ltr) {
  direction: ltr !important;
}

/********** deck, tabpanels & stack *********/

tabpanels > *|*:not(:-moz-native-anonymous) {
  /* tabpanels is special: we want to avoid displaying them, but we still want
   * the hidden children to be accessible */
  -moz-subtree-hidden-only-visually: 1;
}

deck > *|*:not(:-moz-native-anonymous) {
  visibility: hidden;
}

tabpanels > .deck-selected,
deck > .deck-selected {
  -moz-subtree-hidden-only-visually: 0;
  visibility: inherit;
}

tabpanels,
deck,
stack {
  display: grid;
  position: relative;
}

/* We shouldn't style native anonymous children like scrollbars or what not. */
tabpanels > *|*:not(:-moz-native-anonymous),
deck > *|*:not(:-moz-native-anonymous),
stack > *|*:not(:-moz-native-anonymous) {
  grid-area: 1 / 1;
  z-index: 0;

  /*
    The default `min-height: auto` value makes grid items refuse to be smaller
    than their content. This doesn't match the traditional behavior of XUL stack,
    which often shoehorns tall content into a smaller stack and allows the content
    to decide how to handle overflow (e.g. by scaling down if it's an image, or
    by adding scrollbars if it's scrollable).
  */
  min-height: 0;
}

/********** tabbox *********/

tabbox {
  flex-direction: column;
  min-height: 0;
}

tabpanels {
  min-height: 0;
}

tabs {
  flex-direction: row;
}

tab {
  align-items: center;
  justify-content: center;
}

/********** tooltip *********/

tooltip[titletip="true"] {
  /* The width of the tooltip isn't limited on cropped <tree> cells. */
  max-width: none;
}

/********** basic rule for anonymous content that needs to pass box properties through
 ********** to an insertion point parent that holds the real kids **************/

.box-inherit {
  align-items: inherit;
  justify-content: inherit;
  flex-grow: inherit;
  flex-shrink: inherit;
  flex-direction: inherit;
}

/********** textbox **********/

search-textbox {
  text-shadow: none;
}

/* Prefix with (xul|*):root to workaround HTML tests loading xul.css */
:root html|textarea:not([resizable="true"]) {
  resize: none;
}

/********** autocomplete textbox **********/

.autocomplete-richlistbox {
  -moz-user-focus: ignore;
  overflow-x: hidden !important;
  flex: 1;
}

.autocomplete-richlistitem {
  flex-direction: column;
  align-items: center;
  overflow: clip;
}

/* The following rule is here to fix bug 96899 (and now 117952).
   Somehow trees create a situation
   in which a popupset flows itself as if its popup child is directly within it
   instead of the placeholder child that should actually be inside the popupset.
   This is a stopgap measure, and it does not address the real bug.  */
.autocomplete-result-popupset {
  max-width: 0;
  width: 0 !important;
  min-width: 0%;
  min-height: 0%;
}

/********** menulist **********/

menulist[popuponly] {
  appearance: none !important;
  margin: 0 !important;
  height: 0 !important;
  min-height: 0 !important;
  border: 0 !important;
  padding: 0 !important;
}

/******** scrollbar ********/

slider {
  /* This is a hint to layerization that the scrollbar thumb can never leave
     the scrollbar track. */
  overflow: hidden;
}

/******** scrollbox ********/

scrollbox {
  /* This makes it scrollable! */
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  scrollbox[smoothscroll=true] {
    scroll-behavior: smooth;
  }
}

/********** stringbundle **********/

stringbundle,
stringbundleset {
  display: none;
}

/********** dialog **********/

dialog {
  flex: 1;
  flex-direction: column;
}

/********** wizard **********/

wizard {
  flex: 1;
  flex-direction: column;
  contain: inline-size;
  min-width: 40em;
  min-height: 30em;
}

wizard > wizardpage {
  grid-area: 1 / 1;
  min-height: 0;
}

wizard > wizardpage:not(.selected) {
  visibility: hidden;
}

wizardpage {
  flex-direction: column;
  overflow: auto;
}

/********** Rich Listbox ********/

richlistbox {
  flex-direction: column;
  overflow: auto;
  min-width: 0;
  min-height: 0;
}

richlistitem {
  flex-shrink: 0;
}

/*********** findbar ************/
findbar {
  overflow-x: hidden;
  contain: inline-size;
}

/* Some elements that in HTML blocks should be inline-level by default */
button, image {
  display: inline-flex;
}

.menu-iconic-highlightable-text:not([highlightable="true"]),
.menu-iconic-text[highlightable="true"] {
  display: none;
}

[orient="vertical"] { flex-direction: column !important; }
[orient="horizontal"] { flex-direction: row !important; }

[align="start"] { align-items: flex-start !important; }
[align="center"] { align-items: center !important; }
[align="end"] { align-items: flex-end !important; }
[align="baseline"] { align-items: baseline !important; }
[align="stretch"] { align-items: stretch !important; }

[pack="start"] { justify-content: start !important; }
[pack="center"] { justify-content: center !important; }
[pack="end"] { justify-content: flex-end !important; }

[flex="0"] { flex: none !important; }
[flex="1"] { flex: 1 !important; }
