/* Styles for the ShEx web apps -- shex-simple and shex-worker.  The map
 * pages in @shexjs/extension-map are redirects to these now, and ShExMap's
 * own rules (the bindings pane) ride in its plugin descriptor's css.  Four
 * copies is how the shape map lost its left padding on three pages: the
 * fix was made once, in the page whose author noticed, and the others
 * quietly did without.
 *
 * A page keeps a <style> of its own for what is actually its own: how its
 * input area scrolls.
 *
 * The palette, so it stays a family:
 *   schema  #f4f4ff   data  #f4fff4   results  #fffff4   bindings #fffff4
 */

h1 { font-size: 1.3em; }
h1, p, ul { margin: 0; margin-left: .1em; }
.ShExLogo { float:left; height:1.3em; padding-left: .3em; }
/* uncomment for breathing icon
.ShExLogo {
  animation-duration: 2s;
  animation-name: ShExLogo-breath;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
@keyframes ShExLogo-breath {
  from { transform: scale(1, 1); }
  to { transform: scale(1.2, 1.2); }
}
*/
.passes999 { margin-right: 1em; }
.passes, #results div .passes { padding-left: .1em; border-left: thick solid #bfb; }
.pair.passes { border-left: none; padding-left: none; }
.pair.passes { background-color: #bfb; }
.fails , #results div .fails  { padding-left: .1em; border-left: thick solid #fbb; }
.pair.fails { border-left: none; padding-left: none; }
.pair.fails { background-color: #fbb; }
.error , #results div .error  { padding-left: .1em; border-left: thick solid #b00; }
/* one validation result per block, told apart by a rule rather than
   by the punctuation of a JSON array */
#results > div > * + * { border-top: 1px solid #ccc; margin-top: .5em; padding-top: .5em; }
.running { background-color: #ddf; }
/* a validation over a synchronous data source holds the main thread,
   so the button says so before it starts and nothing else can */
#validate.running { background-color: #ffe9a8; border-color: #d0a400; font-style: italic; }
#inputarea { white-space: nowrap; }
#inputarea textarea { overflow-x: auto }
#inputarea textarea.data.focus {
  width: 100%;
  overflow: hidden;
  border-style: inset;
  border-width: 2px;
  padding: 1px 0px;
}
/* adds a bit of left padding to the shape map to fix issue with blinking cursor on left edge not shown enough when element gets bordered and is focused */      
#queryMap { padding-left: .4em }
ul[data-navColumn] button:focus::before { content: "> "; color: #730; margin-left: -1em; }
ul[data-navColumn] button:focus::after  { content: " <"; color: #730; margin-right: -1em; }
.schema.textarea, .schema, .schema.ui-dialog-content { background-color: #f4f4ff; color: #000000; border-color: #fc561c }
#inputSchema li.selected button { background-color: #e8e8ff; color: #000000; }
#inputData textarea, .data, .data.ui-dialog-content { background-color: #f4fff4; color: #000000; border-color: #f0a133 }
#inputData li.selected button { background-color: #e8ffe8; color: #000000; }
/* results are the third thing on the page, so the third tint in the
   family: schema #f4f4ff, data #f4fff4, results #fffff4.  Whether a
   result passed stays in its left border, which says it louder. */
.results { background-color: #fffff4; color: #000000; }
#manifestDrop { border-color: white; width: 100%; }
#manifestDrop div.manifest { overflow: auto; max-height: 10ex; }
#pluginDrop { border-color: #00ffff; width: 88%; border-width: thin; }
#inputSchema li button, #inputData li button {
  font-size: .7em;
  padding: 0em 2ex;
  border-radius: .5em;
  border: thin solid #000;
  cursor: pointer;
  box-shadow: 0.1em 0px 1em rgba(255, 255, 255, 0.9) inset;
}
#inputSchema li button.disabled, #inputData li button.disabled {
  color: #777;
}
/* The page is the window: the title, as much of the middle as is left,
   and the results pinned to the bottom.  Which is what puts #results in one
   place whichever screen is up -- the validator's screen is the tall one,
   since only it has the manifest and the shape map under the schema, and
   the results used to ride up and down with whatever was above them.  The
   panes take the slack instead.
   (margin: the window's height is the budget, so the gap around the page is
   padding inside it rather than margin outside.) */
/* height, not min-height: the window's height has to be the budget rather
   than the floor, or nothing is ever obliged to give anything up -- a
   document taller than its pane simply made the page taller, and the panes
   grew with what was in them instead of being what was left of the page.
   What does not fit scrolls where it is; nothing is lost by the page
   staying the size of the window. */
html { height: 100%; }
body {
    box-sizing: border-box;
    height: 100%;
    overflow: hidden;
    margin: 0;
    padding: .4em;
    display: flex;
    flex-direction: column;
    border-width: .25em; border-style: solid; border-color: white;
}
#title { flex: 0 0 auto; }
#inputarea { flex: 1 1 auto; min-height: 0; overflow: auto; }
#results { flex: 0 0 40vh; display: flex; flex-direction: column; min-height: 0; }

/* ...and the slack goes to the panes rather than to the space around them.
   The columns are as tall as the middle is; in each, the document is what
   grows -- the manifest under the schema, the source's tabs and the buttons
   under the data, are as tall as they are.  Without this the middle grew
   and the panes didn't, which put a band of nothing between the panes and
   the results.

   A column is the height of the middle because it is *stretched* to it, not
   because it asks for a percentage of it: a flex item's height is only
   definite once it has been laid out, and a column that asks too early gets
   its content's height and leaves that band under itself. */
#inputarea { display: flex; align-items: stretch; }
#inputarea > .panel { flex: 0 0 48.5%; }
#inputarea > #screens { flex: 1 1 auto; min-width: 0; }
#screens { display: flex; flex-direction: column; min-height: 0; }
#screens > .screen { flex: 1 1 auto; min-height: 0; }
#inputSchema, #inputData { display: flex; flex-direction: column; min-height: 0; }
#schemaDocument, #dataArea, #dataDocument {
    flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}
#dataSource-tabs { flex: 0 0 auto; }
/* What is under the document is anchored to the foot of the column, which
   is the top of the results: the validate row never moves.  The example
   lists are what gives way when there are more of them than there is room
   for -- they take what they need up to that, and scroll past it -- so
   picking a schema with a dozen examples resizes the document rather than
   pushing everything below it down the page. */
#inputSchema > div:not(#schemaDocument),
#inputData > div:not(#dataArea):not(#dataExamples) { flex: 0 0 auto; }
#dataExamples { flex: 0 0 auto; max-height: 30%; overflow: auto; }
/* a document is its box: a textarea sized in rows, or an editor that takes
   its height from what it was given rather than from what is in it */
#schemaDocument > textarea, #dataDocument > textarea,
.fillsColumn > textarea { height: 100%; box-sizing: border-box; }
#schemaDocument > .shexjs-editor-pane, #dataDocument > .shexjs-editor-pane,
.screen .panel > div[id] > .shexjs-editor-pane { flex: 1 1 auto; min-height: 0; }
.shexjs-editor-pane > .cm-editor { height: 100%; }
/* ...and inside the results, the tab strip is fixed and the panel takes the
   rest, so what is in it scrolls rather than the page growing.

   Whichever box holds the results is the one that scrolls: a tab's panel
   where there are tabs, and #results' own div where there are none -- which
   is every page with no plugin on it.  Without that the results ran past
   the foot of the page with nothing to scroll them, and a hover that
   scrolled a result into view took the whole page with it, the body being
   the nearest thing that would move. */
#results > div, #resultsTabs { flex: 1 1 auto; min-height: 0; }
#results > div:not(#resultsTabs) { overflow: auto; }
/* Between the two: a handle to drag, to say how much of the page is what
   you are working on and how much is what came of it.  Outside #results,
   because "#results > div" is where results are written. */
#resultsGrip {
    flex: 0 0 auto;
    height: .45em;
    margin: .15em 0;
    border-radius: .2em;
    background-color: #ddd;
    cursor: row-resize;
}
#resultsGrip:hover { background-color: #bbb; }
#resultsTabs { display: flex; flex-direction: column; }
#resultsTabs > ul { flex: 0 0 auto; }
/* something about the results as a whole rather than in them: ShExMap's
   list of viable materializations, at the right-hand end of the strip of
   tabs, out of the flow so that it cannot push the results it is about */
#resultsTabs { position: relative; }
/* width: the sheet gives every div in #results 99% of it, which made this
   a full-width box anchored to the right with its text at the left -- over
   the tabs it is supposed to sit beside.  It is as wide as what it says. */
#resultsTabs > .resultsTabsAside {
    position: absolute;
    top: .4em;
    right: .6em;
    width: auto;
    white-space: nowrap;
    text-align: right;
    font-size: .9em;
    /* ...and none of the rule that separates one result from the next:
       this is beside the tabs rather than under them, and the separator's
       margin and padding are what dropped it half a line */
    margin: 0;
    padding: 0;
    border-top: none;
}
/* the tab set and the document share one box, whose height the app
   fixes to what a document needs once it has measured one (see
   showDocumentArea) so the buttons below don't move when the settings
   tab, which is short, is showing */
#dataSource-tabs { margin-bottom: .2em; padding: .2em; }
#dataSource-tabs .ui-tabs-nav { padding-left: .2em; }
#dataSource-tabs .ui-tabs-panel { padding: .3em .2em; }
/* one setting per line: they are a form, not a sentence, and a row of
   them runs off the side of a panel that is half the window wide */
#neighborhoodFields label.neighborhoodField { font-size: .85em; display: block; margin: .15em 0; }
#neighborhoodFields label.neighborhoodField > span { display: inline-block; min-width: 11em; }
#neighborhoodFields input[type=text], #neighborhoodFields input[type=number] { width: 22em; max-width: 60%; }
#neighborhoodFields .noSettings { font-size: .85em; font-style: italic; color: #666; }
#dataPaneControls { float: right; }
#dataPaneControls button { font-size: .8em; }
#dataSource { font-size: .8em; }
.droparea { border-width: .25em; border-style: dashed; }
.droparea.hover, body.hover { border: .25em dashed #0c0; }
.stoppable { background-color: red; }
#results div:disabled { background-color: #fff; }
#results div { width: 99%; border: none; }
/* the 99% width above must not reach into CodeMirror internals
   (appinfo results panes): 99%-wide gutters push the code offscreen */
#results .cm-editor div { width: unset; }
#results div:disabled.passes { color: #373; }
#results div:disabled.fails  { color: #733; }
#results div:disabled.error  { color: #300; }
#results div.human { margin: 1ex 0; }
#results div.human pre { margin: 0 2em; }
#results h3 { font-size: larger; margin: 0; }
#results pre { margin: 1ex; }
#results .data, #results .schema { border-style: dotted; border-width: 2px; }
.status { display: none; } /* disable .status 'cause it's redundant against the selected marker. */
#navlist li {
  display: inline;
  list-style-type: none;
  padding-right: 10px;
}
/* the shape map, in its three views (text, editor, fixed).  Not
   "actions": the buttons that act on it live with the data. */
#shapeMapArea {
  float:right;
  margin-right: .1em;
}
/* http://stackoverflow.com/questions/686905/labeling-file-upload-button#answer-35767488 */
.inputfile {
  /* visibility: hidden etc. wont work */
  width: 0.1px;
  height: 0.1px;
  opacity: 0;
  overflow: hidden;
  position: absolute;
  z-index: -1;
}
.inputfile:focus + label {
  /* keyboard navigation */
  outline: 1px dotted #000;
  outline: -webkit-focus-ring-color auto 5px;
}
.inputfile + label * {
  pointer-events: none;
}
label {
  /* border: thin solid black; */
  padding: 0 .3em;
}
.heading {
  font-weight: bold;
}
/* Screens: the validator's two panels are the app's own screen, and each
   plugin's panes land in a .screen of its own inside #screens, one showing
   at a time (ShExBaseApp.showScreen).  A screen is a block the full width
   of the page; the .panels inside it are its columns. */
