/* THE CONTROL SYSTEM.
 *
 * ------------------------------------------------------------------ why this file exists
 *
 * Forty pressable things had grown up in this application, each one styled where it happened to
 * be written: seven heights between 17 and 30 pixels, three capsule radii, two radii hard-coded
 * at 4 and 5 pixels that could not follow a theme, five different answers to "this one is
 * currently ON", and four different outlined buttons. Every one of them was defensible on its own
 * and the row they made together was not. That is what a stranger means when they say an
 * interface looks machine-made: not one ugly button, but no two buttons agreeing on anything.
 *
 * And underneath them sat a skeuomorphic recipe - a gradient body, a lit rim along the top, a
 * darker bottom edge, a contact shadow, a pixel of press travel. It is the 2008 web button. Two
 * of the five appearances wore it in full, and it leaked into the other three through the welded
 * toolbar groups, because the theme that removes it listed the controls to flatten by hand and
 * the list had drifted. A recipe that has to be un-done by every theme is the wrong default.
 *
 * ------------------------------------------------------------------ what it is instead
 *
 * The grammar every current professional tool converged on - TradingView's chrome, which this
 * product's default appearance already ports, and equally Linear's, Figma's, Stripe's: a control
 * is FLAT. It is a ground, a hairline and a label. Depth is carried by the palette - a control's
 * ground is one step off its surround - never by a gradient or a shadow. Nothing about it is
 * pretending to be a physical object.
 *
 * FOUR ROLES, and every pressable thing in the product is exactly one of them:
 *
 *   quiet    A verb. Transparent at rest, and hover LIGHTS ITS INK rather than putting a plate
 *            behind it. Toolbar verbs, icon buttons, window controls, row controls.
 *   field    A control that carries a VALUE or commits something: a hairline frame around a
 *            transparent body. Buttons, chips, steppers, the welded toolbar groups, tiles.
 *   on       The one answer to "this is currently selected": the quiet ground, full-strength ink.
 *            The accent is NOT this - it is reserved, below.
 *   primary  The single committing action on a surface. Filled, and the only filled thing on it.
 *
 * THE ACCENT is spent on four things and nothing else: the current period, the armed drawing
 * tool, a checked box, and a focused field - and only in an appearance that HAS an accent. The
 * base palette's is a grey on purpose, so there the period is stated in weight and ink instead.
 * A colour that marks everything marks nothing.
 *
 * THREE HEIGHTS: 20 for an icon inside a list row, 24 for dense chrome, 28 for the default
 * control and for every button that commits. Nothing in between, so a row of controls lines up
 * without anyone measuring.
 *
 * ONE RADIUS - var(--r), which is themed, so controls follow the appearance instead of sitting at
 * 4px inside a 1px-radius theme. The capsule survives in exactly one place, on a TAG: a thing
 * that labels rather than acts.
 *
 * ------------------------------------------------------------------ how it is arranged
 *
 * Paint lives here; geometry stays with the component that owns it. A file that draws a panel
 * keeps its layout, spacing and structure, and does not restate what a button looks like - the
 * comment at each site says so. This sheet loads directly after style.css, so an appearance can
 * still tune the system and a component can still override a single value deliberately.
 */

:root {
  /* Three heights. */
  --c-row: 20px;
  --c-sm: 24px;
  --c-md: 28px;
  /* The fourth is not a control height: it is the one prominent rung a TEXT FIELD may take, for
     the headline search of a window that exists to be searched. See "the field, for TEXT". */
  --c-lg: 36px;

  /* Two paddings, matched to them: dense, and wide enough for a word that commits. */
  --c-pad-sm: 8px;
  --c-pad-wide: 14px;

  /* The one capsule, for tags. */
  --r-tag: 999px;

  /* State grounds, derived from the palette rather than picked per control, so they are correct
     on a light appearance without a second table. */
  --c-press: color-mix(in srgb, var(--ink) 12%, var(--panel-2));
  --c-line: var(--line-2);
  --c-line-hover: var(--ink-faint);
}

/* One transition for every control, so the whole chrome responds at one speed. Linear, and fast:
   an eased or bouncy control that reports market state makes the state look uncertain. */
