/* 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] {
  display: none;
}

/* hide the content, but don't destroy the frames */
[collapsed] {
  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,
.treecol-text,
.treecol-sortdirection,
.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;
}

/* Double :fullscreen to have more specificity than the fullscreen spec's rule */
browser:fullscreen:fullscreen {
  -moz-top-layer: none !important;
  position: static !important;
}

/*********** 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,
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 ***********/

/* Note that this attribute is added dynamically if needed to menubars by the
 * native menubar code */
menubar[native] {
  display: none !important;
}

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) {
    padding: 6px 10px; /* Matches Adwaita. */
    line-height: 1.4; /* For Noto Sans; note that 1.2 may clip descenders. */
    border: 0.5px solid color-mix(in srgb, currentColor 60%, transparent);
    @media (-moz-gtk-csd-transparency-available) {
      border-radius: env(-moz-gtk-csd-tooltip-radius);
    }
  }
  @media (-moz-platform: macos) {
    padding: 2px 6px; /* Matches native metrics. */
  }
  @media (-moz-platform: windows) {
    appearance: none;
    border: 1px solid;

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

/******** 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] {
  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,
tabpanels > .split-view-panel,
tabpanels > .split-view-splitter,
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;
}

/* 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;
}

/********** 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;
}

[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;
}