/* The screen tabs stand in for the part of the title that named what is
   showing: "ShEx - " stays, "Validator" becomes the first tab.  They sit in
   the heading, so they are told the type a button does not inherit, and
   they are tabs on the page's own terms rather than jquery-ui's -- what
   they switch is elsewhere on the page, which jquery-ui tabs cannot do. */
#screenTabs { margin-left: .2em; vertical-align: baseline; }
#screenTabs button {
    font: inherit;
    font-size: .6em;
    padding: .15em .6em;
    margin-right: .15em;
    border: 1px solid #bbb;
    border-bottom: none;
    border-radius: .4em .4em 0 0;
    background-color: #eee;
    color: #444;
    cursor: pointer;
}
#screenTabs button[aria-selected="true"] {
    background-color: #fff;
    color: #000;
    font-weight: bold;
}
/* The × that unloads the plugin whose tab it is.  Quiet until the tab is
   under the mouse: a reader switching screens should not keep finding a
   button that takes one away. */
#screenTabs .unloadPlugin {
    margin-left: .5em;
    padding: 0 .15em;
    border-radius: .2em;
    color: #999;
    opacity: 0;
    cursor: pointer;
}
#screenTabs button:hover .unloadPlugin,
#screenTabs button:focus-within .unloadPlugin { opacity: 1; }
#screenTabs .unloadPlugin:hover { color: #a00; background-color: #f4dede; }
/* A screen's columns stand side by side and stretch to the tallest of
   them, so a pane that is alone in its column may have all of it: the
   overlay ShExReduce puts where the schema stands gets the height that
   column gets, rather than the dozen rows a textarea asks for.  The toolbar
   and the statusbar wrap to lines of their own underneath. */