.ctl,
.btn,
.chip,
.tab,
.tp-type,
.tp-pct,
.tp-side,
.tp-mini,
.tp-levmode,
.tp-close,
.tfq,
.navbtn,
.sb-btn,
button.sb,
.win-btn,
.dw-btn,
.ot-btn,
.rb-btn,
.th-preset,
.newtab-view,
.toggles button,
.ip-pill,
.cp-btn,
.pp-btn,
.pp-ibtn,
.pp-addbtn,
.pp-spinbtn,
.nw-chip,
.nw-segbtn,
.nw-srcbtn,
.fl-step,
.fl-chip,
.up-pill {
  transition: background-color var(--t-tap) var(--ease), border-color var(--t-tap) var(--ease), color var(--t-tap) var(--ease);
}

/* =============================================================== the quiet role
 *
 * A verb, and nothing more. THE HOVER LAW, stated once and applied everywhere: a control with no
 * face at rest never gains one on hover. Its ink lights and NOTHING appears - no plate, no
 * border, no ground. The grey square materialising behind a small glyph, twenty times across one
 * toolbar, is the single loudest default-UI tell; the expensive version of hover is luminance. */
.ctl,
.tab,
.tfq,
.navbtn,
.sb-btn,
button.sb,
.win-btn,
.dw-btn,
.ot-btn,
.rb-btn,
.toggles button,
.nw-chip,
.nw-segbtn,
.pp-addbtn {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r);
  box-shadow: none;
  color: var(--ink-dim);
  cursor: pointer;
}

.ctl:hover,
.tab:hover,
.tfq:hover,
.navbtn:hover,
.sb-btn:hover,
button.sb:hover,
.win-btn:hover,
.dw-btn:hover,
.ot-btn:hover,
.rb-btn:hover,
.toggles button:hover,
.nw-chip:hover,
.nw-segbtn:hover,
.pp-addbtn:hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--ink);
}

/* =============================================================== the field role
 *
 * A control that carries a value or commits something: a hairline around a transparent body. The
 * hairline is what says "there is a control here" without a plate saying it louder. */
.btn,
.chip,
.th-preset,
.newtab-view,
.ip-pill,
.cp-btn,
.pp-btn,
.pp-ibtn,
.nw-srcbtn,
.fl-step,
.fl-chip,
.sym-group,
.tf-group,
.stepper,
.nw-seg {
  background: transparent;
  border: 1px solid var(--c-line);
  border-radius: var(--r);
  box-shadow: none;
  color: var(--ink-dim);
}

.btn:hover,
.chip:hover,
.th-preset:hover,
.newtab-view:hover,
.ip-pill:hover,
.cp-btn:hover,
.pp-btn:hover,
.pp-ibtn:hover,
.nw-srcbtn:hover,
.fl-step:hover,
.fl-chip:hover {
  background: transparent;
  border-color: var(--c-line-hover);
  color: var(--ink);
}

/* -------------------------------------------------- the field role, INSIDE THE FURNITURE
 *
 * A hairline around a transparent body is right for a field on a surface you are reading: the
 * frame is the quietest way to say "there is a control here" when there is room to be quiet.
 *
 * In a toolbar there is no room. Three outlined boxes in a row - instrument, period, tick - draw
 * six vertical hairlines across the densest 300 pixels in the window, and the eye reads six edges
 * before it reads three values. Every desktop terminal answers this the same way and it is the
 * opposite of the surface answer: the cell gets a GROUND one step off the band and no frame at
 * all. One edge each instead of two, and the value is what you see first.
 *
 * Scoped to the bands, deliberately. The same group in a dialog keeps its hairline, because there
 * it is being read. */
.bar .sym-group,
.bar .tf-group,
.bar .stepper {
  background: var(--panel-2);
  border-color: transparent;
}
.bar .sym-group:hover,
.bar .tf-group:hover,
.bar .stepper:hover {
  background: var(--panel-3);
  border-color: transparent;
}

/* A welded group is one field with zones inside it, not a row of fields: its children give up
   their own body and keep only their type and their ink. */
.sym-group > *,
.tf-group > *,
.tf-group .tf-quick > *,
.stepper > * {
  background: transparent;
  border: 0;
  box-shadow: none;
}

/* =============================================================== the on role
 *
 * ONE answer, everywhere, to "this is currently selected": the quiet ground and full-strength
 * ink. It was five answers - an accent fill here, --sel there, --panel-3 in a third place - and a
 * reader had to learn each surface separately to know what was on. */
.tab.on,
.chip.on,
.toggles button.on,
.dw-btn.on,
.ip-pill.on,
.nw-chip.on,
.nw-segbtn.on,
.nw-srcbtn.on,
.fl-step.on,
.fl-chip.on,
.fl-fbtn.open,
/* the trade column's order-type switch */
.tp-type.on,
.ladder-bar .ctl.on {
  background: var(--sel);
  border-color: var(--c-line);
  color: var(--ink);
  box-shadow: none;
}
/* A latch with no frame at rest does not grow one when it latches - the ground is the whole
   statement. */
.tab.on,
.toggles button.on,
.dw-btn.on,
.nw-chip.on,
.nw-segbtn.on,
.ladder-bar .ctl.on {
  border-color: transparent;
}

/* The viewport buttons at the end of the tab strip are the owner's own exception, and a correct
   one: a latched auto-scale shows as ink with a hairline UNDER it, no plate at all, because they
   sit half inside the price axis where a plate would read as part of the chart. style.css draws
   that underline; the system only has to not put a ground behind it. */

/* The current period is a latch like any other, and it is the one latch that also carries weight:
   a period is read at a glance from across a desk. An appearance with a real accent spends it
   here - theme-tv.css does, which is where TradingView puts its blue - and the base palette,
   whose "accent" is a grey by design, states it in ink instead. */
.tfq.on,
.tf-group .tfq.on {
  background: var(--sel);
  border-color: transparent;
  color: var(--ink);
  font-weight: var(--w-semi);
}

/* The tool rail is deliberately NOT in this system. It is a palette, not a toolbar: an icon
   column whose latch is the armed tool, whose hover is a pill on the standalone buttons, and
   whose geometry is set by the icon rather than by a text height. It is internally consistent
   already, style.css owns it, and each appearance themes it - dragging it in here would trade a
   coherent component for a uniform one. */

/* =============================================================== the primary role
 *
 * The one committing action on a surface, and the only filled thing on it. */
.btn.primary,
.cp-apply,
.pp-apply {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-ink);
  font-weight: var(--w-semi);
}
.btn.primary:hover,
.cp-apply:hover,
.pp-apply:hover {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
  color: var(--primary-ink);
}

/* Destructive: the sell colour as INK, filling only under the pointer. A permanently red button
   in a toolbar is a warning nobody reads by the second day. */
.btn.danger {
  border-color: color-mix(in srgb, var(--sell) 45%, transparent);
  color: var(--sell-hi);
}
.btn.danger:hover {
  background: var(--sell);
  border-color: var(--sell);
  color: #fff;
}

/* A verb with no frame at all - the third button in a footer, next to a primary and an outline. */
.btn.ghost {
  border-color: transparent;
  background: transparent;
}
.btn.ghost:hover { border-color: transparent; background: transparent; color: var(--ink); }

/* =============================================================== press, disabled, focus
 *
 * THE PRESS. No travel. A control that moves is a control pretending to be a physical object,
 * which is the whole tell this file removes; the ground steps one shade instead. Travel also
 * costs a repaint of whatever sits under it, which on a live tape is not free. */
.ctl:active,
.btn:active,
.chip:active,
.tab:active,
.tfq:active,
.navbtn:active,
.sb-btn:active,
button.sb:active,
.win-btn:active,
.dw-btn:active,
.ot-btn:active,
.rb-btn:active,
.th-preset:active,
.newtab-view:active,
.toggles button:active,
.ip-pill:active,
.cp-btn:active,
.pp-btn:active,
.pp-ibtn:active,
.pp-addbtn:active,
.pp-spinbtn:active,
.nw-chip:active,
.nw-segbtn:active,
.nw-srcbtn:active,
.fl-step:active,
.fl-chip:active,
.up-pill:active {
  transform: none;
  box-shadow: none;
  background: var(--c-press);
}
/* Except the two that are already filled, where a grey press would read as the button breaking. */
.btn.primary:active,
.cp-apply:active,
.pp-apply:active { background: var(--primary-hover); }

/* Disabled says so once, in opacity, and stops answering the pointer. Every control that can be
   disabled used to do this its own way, or not at all. */