.screen { display: flex; flex-direction: column; height: 100%; }
.screenColumns { display: flex; align-items: stretch; flex: 1 1 auto; min-height: 0; }
/* 0px rather than 0: the same length, and the one a test's document
   parser will accept -- a `flex` shorthand with a unitless basis is dropped
   whole there, so a rule written that way is a rule no test can see. */
.screenColumns > .panel, .screenColumns [data-borrow] > .panel { flex: 1 1 0px; }
/* A borrowed pane is a column of the screen like any other: the slot it is
   lent to has to be the box the pane fills, or the pane is as tall as what
   is in it and the column ends short of the results. */
.screenColumns > [data-borrow] { flex: 1 1 0px; display: flex; flex-direction: column; min-height: 0; }
/* A screen's panes fill it the way the validator's do: a column shares its
   height among the panes in it -- in proportion to the rows each asked for,
   which the app writes on the pane -- each pane's document takes what its
   pane has left, and what doesn't fit scrolls where it is.  A pane that says
   `fill` is one that happens to be alone in its column. */
.screenColumns > .panel { display: flex; flex-direction: column; min-height: 0; }
.screenColumns > .panel > div[id],
.screen [data-tabset] > div[id],
.screen [data-tabset] > [data-borrow] {
    flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}
.screen div[id] > textarea,
.screen div[id] > .shexjs-editor-pane { flex: 1 1 auto; min-height: 0; }
.screen > .pluginToolbar, .screen > .pluginStatusbar { flex: 0 0 auto; }
/* ...and a pane that asked for its box takes what is left of it once the
   status line above has had its share.  Used on a screen's column and in a
   results tab, which are the two boxes a pane can be given whole. */
.fillsColumn { display: flex; flex-direction: column; height: 100%; }
.fillsColumn > textarea,
.fillsColumn > .shexjs-editor-pane { flex: 1 1 auto; }

/* Every kind of result gets the same box.  Two reasons: a reader switching
   between a validation and what was made of it should not have the page
   change size underneath them, and a long result used to push the rest of
   the page off the bottom -- a results pane measured while its tab was
   hidden can come back taller than the window, and a tab that scrolls keeps
   that between its own edges. */
#resultsTabs > div[id] { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* the slot a screen keeps for a pane it borrows: as a column of the
   screen the pane is a .panel already, so the slot lays nothing out; in a
   tab set the slot is the tab's panel, and what it holds fills it */
.screen > [data-borrow] { display: contents; }
.screen [data-tabset] .panel,
.screen [data-tabset] > [data-borrow] > * { width: auto; margin: 0; }
/* a set of panes taking turns is as much the column as one pane is */
.screen [data-tabset] { display: flex; flex-direction: column; height: 100%; }
.screen [data-tabset] > div[id] { flex: 1 1 auto; }
.panel {
  width: 48.5%;
  display: inline-block;
  margin: 0 .4em;
  vertical-align: top;
}
h2.status { margin: 0; }
#schemaDialect, #dataDialect { font-size: .7em; }
#shapeMap-tabs textarea.error { padding-left: default; border-left: default; background-color: #fdd; }
#editMap input.error { padding-left: none; border-left: none; background-color: #fdd; }
.pair { list-style-type: none; }
.addPair, .removePair { font-size: 80%; line-height: 1ex; font-family: monospace; }
.pair button {
  width: 1em;
  padding: .5em 0;
  padding-right: .5em; /* for firefox rendering issue */
}

#menuForm > fieldset {
    box-shadow: -.3ex .3ex grey;
    display: inline;
}

#controls {
    position: absolute;
    left: 0;
    top: 0;
    list-style: none;
    margin: 0;
    display: none;
    background: white; opacity: 1;
    border: thin solid buttontext;
    /* box-shadow: -.3ex .3ex grey; */
}
#controls div {
    border: 10px solid buttonface;
}
#controls h3 {
    margin: 0;
}
#menu-button { margin-left: 1em; }
#menu-button svg { width: 1em; height: 1.5ex; }
#about {
  margin: 3em;
}
#controls ul { padding-left: 0; margin-left: 0; list-style-type: none; }
#controls li { padding: 0 1em; }
#controls li.menuitem:hover { background-color: buttonface; }