.ctl:disabled,
.btn:disabled,
.chip:disabled,
.tfq:disabled,
.navbtn:disabled,
.sb-btn:disabled,
.win-btn:disabled,
.dw-btn:disabled,
.ot-btn:disabled,
.rb-btn:disabled,
.th-preset:disabled,
.toggles button:disabled,
.ip-pill:disabled,
.cp-btn:disabled,
.pp-btn:disabled,
.pp-ibtn:disabled,
.pp-addbtn:disabled,
.pp-spinbtn:disabled,
.nw-chip:disabled,
.nw-segbtn:disabled,
.nw-srcbtn:disabled,
.fl-step:disabled,
.fl-chip:disabled {
  opacity: .45;
  cursor: default;
  pointer-events: none;
}

/* Focus is the accent, one hairline, inside the control's own edge so it cannot change the
   layout. Declared in style.css for every element; restated here only so a control that draws its
   own border cannot lose it. */
.btn:focus-visible,
.chip:focus-visible,
.ctl:focus-visible,
.ip-pill:focus-visible,
.nw-srcbtn:focus-visible,
.fl-step:focus-visible,
.fl-chip:focus-visible {
  outline: 1px solid var(--focus);
  outline-offset: -1px;
}

/* =============================================================== the three heights
 *
 * Applied by role, not per component, so a row of mixed controls lines up. Where a component
 * needs a different metric for a real reason - a tile, a tag - it says so at its own site. */
.btn,
.cp-btn,
.pp-btn,
.ip-pill,
.nw-srcbtn {
  height: var(--c-md);
  padding: 0 var(--c-pad-wide);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font: inherit;
  font-size: var(--t-sm);
  white-space: nowrap;
  cursor: pointer;
}
/* A committing word gets the wide padding; a chip in a dense strip does not. */
.chip,
.nw-chip,
.nw-segbtn,
.pp-ibtn,
.fl-step,
.fl-chip {
  height: var(--c-sm);
  padding: 0 var(--c-pad-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-size: var(--t-sm);
  white-space: nowrap;
  cursor: pointer;
}
.ot-btn { height: var(--c-row); }

/* `display` on a class beats the user agent's [hidden], so a control given a display value here
   can no longer be hidden by the attribute - it just keeps standing there. Every role that sets
   one restates it, once, where the display was set rather than at each of the forty call sites. */
.btn[hidden],
.cp-btn[hidden],
.pp-btn[hidden],
.ip-pill[hidden],
.nw-srcbtn[hidden],
.chip[hidden],
.nw-chip[hidden],
.nw-segbtn[hidden],
.pp-ibtn[hidden],
.fl-step[hidden],
.fl-chip[hidden] { display: none; }

/* The capsule, kept for the one thing it is right for: a TAG, which labels rather than acts. */
.nw-pill,
.nw-symchip,
.up-pill { border-radius: var(--r-tag); }

/* =============================================================== the field, for TEXT
 *
 * The four roles above cover everything that is PRESSED. Nothing covered the things that are
 * TYPED INTO, and it showed: five text fields had grown up across the product at four heights
 * (24, 26, 28, 38), two radii (the themed corner, and a literal 8px on the one field most people
 * see first), two grounds (the page black on one, transparent on the rest) and two glyph insets.
 * Set side by side they are the same fault the top of this file describes for buttons - no two
 * agreeing on anything - and a search box is the control a stranger judges a tool by, because it
 * is the first thing they touch.
 *
 * TWO RUNGS, and no others:
 *
 *   28  --c-md   the default. The same height as a button that commits, so a field and a button
 *                on one row line up without anyone measuring.
 *   36  --c-lg   a window's HEADLINE search - the one field that is the whole point of the
 *                window it opens in. Bigger on purpose, and still the same corner, hairline,
 *                ground and focus as the small one, so it reads as the same control enlarged
 *                rather than as a different control.
 *
 * ONE FOCUS. A field used to say it was focused twice: its own border went to the accent, and
 * the document-wide :focus-visible ring was painted on top of it - two blue lines a pixel apart
 * around a black box, which is the loudest thing in a settings window of eight hundred controls.
 * The ring is right for a button that has no border of its own to change. A field HAS one, so it
 * states focus itself: the hairline takes the accent and a soft halo sits outside it. The
 * document rule now exempts text entry by SHAPE rather than by a roster of class names, so a
 * field written tomorrow is exempt the day it is written.
 *
 * Type is NOT set here. What a field is set in - the value weight on a settings row, the
 * monospace on a label prefix - belongs to the component, and this role is the box around it. */

.fld-input:not([type='checkbox']),
.fld-pick,
input.txt,
.search,
.set-search,
.im-search,
.wl-search,
.toolfly-search,
.al-input,
.nw-searchwrap,
.aw-searchwrap {
  box-sizing: border-box;
  height: var(--c-md);
  border: 1px solid var(--c-line);
  border-radius: var(--r);
  background: transparent;
  color: var(--ink);
  transition: border-color var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

/* The headline rung, and the dense one. A field in a panel toolbar sits with 24px chrome and
   takes its height, exactly as a chip does - the rungs are the control heights, not a second
   scale invented for text. */
.im-search { height: var(--c-lg); }
.wl-search,
.nw-searchwrap,
.aw-searchwrap { height: var(--c-sm); }

.fld-input:not([type='checkbox']):hover,
.fld-pick:hover,
input.txt:hover,
.search:hover,
.set-search:hover,
.im-search:hover,
.wl-search:hover,
.toolfly-search:hover,
.al-input:hover,
.nw-searchwrap:hover,
.aw-searchwrap:hover {
  border-color: var(--c-line-hover);
}

/* Focus: the hairline takes the accent, and a halo sits OUTSIDE the edge so nothing reflows.
   Three pixels at a sixth strength - visible across a window, and quiet enough that a focused
   field does not become the loudest thing on the screen. */
.fld-input:not([type='checkbox']):focus,
.fld-pick:focus-visible,
input.txt:focus,
.search:focus,
.set-search:focus,
.im-search:focus,
.wl-search:focus,
.toolfly-search:focus,
.al-input:focus,
.aw-searchwrap:focus-within,
/* The news field puts its hairline on a WRAPPER so the glyph can sit beside the text rather than
   behind it. Same role, one construction away - so it answers focus-within. */
.nw-searchwrap:focus-within {
  outline: none;
  border-color: var(--focus);
  /* Two pixels at a ninth strength. A window whose whole point is its search opens with that
     field already focused, so this halo is the first thing anyone sees of the window - at three
     pixels and a sixth it drew a band of colour the width of the dialog, which is a lot of noise
     to spend saying "the cursor is where you expected it". */
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--focus) 11%, transparent);
}