.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
    padding: 0 .1em;
}
.ui-tabs .ui-tabs-panel {
    padding: 0;
}
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button {
    font-size: small;
}
#shapeMap-tabs .ui-tabs-panel {
    font-family: monospace;
    min-height: 10ex;
}
#shapeMap-tabs {
    font-family: inherit;
    font-size: inherit;
    margin-top: .5ex;
}
#editMap, #fixedMap {
    padding: 0;
}
#editMap td {
    padding: 0;
}
#editMap td:nth-child(2),
#editMap td:nth-child(4),
#editMap td:nth-child(5) {
    width: .01em;
}
#editMap input, #fixedMap input {
    width: 100%;
}
#fixedMap tr td:nth-child(2),
#fixedMap tr td:nth-child(4),
#fixedMap tr td:nth-child(5) { width: .8em; }
ul {
    padding-left: 1.2em;
    padding-right: .4em;
}

/* The validation debugger's controls (doc/debugger-design.md).
 *
 * Three rows rather than one long line: the step buttons beside the button
 * that started them, then which match is being stepped, then what it is
 * doing.  On one line the status text -- "paused before matching
 * <http://…/P31>; step or continue" -- pushed everything after it off to
 * the right, and the pane scrolled sideways to follow. */
#valDebugControls {
    margin-left: .6em;
    white-space: nowrap;
}
.valDbgRow {
    margin-top: .35em;
    font-size: small;
}
#valDbgMatches {
    max-width: 100%;
}
/* one small button per thread, and a generation can have a lot of them:
   let the list scroll in its own strip instead of widening the page */
#valDbgThreads {
    display: inline-block;
    vertical-align: middle;
    margin-left: .5em;
    max-width: 22em;
    overflow-x: auto;
    white-space: nowrap;
    font-size: small;
}
/* the breakpoints, one chip each, the × taking it away */
#valDbgBreakpoints .dbgBreakpoint {
    display: inline-block;
    margin-left: .4em;
    padding: 0 .3em;
    border: thin solid #c22;
    border-radius: .5em;
    font-size: small;
}
#valDbgBreakpoints .dbgBreakpoint button {
    border: none;
    background: none;
    padding: 0 0 0 .2em;
    cursor: pointer;
}
table.dbgThreadState th { text-align: left; padding-right: .6em; vertical-align: top; }
table.dbgThreadState caption { text-align: left; font-weight: bold; }
/* the status is a sentence, so let it wrap rather than run off the edge */
#valDbgStatus {
    display: inline-block;
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
}

/* A plugin's row of controls, arranged like the validator's above.
 *
 * The inner box floats right so it sits at the panel's edge, and its
 * wrapper held nothing else -- so the wrapper collapsed to no height at
 * all, the float escaped it, and what came next in the page laid out over
 * the top of the buttons.  A block formatting context contains its floats. */
.pluginToolbar {
    display: flow-root;
}
.pluginToolbarInner {
    float: right;
    margin-right: .1em;
    text-align: right;
}

/* The highlight switch's chip: centred above the validate/materialize
 * controls, where the reader is already looking when they press a button.
 *
 * A momentary mode has to be *visible* while it is held -- that is the whole
 * argument for holding a key rather than latching one -- so this says both
 * what the switch is set to and whether a highlight is frozen. */
/* beside the controls button, on its line.  #menuForm is a form and so a
 * block, which is why sitting after it put the chip underneath. */
#highlightModeRow {
    display: inline;
    margin-left: .6em;
}
#highlightMode {
    font-size: small;
    padding: .1em .7em;
    border: 1px solid #bbb;
    border-radius: 999px;
    background: #f4f4f4;
    color: #444;
    cursor: pointer;
    white-space: nowrap;
}
/* live: the mouse is painting right now (whether by the switch or the key) */
#highlightMode[data-live="yes"] {
    border-color: #6a9a3a;
    background: #eef6e4;
    color: #33521c;
}
#highlightMode[data-state="off"] {
    color: #888;
}
/* frozen outranks the rest: nothing the mouse does will change the picture */
#highlightMode[data-frozen="yes"] {
    border-color: #7a86c8;
    background: #eceefb;
    color: #333c78;
    font-weight: bold;
}
#highlightMode:focus-visible {
    outline: 2px solid #88f;
    outline-offset: 1px;
}