/* A field carries its search glyph INSIDE it, so the glyph is one size everywhere and the text
   starts clear of it. Stated here because the inset and the glyph have to agree, and they were
   set independently in two sheets. */
.set-searchicon,
.im-searchwrap > svg {
  width: 14px;
  height: 14px;
}

/* THE BROWSER'S OWN CLEAR BUTTON, removed everywhere rather than in one sheet.
 *
 * `type=search` earns the field Escape-to-clear and the engine's clear glyph - and that glyph is
 * drawn by the browser, at the browser's weight, in the browser's size. In the settings strip it
 * landed as a bold cross roughly a third heavier than the magnifier six inches to its left, which
 * is the kind of mismatch nobody can name and everybody sees. One sheet already hid it, for one
 * field. This hides it for all of them; a field that needs a clear draws its own, in the ink and
 * at the size the rest of the chrome uses. */
input[type='search']::-webkit-search-cancel-button,
input[type='search']::-webkit-search-decoration { -webkit-appearance: none; display: none; }

/* =============================================================== reduced motion */
@media (prefers-reduced-motion: reduce) {
  .ctl, .btn, .chip, .tab, .tfq, .navbtn, .sb-btn, button.sb, .win-btn, .dw-btn, .ot-btn,
  .rb-btn, .th-preset, .newtab-view, .toggles button, .ip-pill, .cp-btn,
  .pp-btn, .pp-ibtn, .pp-addbtn, .pp-spinbtn, .nw-chip, .nw-segbtn, .nw-srcbtn, .fl-step,
  .fl-chip, .up-pill,
  .fld-input, .fld-pick, input.txt, .search, .set-search, .im-search, .wl-search,
  .toolfly-search, .al-input, .nw-searchwrap, .aw-searchwrap { transition: none; }
}
