/* A dark trading desk. Sober rather than decorative: the chart is the thing
   that carries meaning, so everything around it stays quiet and out of the way. */

/* Vazirmatn, carried inside the application rather than fetched. A font that
   arrived over the network would leave the interface in a fallback for anyone
   without a connection — which is most of the point of this program. */
@font-face {
  font-family: Vazirmatn;
  src: url("fonts/Vazirmatn-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: Vazirmatn;
  src: url("fonts/Vazirmatn-Medium.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: Vazirmatn;
  src: url("fonts/Vazirmatn-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

/* The same face again, offered ONLY for Persian.
 *
 * `unicode-range` decides which characters a family is even considered for,
 * so this one covers the Arabic block and nothing else. Put at the FRONT of a
 * list, it takes every Persian character and leaves every Latin one to the
 * face behind it. That is the only way to say "Persian is always Vazirmatn"
 * inside a monospace box without turning the code in it proportional.
 *
 * It is needed because a face can carry Persian without anybody meaning it
 * to. Measured on this machine: the same five Persian words came out 129.4px
 * in Vazirmatn, 131.5px under the old `--mono` (Tahoma, through Bahnschrift
 * which has none), and 146.5px under `--code` — Cascadia Mono, drawing
 * Persian of its own in a box meant for code. Three faces, none of them
 * chosen, and nothing on screen to say so.
 *
 * Only 400 and 700: a code box and a figure are never set in medium. */
@font-face {
  font-family: "Vazirmatn Fa";
  src: url("fonts/Vazirmatn-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0600-06FF, U+200C-200D, U+FB50-FDFF, U+FE70-FEFF;
}
@font-face {
  font-family: "Vazirmatn Fa";
  src: url("fonts/Vazirmatn-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0600-06FF, U+200C-200D, U+FB50-FDFF, U+FE70-FEFF;
}

:root {
  /* What the BROWSER paints for us, which is not nothing.
   *
   * Scrollbars inside a panel, the caret in a text field, the little calendar
   * on a date input: the browser draws all of those and no rule here can
   * reach them. This is the only thing that tells it which palette to use.
   *
   * It USED to be the answer for a `select`'s list as well, and it was not
   * good enough. That list is a window of the operating system's, and a
   * customer photographed a white one standing over the dark interface with
   * this declaration in place. Worse, no check could ever have seen it: a
   * window outside the document does not appear in a screenshot of the
   * document. The list is drawn by `web/selectlist.js` now, further down this
   * file under "The list a select opens" - so it is ours, it is in the page,
   * and it is photographed on demand.
   *
   * Keep this. What it still covers is real. It is simply not the whole
   * answer it was written as. The light half is in shell.css, inside
   * `:root.light`. */
  color-scheme: dark;

  /* A calmer, deeper neutral scale for long sessions — a clear three-step
     elevation (ground → panel → raised) reads as depth without brightness, and
     the text is a soft off-white rather than pure white to avoid halation.
     Semantic up/down stay the sober teal-green and soft red (the +/- and
     BUY/SELL labels carry the meaning for colour-blind eyes). */
  /* ---- the surfaces ----
     A deep blue-black rather than a neutral grey, taken from the design the
     owner chose. Adobe's greys were here before and their neutrality was the
     whole point of them; this is a different intention, not a drift.

     What is *not* taken from that design is its spacing. Its own surfaces sit
     very close together - which is what gives the picture its flat, deep look
     - and measured against the bars this interface is held to, four of them
     fail: the chart and a panel 1.06 apart where 1.15 is asked, a panel and
     the thing raised on it 1.10, a divider 1.32 against 1.40, the smallest
     writing 4.34 on a panel against 4.50.

     So every step below keeps the luminance the grey it replaces had - solved
     for, not judged by eye - and is only turned blue. The bars come out
     exactly where they were and the screen is the one that was asked for.

     The three that carry writing are tinted at a third of the saturation the
     surfaces get. A page whose text is as blue as its panels reads as a
     coloured page; this reads as a dark room.

     Saturation 9%, and the room is no longer a colour at all - which is
     the point rather than a side effect.

     Counted before this: of the twenty-one pairs of meanings that share
     this screen, four sat closer than thirty-two degrees of hue - the
     candle green and the accent six apart, the two greens fourteen, the
     red and the gold eighteen. One cause, not four. At 27% on hue 218
     the chrome held the slot on the wheel where an accent belongs, so
     the accent was pushed onto cyan, the cyan landed beside a rising
     candle, and everything after that was a consequence.

     The blue has not left the program; it has moved from the walls to
     the thing you press. `--accent` is a blue at 210 now, which is what
     "selected" is in every platform a trader has already used.

     Every surface and grey below is its old value at a third of the
     colourfulness and exactly the luminance, so nothing that was
     legible changes by more than a hundredth.

     The history, kept because it is the risk. Saturation 29% stood here
     for one
     release and was raised to 45% for reading as "dark" rather than as
     "blue" on a screen full of candles. This is not that decision being
     forgotten. What changed in between is the accent: it was a violet
     then, a colour with nothing to do with the room, and the room had to
     carry the blue by itself. It is a cyan now, 39 degrees away and the
     brightest thing on the screen - and a quieter room is what lets it
     carry. Chosen off pictures of the program itself, eight grounds side
     by side with the cyan standing in each, rather than off a swatch.

     Lowering it costs nothing on any bar, because what is held constant
     here is luminance and not lightness: every value below is the 45%
     one with its colourfulness scaled and its luminance solved back to
     where it was, to within a fifth of a byte. Every ratio in the
     program is the number it was. */
  /* The spacing scale. Four steps and nothing between them.

     Counted on a running page before this existed, the side column used
     nine different gaps and the three commonest were 1, 6 and 2 pixels:
     one, two, three, four, five, six, eight, nine and eleven all at
     once. Rhythm is not something a reader can name and it is the first
     thing they feel; nine values have none. */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;

  /* One point darker than it was, which is the whole move: the step up
     to a panel measured 1.143 where this theme holds itself to 1.15.
     The ground gives rather than the panel, because the panel carries
     nearly all the writing and lifting it would have cost every line of
     it - this way every ratio on the ground improves instead. */
  --bg:        #0c0d0f;   /* behind the canvas */
  --panel:     #1b1d20;   /* a panel */
  --panel-2:   #2d3036;   /* a panel header, or something raised */
  --panel-3:   #464b54;   /* a step above that again */
  --line:      #464b54;   /* the separator between panels. The same value as
                             the surface above it on purpose: they were the same
                             step in the scale this came from, and had been
                             within two of each other before that. */
  --line-soft: #000000;   /* the dark one, for hairlines inside a panel. A
                             groove rather than a divider, so it is not held to
                             the 1.4: it is meant to be felt rather than seen. */
  --text:      #ebebec;
  --dim:       #aeb0b3;
  /* Nine points lighter than gray-500, and the nine points are the whole
     story of how a value can be right and still be wrong.

     It was solved against a panel and against the chart, where it measured
     5.08 and 6.33 and cleared the 4.5 bar with room. Nobody solved it against
     --panel-2, which is a step darker again and is what almost every caption
     in this program actually sits on: a tab strip, a picker row, a dialog
     head. There it measured 4.02, and twelve captions were under the floor -
     "Trades", "Floating", "Symbol", "48 instruments", the star, the caret.

     A colour is only as good as the darkest thing it is put on. This one is
     now solved on the darkest of the four, where it makes 4.51, and every
     lighter surface follows: 5.76 on a panel and 6.58 on the chart. It is
     still well below --dim, so the three greys keep their order. */
  --faint:     #94979b;

  /* The pair most charts use, at the hue a trader has already spent years
     reading: the teal-green at 174 rather than the 157 Spectrum's green sat
     at. Picked off a close-up of a real year of EURUSD rather than off
     swatches, because a candle colour is hundreds of small filled shapes in
     bulk and nothing smaller than that shows how it behaves.

     Quoted as `#26a69a`, and lifted from there. These are read as text as
     well as drawn as shapes - a profit figure, a SELL label - and this holds
     writing to 4.5 against the worst ground it lands on, which is a raised
     surface. Hue and saturation held; only the lightness moved. */
  --up:        #27aa7e;
  /* Turned eleven degrees towards orange, from hue 1 to hue 12, and picked
     off a picture of the program rather than a swatch.

     Two things worth knowing about this value. It is measurably *more*
     legible than the red it replaces - 7.70 against the chart where that was
     6.57 - because turning a red towards orange lifts it, and the lift was
     kept rather than solved away.

     And it moved towards the gold at the same time as the gold moved towards
     it. Apart they measured 27 and 29 degrees from the other's old value;
     together they are 18, which is inside the distance this palette treats as
     close. A news mark and a falling candle are relatives now. That was the
     owner's call, made with the number in front of them, and it is written
     here so the next person to open this file does not have to find it out
     from the screen. */
  --down:      #f1866b;
  /* ---- which way a trade was taken ----
     Not the same thing as the accent, though it was the same token until the
     two were separated: `--accent` is what is selected, focused or active;
     this is what a *buy* is - on the ticket, in the trades table, on the
     closed-trade card and on the chart. Thirty-seven places were reading
     this one and meaning the other.

     Green, and green is now reserved for it: a buy is green in every window
     and in both languages, and nothing else on the ticket may be. This was
     gold, for a reason that is written out under `--gold` below and no longer
     applies - the owner's instruction is that a buy is green, full stop.

     The green the watchlist used for crypto, which is why that group had to
     move. It went to the gold first, and the gold was already metals' - four
     degrees apart, so the watchlist had two markets in one colour until
     somebody said so. Crypto is cyan now, at hue 188; the reasoning and the
     numbers are with the colour, in shell.css.

     It does NOT follow the candle green, and the rule is what stopped it.
     The candles moved to the platform pair at hue 174, and this was taken
     with them - until the guard that holds the owner's rule failed it, which
     is exactly its job. "Green" there means the green channel clear of both
     others by a quarter of the range; at 174 it clears the red easily and the
     blue by 13. That colour is a teal. It reads as one, it would have sat six
     degrees from the accent, and a buy would have been the same colour as a
     chosen control.

     So a candle can be teal and a buy cannot. They were separate tokens
     already, for this reason.

     5.49 against a panel and 6.28 against the chart, so it holds as writing
     as well as as a fill. */
  --buy:       #26a67b;
  --sell:      #f1866b;
  /* The same two directions, as something filled rather than as something
     written.

     `--buy` and `--sell` above are read: a price, a label, a border, the tint
     behind a row. These are painted: the big Sell and Buy buttons, and the
     two halves of the order card in the chart menu.

     They had been the same tokens, and it worked for the green by luck - it
     was already mixed as a fill - and not at all for the red, which is a text
     colour and looked highlighted next to a painted button. Twenty-eight
     points of lightness between them.

     Taking the red down to the green's weight was the obvious repair and it
     is not available while the two share a token: the SELL price is the same
     value, and it falls from 4.58 on its tile to 2.19. So they are separate
     now, and only the red gains anything - `--buy-solid` is the green
     unchanged, named for the job it was already doing.

     Matched on lightness, not luminance. Solved for the green's luminance the
     red comes back out at 61% lightness, which is the pale salmon this began
     as: a saturated red at a green's luminance always reads lighter than it. */
  --buy-solid:  #26a67b;
  /* USDT's own colour in the world. Five points from --buy-solid and kept
     apart from it on purpose: one means «buy», the other means «tether», and
     a subject keeps its colour wherever it appears. */
  --usdt:       #26a17b;
  --sell-solid: #ba3412;

  /* What is legible on a filled buy or a filled sell.
     White on the green is 3.08 to one and on the red 2.85 - both under the
     4.5 the smallest writing here is held to, on the two largest buttons on
     the panel. Near-black on each takes them to 6.14 and 6.7. The buy's ink
     is tinted with its own hue rather than left the gold's warm black, which
     was mixed for a colour that is no longer there. */
  --on-buy:    #04140d;
  /* White, because the red it sits on is a deep one now: 5.85 to one, where
     near-black on it would be 3.37. */
  --on-sell:   #ffffff;
  /* What is selected, focused or active.
     *
     * A cyan, and the hue was measured rather than liked.
     *
     * An accent here has two things to stay clear of, and the second one only
     * appeared when the surfaces stopped being neutral grey. It must not be
     * mistaken for a colour that already means something - the buy green, the
     * sell red, the gold, the dots on the instrument groups - and it must not
     * disappear into the room, which is now a blue one at hue 218.
     *
     * The violet that stood here was 36 degrees from the nearest meaning and
     * only 41 from the room: beside the ground rather than out of it, which
     * is what made it read as foreign. This is 38 from the room and, of the
     * cold colours, the furthest from it that is not itself near a meaning.
     *
     * The caution, once: it is 20 degrees from the buy green. They differ in
     * every other way - the buy green is far lighter and far more saturated -
     * and they never appear as the same kind of thing, one being a filled
     * control and the other a direction. But it is the closest of the three
     * that were shortlisted. */
  --accent:    #3278bd;
  --accent-2:  #2a639d;   /* the far end of the accent's gradient */
  /* The accent when it is WRITING rather than a fill.
     The accent is designed to be a surface with --ink on top of it, and on a
     panel that is all it is ever asked to be. On the chart ground it is asked
     to be a glyph instead - the "now" mark - and there it measures 4.19, under
     the 4.5 a small mark needs. Six points lighter clears it at 4.55 without
     moving the hue at all, so it is the same blue and not a second one. */
  --accent-ink: #387ec3;
  /* The market colours when they are WRITING rather than candles.

     The candles are hundreds of filled shapes and were picked by eye on
     a real year of EURUSD; a figure is nine characters at twelve pixels
     and is picked by measuring. They were one value for both jobs, and
     the value that suits a candle is not required to clear 4.5 as text.

     Only the green needed moving here, and only just: on --panel-2 it
     measured 4.496 against a floor of 4.5, four thousandths under. The
     red is 5.27 and is carried across unchanged so the pair stays one
     idea. The candles are untouched. */
  --up-ink:    #27ac7f;
  --down-ink:  #f1866b;
  /* The gold clears its ground in this theme at 6.94, so the writing
     weight and the mark are the same colour. The token exists anyway,
     because the light theme needs it and a name that means one thing in
     one theme and nothing in the other is worse than a repeated value. */
  --gold-ink:  #b89728;
  --ink:       #ffffff;   /* what is legible ON the accent, as Adobe sets it */
  /* ---- the one colour here that is not Adobe's ----
     `#d4a03c` was this application's accent before the palette became
     Photoshop's, and losing it left a screen with no colour of its own: grey,
     Adobe's blue, and the green and red that belong to the market.

     It is back with one job, which is the opposite of the blue's. Blue acts -
     what is selected, what is pressed, what has focus. Gold marks - a starred
     instrument, a news event, a reading worth a second look, a licence with
     days left on it.

     It carried a second job for a while - it was also what a *buy* was - and
     that job has gone back to green on the owner's instruction. The reason it
     was ever gold is worth keeping written down, because it is a real cost
     that is now being paid: direction in the money colours means a losing buy
     wears a green badge on the same row as its red loss. `--up`/`--down` and
     `--buy`/`--sell` are still separate tokens, so the two greens are
     different greens and a row is still readable; they are simply both green
     now.

     At hue 46 now. It was 39, then 30 towards amber - and at 30 it sat
     eighteen degrees from the red, which is close enough that a news
     mark and a falling candle read as relatives. Solved for the gap
     rather than picked: 34 degrees from the red, which is the widest
     any two meanings on this screen were before this pass. It is the only
     other warm colour in the palette, so this is the one direction it
     has that costs something: see the note under `--down`.

     5.99 against a panel and 6.85 against the chart. */
  --gold:      #b89728;

  /* The crypto market's own colour in the watchlist.

     A token and not a literal in the rule, because it needs a value per
     theme - `--cat` is read as well as seen, it colours the ticker on the
     row you are looking at - and because a dark literal outside a palette is
     exactly what the guard further down forbids. It caught this one.

     Why it is not the gold any more, and why hue 188, is written where it is
     used: shell.css, under `[data-cat="crypto"]`.

     5.39 : 1 on the card it sits on. */
  --cat-crypto: #24b5cc;

  /* The news marks had been borrowing --accent, which is also the highlight
     on every selected control: one could not be changed without the other.

     The same gold, under its own name and with its own copy of the value.
     The settings window offers this one as "News marks" and saves a
     customer's choice against this name, so it cannot become `var(--gold)`
     without orphaning what they saved - and should not, either: recolouring
     the news marks is not a request to recolour a warning.

     Its own copy, and so it has to be turned by hand whenever the gold
     turns - which is the price of the separation and is paid here. */
  --news:      #b89728;

  /* Cosmetic depth + focus, used by the polish layer at the end of this file. */
  /* ---- light, depth and colour ----
     None of these carries meaning: a customer never has to read one, so none
     of them is bound by the contrast floors. What they are for is the thing
     those floors cannot give - a surface that has a top and a bottom, a mark
     that glows, a window that opens with somewhere to look. */
  --sheen: inset 0 1px 0 rgba(255,255,255,.05);
  --lift: linear-gradient(180deg,
            color-mix(in srgb, var(--panel-2) 55%, transparent), transparent 62%);
  /* Flat, like a Photoshop panel header. This used to be a wash of the accent
     across the top of every window, which is the one thing that kept putting
     blue back into a palette whose whole character is that it has none. */
  --wash: radial-gradient(120% 150% at 12% -40%,
            rgba(255,255,255,.04), transparent 60%);
  /* `--lift` tints the top of a surface that is *see-through*; `--top` is the
     same idea for one that is not - a highlight along the upper edge, which is
     what makes a card look like a thing sitting on something rather than a
     rectangle cut out of it. */
  --top: linear-gradient(180deg, rgba(255,255,255,.045), transparent 60%);
  /* ---- a field -----------------------------------------------------------
     One step away from whatever is under it, rather than a fixed grey.

     Every form field in the program used to be painted `--panel-2`, which is
     also the ground of a panel header - so a field sitting on one vanished
     into it, and the same value on `--bg` read as a raised tile. The colour
     was describing the paint rather than the relationship, and the
     relationship is the whole of what a field looks like.

     Translucent, so the step is taken from the surface actually underneath
     and comes out right on a panel, on a sheet, on the ground, and on
     anything added later that nobody thought about. White here; the light
     theme turns it over, because on paper a field is a shade DOWN from the
     card and a white one on near-white is nothing at all. */
  --field:       rgba(255,255,255,.055);
  --field-hover: rgba(255,255,255,.085);
  --field-h: 34px;    /* one height, everywhere */
  --field-r: 9px;     /* one corner. There were five */
  --field-pad: 11px;
  /* The mark that says a box opens. A chevron inside a soft square, which is
     the one part of this the shape is recognised by - see design 1 in
     `design/select-ten.html`. It cannot take `currentColor`, being a data
     URI, so each theme carries its own. */
  --caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Crect x='.5' y='.5' width='19' height='19' rx='6' fill='%23464b54'/%3E%3Cpath d='M6.6 8.6 10 12l3.4-3.4' fill='none' stroke='%23d7d9dc' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* How tall the bar across the top is. Said once: three other rules
     subtract it from the window to size what is underneath, and they
     were three separate literals. */
  --topbar: 38px;
  /* The other side of the same idea: a track sunk into the surface
     rather than raised off it. */
  --well: inset 0 1px 2px rgba(0,0,0,.4);
  /* The ground a window body sits on. Much softer than `--wash`, which is for
     a header: this one covers the whole sheet and must never be noticed. */
  /* Nearly nothing, and grey rather than blue. Photoshop's panels are flat;
     what little is here is there to give a window somewhere to look, not to
     put a colour back that the palette does not have. */
  --ground: radial-gradient(90% 65% at 15% -10%, rgba(255,255,255,.035), transparent 62%);
  --glow: 0 6px 18px -8px color-mix(in srgb, var(--accent) 70%, transparent);
  --glow-soft: 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
  --elev-1: 0 1px 2px rgba(0,0,0,.35);
  --elev-2: 0 14px 40px -12px rgba(0,0,0,.6), 0 2px 8px -4px rgba(0,0,0,.5);
  --ring:   color-mix(in srgb, var(--accent) 62%, transparent);

  /* Three surfaces that were written as literals all over the stylesheet and
     so could not be themed at all. The values are the ones that were already
     being used, so the dark theme is unchanged by naming them.

       --hover        what a control sits on while the pointer is over it
       --line-strong  the border of that same control, one step up from --line
       --sel          the block behind a chosen item in a group

     The last one is why this matters: `.seg button.on` was a hard-coded dark
     block carrying `color: var(--text)`, which in light mode is dark text on
     a dark background. */
  --hover:       #2d3036;   /* a panel with the pointer over it: one step up
                               from the panel, and therefore the same value as
                               `--panel-2` */
  --line-strong: #656c77;
  --sel:         #2c5177;   /* the accent, sunk into a panel, as a chosen row.
                               Solved against the track it actually sits on:
                               1.61 against `--panel-2`, where the value before
                               it managed 1.13 and a chosen chip was all but
                               indistinguishable from an unchosen one. It had
                               been matched to the luminance of a much darker
                               palette and left behind when the surfaces were
                               lifted to the blue.
                               Solved to the same luminance the blue one had,
                               so a chosen row is exactly as loud as it was. */

  /* THE typographic decision. Numbers are most of what is on this screen and
     they were set in the body font. `--mono` is now Bahnschrift: a DIN
     grotesk with real tabular figures, on every Windows since 2017, so
     nothing is shipped and nothing is licensed.

     Code keeps a true monospace of its own — Bahnschrift's letters are not
     fixed width, and a Pine script needs them to be. */
  /* ---- what sits over what, on the chart ----
     The chart carries permanent furniture - the buy/sell strip, the reading,
     the list of indicators - and it carries panels somebody opens: the
     starred tools, the style bar for a selected drawing, what is
     downloading. A panel that was opened is being looked at, so it goes over
     the furniture; the furniture is always there and does not.

     One token because the numbers had drifted: the strip was 8 and three of
     the panels were 7, 7 and 6, so every one of them opened underneath it. */
  --layer-float: 20;

  /* Bahnschrift for the digits, and **Vazirmatn behind it for everything it
     cannot draw**.
   *
   * Bahnschrift has no Persian in it at all. Every place this token is used
   * that can also carry a word — and there are many, because a figure usually
   * has a label beside it — fell through Bahnschrift to whatever Windows
   * offered next, which is Tahoma. Reported from the chart: the stop and
   * target pills, whose words are `t('SL')` and `t('TP')` and are Persian,
   * drawn on a canvas at `10px var(--mono)`.
   *
   * A canvas falls back per GLYPH exactly as CSS does, so putting Vazirmatn
   * in the list costs the digits nothing — Bahnschrift still draws them, and
   * still lines them up — and means no Persian anywhere in the application
   * can land on a face that was never chosen. Fixed in the token rather than
   * at the twenty-odd places that use it, because the next one added would
   * have had the same fault and nothing would have said so. */
  --mono: "Vazirmatn Fa", Bahnschrift, "DIN Alternate", "Segoe UI", system-ui, sans-serif;
  --code: "Vazirmatn Fa", "Cascadia Mono", "JetBrains Mono", Consolas, "SF Mono", monospace;
  /* Vazirmatn ships with the application. Windows has no Persian face worth
     the name — Segoe falls back to Tahoma — and it is the single biggest
     reason the Persian half used to look machine-made. */
  --ui: Vazirmatn, "Segoe UI", Inter, system-ui, sans-serif;
}

@font-face { font-family: Vazirmatn; font-weight: 400; font-display: swap;
  src: url(fonts/Vazirmatn-Regular.woff2) format("woff2"); }
@font-face { font-family: Vazirmatn; font-weight: 500; font-display: swap;
  src: url(fonts/Vazirmatn-Medium.woff2) format("woff2"); }
@font-face { font-family: Vazirmatn; font-weight: 700; font-display: swap;
  src: url(fonts/Vazirmatn-Bold.woff2) format("woff2"); }

* { box-sizing: border-box; }

/* Controls do not inherit the page's font. Nothing about a `<button>` says it
   should be set in the same face as the words around it, so unless this is
   here the browser uses its own - Arial, at its own size - and the interface
   ends up in two typefaces.
 *
 * Said once, for every control there is. It had been said one rule at a time
 * instead, about thirty times, and the eighty controls that were missed were
 * the ones somebody eventually noticed. Anything that wants its own face -
 * a figure in `--mono`, a script in `--code` - says so in its own rule and
 * wins on specificity. */
button, input, select, textarea { font: inherit; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--text);
  font: 13px/1.45 var(--ui);
  overflow: hidden;
  user-select: none;
}

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums;
        font-feature-settings: "tnum" 1; letter-spacing: .2px; }
.sub  { color: var(--dim); font-size: 11px; }
.hidden { display: none !important; }
.spacer { flex: 1; }

/* ---------- top bar ---------- */

#topbar {
  height: var(--topbar); flex: 0 0 var(--topbar);
  display: flex; align-items: center; gap: 8px;
  padding: 0 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  /* Nothing here may widen the page: the side panel is sized off the viewport,
     so a top bar that overflows pushes the account figures off the screen.
     But `hidden` was the wrong way to hold that line — it silently ate the
     buttons at the end. In Persian, where every label is longer, the settings
     and session buttons were already 16px off the edge and unreachable at
     1400px, with nothing to suggest they existed. Scrolling keeps the page
     the same width and keeps every control reachable. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
#topbar::-webkit-scrollbar { height: 4px; }
#topbar::-webkit-scrollbar-thumb { background: var(--line); border-radius: 2px; }
#topbar > * { flex-shrink: 0; }
.spacer { flex: 1 1 0; min-width: 0; }

.chip {
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 11px; font: inherit; cursor: pointer;
  white-space: nowrap;
}
.chip:hover { border-color: var(--line-strong); background: var(--hover); }
/* Gold, which in this interface already means "worth a second look" - the
   favourite star, the news flag, the tip card. A row of grey chips is a row of
   housekeeping; this one opens the pictures. A tint and a border rather than a
   filled button, because filled is what the one action that commits something
   looks like, and looking at pictures commits nothing.
   
   The gold is the border and the face, never the writing. Written in
   `--gold-ink` the label measured 3.93 against its own face in the dark theme
   and 4.22 in the light one, both under the 4.5 floor - and it looked perfectly
   fine, which is how it nearly shipped. 24% is where the face clears 1.15
   against the row behind it in the light theme (1.24) without dulling the
   label: 7.6 dark, 9.18 light. */
.chip.gold {
  border-color: color-mix(in srgb, var(--gold) 55%, var(--line));
  background: color-mix(in srgb, var(--gold) 24%, var(--panel-2));
}
.chip.gold:hover {
  border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 34%, var(--panel-2));
}
.chip.strong { font-weight: 600; font-size: 14px; letter-spacing: .3px; }
.caret { color: var(--faint); margin-left: 6px; }

/* The chart-type chip holds a drawn chart rather than a character, so the
   button has to lay its two children out on a line instead of relying on the
   text baseline an SVG does not sit on. */
button[data-topmenu="type"] { display: inline-flex; align-items: center; }
#typeIcon { display: inline-flex; align-items: center; }
#typeIcon svg { display: block; }

#rail .rico { display: block; }

/* Chart-settings checkbox rows: one tidy column of evenly-spaced ticks, the box
   pinned to the leading edge and aligned with its label. Kept `direction: ltr`
   so the tick sits in the same place in Persian as in English — the layout is
   translated, not mirrored. Scoped under `.pad.grid2` to override the column
   label / bordered-input styling the settings grid otherwise imposes. */
/* Two to a line. Eight switches in one column is eight lines of a window
   that has width to spare and no height at all; and once the labels became
   names rather than sentences, two fit side by side with room left. */
/* Anything in the account grid that is a sentence rather than a field takes
   the whole line: a note, a switch with a name long enough to read, or the
   heading over the two settings that came out of the chart window. */
.pad.grid2 > .wide { grid-column: 1 / -1; }
.pad.grid2 > .secline.wide { margin: 14px 0 2px; }
.pad.grid2 > .tg.wide {
  display: flex; flex-direction: row; align-items: center; gap: 10px;
  padding: 6px 0; font-size: 12.5px; color: var(--text); cursor: pointer;
  text-align: start;
}

.checklist { grid-column: 1 / -1; display: grid;
             grid-template-columns: 1fr 1fr; gap: 2px 8px; }
.pad.grid2 .checklist .tick {
  display: flex; flex-direction: row; align-items: center; gap: 10px;
  direction: ltr; text-align: left;
  padding: 8px 10px; border-radius: 10px;
  font-size: 12.5px; color: var(--text); cursor: pointer;
  transition: background .12s ease;
  /* Two columns means half the room, so a label that outgrows its half has
     to wrap inside it rather than push the grid wider than the window. */
  min-width: 0; overflow-wrap: anywhere;
}
.pad.grid2 .checklist .tick:hover { background: var(--panel-2); }
.pad.grid2 .checklist .tick input[type=checkbox] {
  width: 16px; height: 16px;
}

/* ---------- session shading ---------- */
/* Same shape as the tick rows above and scoped the same way, so the settings
   grid's column-label styling does not turn each row into a stack. */
/* Drawn by what it is, not by which window holds it. Every rule below was
   written as `.pad.grid2 .shadelist …`, and when chart settings stopped being
   a two-column grid all nine stopped matching at once - the rows came apart
   into a bare checkbox, a name run into its hours, and a browser-sized colour
   box. `.shadelist` appears in one place in the program; the prefix was never
   doing any work. */
.shadelist { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 1px; }
.shadelist .shaderow {
  display: flex; flex-direction: row; align-items: center; gap: 10px;
  direction: ltr; text-align: left;
  padding: 6px 9px; border-radius: 7px;
  font-size: 13px; color: var(--text); cursor: pointer;
  transition: background .12s ease;
}
.shadelist .shaderow:hover { background: var(--panel-2); }
.shadelist .shaderow input[type=checkbox] {
  width: 16px; height: 16px;
}
.shadelist .shaderow .flag { font-size: 16px; line-height: 1; }
.shadelist .shaderow .name { min-width: 88px; }
/* The hours push to the far end so all four line up and read as one day. */
.shadelist .shaderow .when {
  color: var(--dim); font-size: 12px; font-variant-numeric: tabular-nums;
  margin-inline-start: auto;
}
.shadelist .shaderow .swatch {
  width: 34px; height: 22px; flex: 0 0 auto; padding: 0;
  border: 1px solid var(--line); border-radius: 5px;
  background: var(--glow); cursor: pointer;
}
/* The strength slider sits with the sessions it applies to, but it is not one
   of them: no switch, no colour, and no hover highlight to click. */
.shadelist .shaderow.strength { cursor: default; padding-top: 10px; }
.shadelist .shaderow.strength:hover { background: none; }
.shadelist .shaderow.strength .name { color: var(--dim); font-size: 12px; }
.shadelist .shaderow input[type=range] { flex: 1; }
.shadelist .shaderow.strength .when { min-width: 34px; text-align: end; }

/* Off keeps its colour readable but stops the row shouting. */
.shadelist .shaderow.off .flag,
.shadelist .shaderow.off .name,
.shadelist .shaderow.off .when { opacity: 0.45; }

/* The MetaTrader tab's read-out (Check result, export status, folder path). A
   proper panel, not a whisper of grey text — a text-only answer was being read
   as "nothing happened". Only shows when it actually has something to say. */
#mt5Out:not(:empty) {
  display: block; margin-top: 10px; padding: 11px 13px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 8px; font-size: 13px; line-height: 1.8; color: var(--text);
}
#mt5Out b.up { color: var(--up-ink); }
#mt5Out b.down { color: var(--down-ink); }

.tfs { display: flex; gap: 2px; background: var(--panel-2);
       border: 1px solid var(--line); border-radius: 6px; padding: 2px; }
.tfs button {
  background: none; border: 0; color: var(--dim);
  padding: 4px 7px; border-radius: 4px; cursor: pointer; font: inherit;
}
.tfs button:hover { color: var(--text); }
.tfs button.active { background: var(--accent); color: #fff; }

.clock { display: flex; align-items: baseline; gap: 8px; }
.clock .big { font-size: 17px; font-weight: 600; letter-spacing: .5px; }
/* Which clock this is, and the way to change it (clockcard.js). */
.zonechip { display: inline-flex; align-items: center; gap: 6px; align-self: center;
  padding: 3px 10px; border-radius: 999px; background: var(--field);
  border: 1px solid var(--line); color: var(--dim); font-size: 12px; cursor: pointer; }
.zonechip:hover { background: var(--field-hover); }
.zonechip b { color: var(--text); font-weight: 600; }
.zonechip .car { opacity: .7; font-size: 10px; }
/* The chip's short form, for a top bar short of room (below). */
.zonechip .cz-short { display: none; color: var(--text); font-weight: 600; }
.clockcard { position: fixed; z-index: 45; /* under every .modal (50) */ width: 360px; max-width: calc(100vw - 16px);
  padding: 14px 16px 12px; border-radius: 12px; background: var(--panel-2);
  border: 1px solid var(--line); box-shadow: 0 14px 40px rgba(0,0,0,.45), var(--sheen);
  color: var(--text); font-size: 13px; line-height: 1.8; }
.clockcard::before { content: ''; position: absolute; top: -7px; left: calc(var(--arrow, 50%) - 6px);
  width: 12px; height: 12px; background: var(--panel-2);
  border-left: 1px solid var(--line); border-top: 1px solid var(--line); transform: rotate(45deg); }
.clockcard h4 { margin: 0 0 4px; font-size: 14px; }
.clockcard p { margin: 0 0 10px; color: var(--dim); }
.cz-tiles { display: flex; gap: 10px; margin: 6px 0 12px; }
.cz-tile { flex: 1; padding: 8px 10px; border-radius: 10px; background: var(--field); text-align: center; }
.cz-tile small { display: block; color: var(--dim); font-size: 11px; }
.cz-tile b { font-size: 18px; font-variant-numeric: tabular-nums; }
.cz-tile.lit { outline: 1px solid var(--gold); }
.cz-row { display: flex; gap: 8px; }
.cz-row .primary { flex: 1; }
.cz-note { color: var(--faint); font-size: 11.5px; margin-top: 8px; }
.cz-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.cz-pick { display: flex; align-items: baseline; gap: 10px; padding: 8px 10px; border-radius: 10px;
  background: var(--field); border: 1px solid transparent; color: var(--text); text-align: start; cursor: pointer; }
.cz-pick:hover { background: var(--field-hover); }
.cz-pick.on { border-color: var(--accent); }
.cz-pick span { flex: 1; }
.cz-pick b { font-variant-numeric: tabular-nums; }
.cz-pick small { color: var(--dim); font-size: 11px; min-width: 52px; }
.cz-more { background: none; border: 0; padding: 4px 0; color: var(--accent-ink); cursor: pointer; font-size: 12px; }

/* The timeframe chip's menu: today's list, one's own among it, and the card
   with the way to make one (toolbar.js `openTfMenu`, the owner's option 3 in
   design/tf-options.mjs). Its own rules rather than
   `.topmenu`'s grid, whose every-button subgrid would reach the card. */
.tfmenu { position: fixed; z-index: 40; min-width: 184px; padding: 5px;
  display: flex; flex-direction: column; gap: 1px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: var(--elev-2); color: var(--text); font-size: 13px; }
.tfmenu .tflist { display: flex; flex-direction: column; gap: 1px; overflow-y: auto;
  overscroll-behavior: contain; }
.tfmenu .tfline { display: flex; align-items: center; border-radius: 6px; flex: none; }
.tfmenu .tfline:hover { background: var(--panel-2); }
.tfmenu .tfline.on { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.tfmenu .tfpick { flex: 1; display: flex; align-items: center; gap: 10px; padding: 6px 10px;
  border: 0; background: none; color: inherit; font: inherit; text-align: start; cursor: pointer; }
.tfmenu .mn, .tfcard .mn { font-family: var(--mono); font-variant-numeric: tabular-nums;
  direction: ltr; unicode-bidi: isolate; }
.tfmenu .tfown { color: var(--faint); font-size: 11px; margin-inline-start: auto; }
.tfmenu .tfdel { width: 26px; height: 26px; flex: none; margin-inline-end: 3px; border: 0;
  border-radius: 5px; background: none; color: var(--faint); font-size: 14px; cursor: pointer; }
.tfmenu .tfdel:hover, .tfmenu .tfdel:focus-visible { color: var(--text); background: var(--panel-3, var(--hover)); }
.tfmenu .mdiv { border: 0; border-top: 1px solid var(--line); margin: 4px 2px; }
.tfmenu .tfmore { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border: 0;
  border-radius: 6px; background: none; color: var(--accent-ink); font: inherit; cursor: pointer;
  text-align: start; }
.tfmenu .tfmore > span:first-child { flex: 1; }
.tfmenu .tfmore:hover, .tfmenu .tfmore.open { background: var(--panel-2); }
.tfmenu .tfchev { opacity: .8; }
.tfmenu button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.tfcard { position: absolute; top: -1px; width: 272px; padding: 12px 14px 14px;
  border-radius: 10px; background: var(--panel-2); border: 1px solid var(--line);
  box-shadow: 0 14px 40px rgba(0,0,0,.45), var(--sheen); line-height: 1.7; }
.tfcard.left { right: calc(100% + 8px); }
.tfcard.right { left: calc(100% + 8px); }
.tfcard.under { top: calc(100% + 6px); inset-inline-start: 0; }
.tfcard h4 { margin: 0 0 2px; font-size: 13.5px; }
.tfcard p { margin: 0 0 10px; color: var(--dim); font-size: 12px; }
.tfform { display: flex; gap: 6px; align-items: stretch; }
.tfform input { width: 54px; padding: 5px 0; text-align: center; border-radius: 7px;
  background: var(--field); border: 1px solid var(--line); color: var(--text); font-size: 13px; }
.tfform input:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.tfunits { flex: 1; display: flex; border: 1px solid var(--line); border-radius: 7px; overflow: hidden; }
.tfunits button { flex: 1; padding: 5px 4px; border: 0; background: none; color: var(--faint);
  font: inherit; font-size: 12px; cursor: pointer; }
.tfunits button.on { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--text); }
.tfunits button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.tferr { min-height: 0; color: var(--down-ink); font-size: 11.5px; line-height: 1.6; margin-top: 4px; }
.tferr:empty { display: none; }
.tfadd { width: 100%; margin-top: 8px; }

.transport { display: flex; align-items: center; gap: 4px; }
.icon {
  width: 32px; height: 30px; border-radius: 6px;
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--text); cursor: pointer; font-size: 12px;
}
.icon:hover { background: var(--hover); }
.icon.play { width: 42px; font-size: 14px; }
.icon.play.on { background: var(--accent); border-color: var(--accent); color: #1a1206; }

/* ==========================================================================
   A field
   ==========================================================================
   Reported as: I do not like this way of choosing that you have put through
   the whole application, I do not think it is pretty.

   It was not one way. `design/select-review.mjs` counted the boxes in the
   running program and found seven descriptions of a select, five corner radii
   and five grounds: the one in the laboratory, the one in the journal
   filters, the one in the builder, the one on a sheet and the one in the
   challenge form were five different-looking controls doing the same job.
   Nothing on screen said which family a box belonged to, because there were
   no families.

   There is one description now. The six rules that competed with it have had
   their boxes taken away and kept only what is genuinely theirs - a width, a
   flex, a direction. Taken away rather than out-weighed: out-weighing leaves
   two answers in the file and the next person cannot tell which is live,
   which is the same reason the dead `.labnav` rules came out when the
   laboratory was rebuilt.

   Three faults that were not the complaint and are fixed by the same edit:

   `:disabled` did not exist anywhere. A select nobody was allowed to use
   looked exactly like one they were.

   The ground was a fixed grey - see `--field` above for why that cannot be
   right on two different surfaces.

   And the text boxes. These rules never described selects on their own:
   `.addrow select, .addrow input` is a single declaration, and so are four of
   the others. Unifying the selects and leaving the inputs would have made a
   select and the box beside it stop matching, which is a worse fault than the
   one being fixed. So this covers both, and they go on matching.
   ========================================================================== */
select, textarea,
/* `input:not([type])` is on every one of these lists, and it is the whole
   of a reported fault. An <input> with no type attribute IS a text input,
   but `input[type=text]` matches the attribute, not the behaviour - so
   thirteen fields written without one (the instrument search, the watchlist
   filter, the challenge's name, the account's username, the discount code,
   the two-factor code...) took none of this and wore the browser's own box.
   «This search field is ugly» was one of the thirteen. */
input[type=text], input[type=number], input[type=search], input:not([type]),
input[type=date], input[type=time], input[type=password] {
  box-sizing: border-box;
  height: var(--field-h);
  /* And it keeps that height. A field is a flex item in a great many rows
     here, and in a COLUMN one the default shrink applies to its height: the
     two selects in the laboratory's lower panes measured 22 against everyone
     else's 34 for no reason but that their pane was short. A field being
     squashed is never the right answer to a container running out of room. */
  flex-shrink: 0;
  padding: 0 var(--field-pad);
  background-color: var(--field);
  background-image: var(--top);
  border: 1px solid var(--line);
  border-radius: var(--field-r);
  color: var(--text);
  font: 500 12.5px var(--ui);
  box-shadow: var(--sheen);
  transition: border-color .12s, background-color .12s, box-shadow .12s;
}
/* A search says so: a small glass at its start, and the placeholder set in
   after it. Only the two fields that search - the instrument picker and the
   watchlist filter - and nothing else, because a glass on a field that is not
   a search is a lie. */
input[type=search] {
  padding-inline-start: 30px;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2394979b' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='4.2'/%3E%3Cpath d='M10.2 10.2 13.5 13.5'/%3E%3C/svg%3E"), var(--top);
  background-repeat: no-repeat, repeat;
  background-position: 10px center, 0 0;
  background-size: 14px 14px, auto;
}
/* Persian: the glass goes to the end the text starts from. `:dir(rtl)` was
   the first attempt and this engine does not honour it - measured, the glass
   stayed at 10px from the left under a right-to-left placeholder - so the
   program's own mark for Persian is used, the same one every other Persian
   rule in this file keys on. */
body.fa input[type=search] { background-position: calc(100% - 10px) center, 0 0; }
input[type=search]::-webkit-search-cancel-button { -webkit-appearance: none; }

/* A box you write a paragraph into has no business being one line tall. */
textarea { height: auto; min-height: 68px; padding: 8px var(--field-pad); }

/* A figure, in both languages.
   Eight rules had reached for `var(--mono)` on their own - the challenge
   form, the indicator row, the builder, the stepper, the order ticket, the
   journal field, the grid and the top of a chart - and a ninth turned it on
   in Persian only, which left an English number in a proportional face for
   no reason anybody could give. Figures line up in a column or they do not;
   that is a property of a number, not of a window. */
input[type=number], input[type=date], input[type=time],
input[data-date], input[data-time] {
  font-family: var(--mono); direction: ltr;
  font-variant-numeric: tabular-nums;
}

select {
  appearance: none; -webkit-appearance: none;
  /* Room for the mark, which is 20 wide and sits 7 in. */
  padding-inline-end: 34px;
  background-image: var(--caret), var(--top);
  background-repeat: no-repeat;
  background-position: right 7px center, 0 0;
  background-size: 20px 20px, auto;
  cursor: pointer;
}
/* The mark belongs at the end of the line, and in Persian the end is the
   left. `body.fa` is how the rest of this file asks; `[dir=rtl]` catches the
   pieces that set their own direction, such as the calendar heading. */
body.fa select, [dir=rtl] select {
  padding-inline-end: 34px;
  background-position: left 7px center, 0 0;
}

select:hover:not(:disabled),
textarea:hover:not(:disabled),
input[type=text]:hover:not(:disabled),
input:not([type]):hover:not(:disabled),
input[type=number]:hover:not(:disabled),
input[type=search]:hover:not(:disabled),
input[type=date]:hover:not(:disabled),
input[type=time]:hover:not(:disabled),
input[type=password]:hover:not(:disabled) {
  border-color: var(--line-strong);
  background-color: var(--field-hover);
}
/* One focus.
   There were five: the shared outline in shell.css, and four windows that
   each wrote `outline: none` and then drew something of their own - the
   welcome window a soft ring, the challenge form and the journal a border,
   the chart's ticket a border and a ground. Every one of those four TOOK THE
   RING AWAY and three of them put back less than they removed.
   The welcome window's was the best of the five, so it is the one, and the
   fields come out of the shared outline list in shell.css so the two do not
   stack. */
select:focus-visible, textarea:focus-visible,
input[type=text]:focus-visible, input[type=number]:focus-visible,
input:not([type]):focus-visible,
input[type=search]:focus-visible, input[type=date]:focus-visible,
input[type=time]:focus-visible, input[type=password]:focus-visible {
  outline: none;
  border-color: var(--accent);
  background-color: var(--field-hover);
  box-shadow: var(--sheen),
              0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* ---- a field that is drawn by the box around it -------------------------
   Four controls put the border and the ground on a WRAPPER and leave the
   input bare inside it, because the wrapper holds something else as well: a
   currency beside the figure, a unit, a pair of arrows, a word. Those are
   still right, and all they need from the description above is to be let out
   of its height - which they never had, and which would have grown a chip
   from a word tall to thirty-four. */
.tkbox input, #challenge .rule .rulebox input,
#challenge .chalchips .cchip input, .setfield > .box input {
  height: auto;
}
/* The state that did not exist. A control nobody may use said nothing about
   it, so the only way to find out was to press it and watch nothing happen. */
select:disabled, textarea:disabled, input:disabled {
  background-color: transparent;
  background-image: none;
  border-color: var(--line-soft);
  color: var(--faint);
  box-shadow: none;
  cursor: not-allowed;
}

/* Two sizes, not two controls. The bar across the top is 38 tall and a 34px
   box in it leaves two pixels a side, so the things that live in a bar are
   the same field made small and round. */
#topbar select, #topbar input[type=text], #topbar input[type=search],
.fieldsm {
  height: 28px; border-radius: 999px;
  padding-inline: 12px 30px; font-size: 12px;
  background-size: 16px 16px, auto;
  background-position: right 6px center, 0 0;
}
body.fa #topbar select, body.fa .fieldsm, [dir=rtl] .fieldsm {
  padding-inline: 12px 30px; background-position: left 6px center, 0 0;
}
/* Read this with the rule above it.
 *
 * That one moves every top-bar caret to the left, because in Persian the bar
 * reads right to left. The transport does not: back, play, forward and speed
 * keep their order in every language, so the speed field is a LEFT-TO-RIGHT
 * field sitting in a right-to-left bar - and the two halves of a caret
 * disagreed about which side that is. `padding-inline` resolves against the
 * ELEMENT's direction, which is ltr here, so the 30px of clearance went to the
 * right; the caret was placed against the LANGUAGE, so it was drawn on the
 * left, 6px in, on top of a number that starts 12px in. Photographed and
 * reported as «تو نسخه فارسی عدد افتاده روی ی چیزی x20».
 *
 * `:dir(ltr)` would say this in one line and is the right tool, but it wants
 * Chromium 120 where nothing else in this file needs more than 111. */
body.fa #topbar .transport select {
  background-position: right 6px center, 0 0;
}
#topbar input[type=text], #topbar input[type=search] { padding-inline: 12px; }

/* ==========================================================================
   A choice you can see all of
   ==========================================================================
   Design 7 of the ten in `design/select-ten.html`, drawn by `segselect.js`
   over a select that has two or three answers and no reason to hide either.

   It is the same field, laid open: the same corner, the same one-step-off
   ground, the same border. What it is NOT is a second kind of control - the
   chosen segment is lit the way the accent lights everything else, and the
   track it sits in is the sunk well used for a slider, so nothing here is a
   new idea that has to be learnt.

   The select is still in the page underneath, holding the value. `.seghidden`
   is how it stands aside, and it is `display: none` rather than a visual
   trick because a hidden field that can still be tabbed to is two stops for
   one control. */
select.seghidden { display: none; }

.segsel {
  display: inline-flex; align-items: center;
  padding: 2px; gap: 2px;
  background: var(--field); border: 1px solid var(--line);
  border-radius: var(--field-r); box-shadow: var(--well);
  height: var(--field-h); box-sizing: border-box;
  max-width: 100%;
}
.segsel > .segbtn {
  flex: 1 1 auto; min-width: 0;
  height: 100%; padding: 0 13px;
  border: 0; background: none;
  border-radius: calc(var(--field-r) - 3px);
  color: var(--dim); font: 500 12.5px var(--ui);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  cursor: pointer;
  transition: background-color .12s, color .12s, box-shadow .12s;
}
.segsel > .segbtn:hover:not(.on):not(:disabled) { color: var(--text); }
.segsel > .segbtn.on {
  background: var(--panel-3); color: var(--text); box-shadow: var(--sheen);
}
/* The keyboard stop, which is one stop for the whole control - so the mark
   has to be on the button the keyboard is actually on, not on the group. */
.segsel > .segbtn:focus-visible {
  outline: 2px solid var(--ring); outline-offset: -2px;
}
.segsel > .segbtn:disabled { color: var(--faint); cursor: not-allowed; }
.segsel.off { opacity: .55; box-shadow: none; }

/* A field on a form is as wide as its row; one in a filter bar is as wide as
   its words. The difference is which of them has a caption stacked over it. */
.labfield > .segsel, .setfield > .segsel, label.wide > .segsel { width: 100%; }



/* ==========================================================================
   What the top bar gives up when it is short of room
   ==========================================================================
   `web/topfit.js` adds these one at a time, cheapest first, until the bar
   fits. Nothing here knows a screen width: the module asks the bar whether it
   fits and gives something up if it does not, which is the only way this can
   be true in Persian as well as English and stay true when a label is
   rewritten.

   Measured before any of it existed: the bar wanted 1180px in English and
   1252 in Persian, and the window will not go below 900. So about three
   hundred pixels had to come from somewhere, and this is where from.

   The transport is not in this list and never will be. Back, play, forward
   and speed are what this program is; QA 16.2.1 was the report of exactly
   those four sliding off the end. */

/* 1. The room between things. Six pixels between sixteen items is ninety-six
      of the three hundred, and it is the cheapest thing on the bar. */
#topbar.fitgap { gap: 3px; padding-inline: 5px; }

/* 2. The date. The time stays, and the date is on the chart's own axis and in
      this element's tooltip. */
#topbar.fitdate #clockDate { display: none; }

/* 3. The words on the buttons that have a mark as well. Each keeps its title,
      so hovering still says what it is, and each has a glyph - the two that
      did not were given one when this was written, because a button that is
      only a word has nothing left when the word goes. */
/* A mark and its word need a space between them. The two buttons that gained
   a glyph had their word up against it. */
#topbar .chip > svg + .lbl { margin-inline-start: 5px; }
#topbar.fitword .lbl { display: none; }
/* A chip with nothing but a glyph left should be square, not a wide box with
   a mark rattling around in it. Eight rather than nine because the floor is
   the floor: at nine, 900px came out seven pixels short with everything else
   already given up, and seven pixels is a scrollbar. */
#topbar.fitword .chip { padding-inline: 8px; }
#topbar.fitword .icon { padding-inline: 2px; }
/* And the speed, which is the only field in this bar and the only piece of it
   that got WIDER on 7 September: the shared field description gave every
   select room for a 20px mark, and in a bar that was six pixels from the edge
   that was the six pixels. Given back here rather than taken off the shared
   rule, because the mark is right everywhere it is not this bar. */
#topbar.fitword select {
  padding-inline: 9px 23px;
  background-size: 14px 14px; background-position: right 5px center;
}
body.fa #topbar.fitword select {
  padding-inline: 9px 23px; background-position: left 5px center;
}

/* 4. The clock, all of it. The only one that takes information off the
      screen rather than moving it into a tooltip - though the time under the
      last candle says the same thing. */
/* The time and the date go; the chip that names the clock and opens its
   card stays, as the offset alone (clockcard.js `cz-short`). It went with
   them, and below about 1000 pixels - the desktop's 900-pixel floor, a
   half-screen browser - nothing on screen said which clock the chart was in
   or opened the card (the area-8 review, 2026-09-29, finding 11). */
#topbar.fitclock #clockDate, #topbar.fitclock #clockTime,
#topbar.fitclock #tickMark { display: none; }
#topbar.fitclock .zonechip { padding: 3px 7px; gap: 0; font-size: 11px; }
#topbar.fitclock .zonechip > b, #topbar.fitclock .zonechip > bdi:not(.cz-short),
#topbar.fitclock .zonechip > .car { display: none; }
#topbar.fitclock .zonechip > .cz-short { display: inline; }

/* 5. And last, the two chips that are only sometimes there at all: how many
      days of a subscription are left while it is nearly gone, and how many
      trades a free account has left today. They say the same thing in four
      characters instead of a sentence - «۲ از ۵» rather than «۲ از ۵ معاملهٔ
      امروز» - and the sentence is on the tooltip either way.

      Last because they are the most worth keeping. The trades counter is the
      whole reason a free account can see the wall coming instead of walking
      into it, and the subscription warning is the one interruption in this
      program that is deliberate. They shorten; they do not go.

      This is the step the first version of the fitter did not have, and the
      reason is worth writing down: the probe measured the bar with the
      licence set to `full`, where NEITHER chip exists. Four states, one
      measured. The person it happened to could say exactly when - «کسی که ۵
      تا معامله روزشو زده توی نسخه رایگان ... تو حالت پولیش اوکیه». */
#topbar .tight { display: none; }
#topbar.fitchip .said { display: none; }
#topbar.fitchip .tight { display: inline; }
/* By the time this step is reached the bar has given up everything else, so
   it is also the place to take the last of the padding. Measured: without it
   the worst state - a subscription with two days left, at the 900px floor -
   came out ONE pixel short, and one pixel is a scrollbar. */
#topbar.fitchip .chip { padding-inline: 6px; }
/* 6  the chart's own switches, into a menu. Between 641 and ~777 pixels the
      bar had given up all five of the above and was still 150 pixels too
      long: the speed box was cut at «20x» and the trading-account button was
      past the edge, with nothing to say so (the area-13 adversary, F11). The
      zoom, the two scroll switches, the crosshair, the second timeframe and
      Jump - the things with a mouse or a key of their own on the chart - go
      under one «⋯», which lists each of them by name. Hidden from the bar,
      never from the person. */
#topbar .foldmore.iconbtn { display: none; }        /* beats shell.css's .iconbtn */
#topbar.fitmore .foldmore.iconbtn { display: inline-flex; }
#topbar.fitmore .canfold { display: none !important; }
/* 7  and below 641 pixels - a half-width browser, or the page zoomed to 300% -
      even that was not enough: forward one bar and the account settings went
      past the right edge (the round-2 area-13 adversary, F9). The bar takes a
      second row there, and the steps above are still taken first, because
      topfit.js asks for the height as well as the width. */
@media (max-width: 640px) {
  :root { --topbar: 76px; }
  #topbar { flex-wrap: wrap; align-content: center; row-gap: 4px; }
}

/* ---------- layout ---------- */

/* The fallback matters: shell.css is what declares `--titlebar`, and if it
   ever failed to load, a calc with an undefined variable is invalid and the
   whole height goes with it. */
main { display: flex; height: calc(100% - var(--topbar) - var(--titlebar, 0px)); }

#chartWrap { position: relative; flex: 1 1 0; min-width: 0; display: flex; }
#chart { display: block; flex: 1 1 0; min-width: 0; height: 100%; cursor: crosshair; }
/* With the crosshair off the pointer is an ordinary one. A cursor shaped like
   a crosshair over a chart with no crosshair on it is the interface telling
   two different stories. A drawing tool sets its own cursor and still wins,
   because that is set on the element itself. */
body.nocross #chart { cursor: default; }

#hud {
  position: absolute; top: 10px; left: 46px;
  transition: top .12s ease;
  font-size: 11px; color: var(--dim); pointer-events: none;
  text-shadow: 0 1px 3px #000;
  line-height: 1.7;
}
#hud b { color: var(--text); font-weight: 600; }

/* Below the buy and sell strip while it is on the chart. It is the control,
   so it takes the top; this is the reading, and a reading is looked at rather
   than pressed. Both go back where they were when the strip is switched off,
   or the chart opens with an empty band across the top of it. */
body.chart-strip #hud { top: 56px; }


#noData {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; text-align: center;
  /* The ground of whichever theme is on, nearly opaque. It was a fixed
     dark grey, which put a black slab across a light interface. */
  background: color-mix(in srgb, var(--bg) 94%, transparent);
}
#noData h2 { margin: 0; font-size: 16px; font-weight: 600; }
#noData p { margin: 0; color: var(--dim); max-width: 380px; }

.primary {
  background: var(--accent); color: #fff; border: 0; border-radius: 6px;
  padding: 8px 16px; font: inherit; font-weight: 600; cursor: pointer;
}
.primary:hover { filter: brightness(1.1); }

/* ---------- side ---------- */

#side {
  width: 296px; flex: 0 0 296px;
  border-left: 1px solid var(--line); background: var(--panel);
  display: flex; flex-direction: column; overflow: hidden;
}

.panel { border-bottom: 1px solid var(--line); padding: 10px 12px; }
.panel.grow { flex: 1; display: flex; flex-direction: column;
              padding: 0; overflow: hidden; border-bottom: 0; }

.account .row { display: flex; justify-content: space-between; align-items: baseline;
                padding: 2px 0; }
.account .row b { font-size: 14px; }
/* A crypto-only row, hidden on a forex account.
 *
 * `.cx-only` says `display: none`, but `.account .row` above says
 * `display: flex` and carries one more class, so it won - and every forex
 * customer has been shown a "ROE" and a "Leverage" reading "-", which mean
 * nothing on their account. Said again here at a weight that can win. */
.account .row.cx-only { display: none; }
body.crypto .account .row.cx-only { display: flex; }
.account .row.sub span { font-size: 11px; color: var(--dim); }

/* quote block */
.quote { display: flex; align-items: stretch; gap: 6px; margin-bottom: 12px; }
.quote .side {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  padding: 7px 4px; border-radius: 6px; background: var(--panel-2);
  border: 1px solid var(--line);
}
.quote .lbl { font-size: 10px; letter-spacing: 1px; color: var(--dim); }
.quote .price { font-size: 17px; font-weight: 600; }
.quote .sell .price { color: var(--sell); }
.quote .buy  .price { color: var(--buy); }
.spreadbox { display: flex; flex-direction: column; align-items: center;
             justify-content: center; min-width: 46px; }
.spreadbox .mono { font-size: 13px; }

.field { display: flex; justify-content: space-between; align-items: center;
         margin-bottom: 8px; font-size: 12px; color: var(--dim); }
.stepper { display: flex; align-items: center; }
.stepper button {
  width: 24px; height: 26px; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); cursor: pointer; font: inherit;
}
.stepper button:first-of-type { border-radius: 5px 0 0 5px; }
.stepper button:last-of-type  { border-radius: 0 5px 5px 0; }
.stepper input {
  width: 68px; height: 26px; text-align: center;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-left: 0; border-right: 0;
  /* The buttons round the two outside ends and the middle joins them flat.
     Said here rather than left out: a field has a corner of its own now, and
     the middle of a stepper growing one opens a seam through the control. */
  border-radius: 0;
  padding: 0;
  font: 13px var(--mono);
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.buttons { display: flex; gap: 8px; margin-top: 12px; }
.buttons button {
  flex: 1; padding: 11px 0; border: 0; border-radius: 6px;
  font: inherit; font-weight: 700; font-size: 14px; color: #fff; cursor: pointer;
  letter-spacing: .4px;
}
.buttons .buy  { background: var(--buy-solid); color: var(--on-buy); }
.buttons .sell { background: var(--sell-solid); color: var(--on-sell); }
.buttons button:hover { filter: brightness(1.12); }
.buttons button:disabled { opacity: .4; cursor: not-allowed; filter: none; }
.hint { margin-top: 7px; text-align: center; font-size: 10px; color: var(--faint); }

/* ---------- what the keyboard does ----------
 * Key-caps, because the shape of one says "this is a key you press" before a
 * word of it is read. It used to be a run of six things separated by middle
 * dots, where `B` read as the start of a word and `Space` read as a word. */
/* A fixed part of the ticket now, so it costs room rather than falling off
   the bottom of the scroller. Which means it has to cost LESS: a wrapping row
   instead of a two-column grid takes two lines where the grid took three, and
   the heading is gone entirely - six key caps do not need to be told they are
   keys. About 46px instead of 90. */
.keys { padding-top: var(--s2); margin-top: var(--s2);
        box-shadow: 0 -1px 0 var(--line-soft); }
.keylist { display: flex; flex-wrap: wrap; gap: 5px 10px; }
/* One key and the thing it does, as one element: nothing inside a pair for
   the Persian window to reorder, and nothing to pair it with the wrong key. */
.keyrow {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 11px; color: var(--dim);
}
.keyrow > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.keys kbd {
  flex: 0 0 auto;
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  line-height: 1; color: var(--text);
  padding: 4px 6px; min-width: 20px; text-align: center;
  background: var(--top), var(--panel-3);
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  /* The lip along the bottom is the whole of what makes it read as a key
     rather than as a box with a letter in it. */
  box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--line-strong) 60%, transparent),
              var(--sheen);
  /* A key is named in Latin whatever language the window is in. */
  direction: ltr; unicode-bidi: isolate;
}

/* tabs */
.tabs { display: flex; border-bottom: 1px solid var(--line); flex: 0 0 auto; }
.tab {
  flex: 1; background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--dim); padding: 9px 0; cursor: pointer; font: inherit; font-size: 12px;
}
.tab.active { color: var(--text); border-bottom-color: var(--accent); }
.tab span { color: var(--faint); font-size: 10px; }
.tabbody { flex: 1; overflow-y: auto; padding: 8px; display: flex;
  flex-direction: column; gap: 6px; }

/* Each open/pending/closed trade is a card rather than a flat ruled row: a
   panel with a rounded body and a colour down its left edge — green or red for
   the side, or win/loss on a closed trade — so the eye reads the outcome before
   the numbers. */
.pos {
  display: grid; grid-template-columns: 1fr auto auto;
  gap: 3px 10px; align-items: center;
  padding: 9px 12px 9px 13px;
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--line); border-radius: 10px;
  transition: background .12s ease, border-color .12s ease, transform .12s ease;
}
.pos:hover { background: var(--panel-2); border-color: var(--line-strong); }
.pos.win  { border-left-color: var(--up); }
.pos.loss { border-left-color: var(--down); }
.pos.buy  { border-left-color: var(--buy); }
.pos.sell { border-left-color: var(--sell); }

/* The side as a small pill, not just coloured text. */
.pos .who { font-size: 11px; font-weight: 700; letter-spacing: .3px;
  padding: 2px 8px; border-radius: 999px; justify-self: start; white-space: nowrap; }
.pos .who.buy  { color: var(--buy);  background: color-mix(in srgb, var(--buy) 15%, transparent); }
.pos .who.sell { color: var(--sell); background: color-mix(in srgb, var(--sell) 15%, transparent); }
.pos .meta { grid-column: 1 / 3; font-size: 10px; color: var(--dim);
  font-family: var(--mono); margin-top: 1px; }
.pos .pl { font-family: var(--mono); font-size: 14px; font-weight: 600; text-align: right; }
.pos .pl.up { color: var(--up-ink); } .pos .pl.down { color: var(--down-ink); }
.pos .kill {
  width: 26px; height: 26px; border-radius: 7px;
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--dim); cursor: pointer; transition: color .12s, border-color .12s;
}
.pos .kill:hover { color: var(--down-ink); border-color: var(--down); }

.statgrid { display: grid; grid-template-columns: 1fr auto; gap: 3px 10px; padding: 10px 12px; }
.statgrid span { color: var(--dim); font-size: 12px; }
.statgrid b { font-family: var(--mono); font-weight: 600; text-align: right; }

.nothing { margin: auto; padding: 26px 12px; text-align: center; color: var(--faint); font-size: 12px; }

/* ---------- modals ---------- */

.modal {
  position: fixed;
  /* Below the window's own title bar, not under it.
   *
   * `inset: 0` starts a dialog at the very top of the page, and in the native
   * window the top 32 pixels are the title bar the program draws itself. A
   * dialog centred in the rest of the screen never noticed; the account drawer
   * runs the full height, so its close button was the thing that landed
   * underneath - reported as half of it being outside the window, in both
   * languages, which is exactly what it was. */
  inset: var(--titlebar, 0px) 0 0 0;
  /* A vignette rather than a flat wash: the window is what should be looked
     at, and a plain 60% black in front of a dark interface is a grey sheet
     with a window on it. */
  background:
    radial-gradient(90% 80% at 50% 45%, rgba(0,0,0,.42), rgba(0,0,0,.74));
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center; z-index: 50;
}

/* A window opened FROM another window has to sit above it.
 *
 * Every `.modal` is z-index 50, so which one is in front is decided by which
 * is later in the document - and `#cardMake` is 53 lines above `#analysis`.
 * Pressing "Picture to share" therefore opened the maker *behind* the screen
 * it was pressed on: the window was open, the card was drawn, and the
 * customer saw nothing happen at all.
 *
 * Every probe passed it, because they all asked whether the `hidden` class
 * was gone and whether the preview had an image. Both were true. Neither is
 * the question - the question is whether it is the thing you touch at that
 * point on the screen, and `elementFromPoint` in the middle of the sheet
 * answered #analysis.
 *
 * Named for what they are rather than raised one by one: these are the two
 * that are opened from inside another window. */
#cardMake, #shotShow, #reviewCard { z-index: 60; }
/* Above the lab, the download dialog and the rest: a licence delivered by
   the eye while one of those is open was announced behind it, and the
   press on the scrim the customer saw closed it unseen (the adversary,
   2026-09-17). */
#paidWin { z-index: 60; }

/* A question (web/ask.js): the same shade and the same sheet as a window,
   above every window, and not a `.modal` - closeModals() would hide it
   without answering it. Two keys that say what they do; the one that
   destroys something wears the sell colour. */
.ask {
  /* Over every window, including the gallery's 72 (`#shotShow`, way below)
     and the avatar picker's 70 - both were written down as «60» in the
     comments this was built on, and the gallery would have taken the front
     off a standing question (the adversary, second pass, 2026-09-15). Under
     the crash card (90) and the withdrawn-copy card (95), which have to
     reach somebody whatever else is open. */
  position: fixed; inset: var(--titlebar, 0px) 0 0 0; z-index: 80;
  background: radial-gradient(90% 80% at 50% 45%, rgba(0,0,0,.42), rgba(0,0,0,.74));
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
}
.ask .sheet { width: 380px; max-width: calc(100vw - 32px); }
.ask .sheet > header { padding: 12px 16px 6px; border-bottom: 0; }
.ask .sheet > header b { font-size: 15px; }
/* The middle scrolls, like every other sheet's does (`.sheet > .pad`). The
   chips under «which setup was this?» are one per setup ever used, so on a
   768-tall screen sixty of them pushed the field and both keys off the bottom
   with nothing to scroll (the adversary, first pass, 2026-09-15). */
.ask .askbody {
  padding: 0 16px 14px; color: var(--dim); font-size: 13px; line-height: 1.7;
  flex: 0 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
}
.ask .askbody p { margin: 0; }
.ask .askbody p b { color: var(--text); font-weight: 600; unicode-bidi: isolate; }
.ask .askbody input {
  width: 100%; margin-top: 10px; padding: 8px 10px; border-radius: 6px;
  border: 1px solid var(--line-strong); background: var(--field); color: var(--text); font: inherit;
}
.ask .askbody input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--ring); }
.ask .askchips { margin-top: 8px; font-size: 11.5px; color: var(--faint); display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ask .askchip {
  font: inherit; cursor: pointer; padding: 1px 9px; border-radius: 999px;
  border: 1px solid var(--line); background: none; color: var(--dim);
}
.ask .askchip:hover { border-color: var(--line-strong); color: var(--text); }
.ask .sheet > footer { display: flex; gap: 8px; padding: 0 16px 14px; border-top: 0; }
.ask .sheet > footer .primary { flex: 1; padding: 9px 14px; }
.ask .sheet > footer .primary.danger { background: var(--sell-solid); color: var(--on-sell); }
.ask .sheet > footer .chip { flex: 1; text-align: center; padding: 9px 14px; }
.sheet {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  width: 360px; max-height: 78vh; display: flex; flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,.55);
}
.sheet.wide { width: 620px; height: 74vh; }
/* A sheet is capped at 78vh, so on a short window its body is the part that
   has to scroll. Without this the bottom of a dialog is simply unreachable:
   the sheet clips it and nothing offers a way down. `min-height: 0` is what
   makes it work — a flex item will not shrink below its own content without
   it, so `overflow-y: auto` had nothing to do. Found on "Sessions and
   storage", which lost 96 pixels off its foot on a 768-tall screen. */
.sheet > .pad {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  /* Never sideways. A dialog that scrolls left and right is a dialog whose
     content is too wide, and hiding it is the lesser of the two wrongs. */
  overflow-x: hidden;
}
/* …and in a stacked body its own children keep their height. `.pad.col` is a
   flex column, so letting the pad shrink let it squash what was inside rather
   than scroll it. Only the column: a plain `.pad` is a *wrapping row*, and
   telling those children not to shrink pushed them off the side instead. */
.sheet > .pad.col > * { flex-shrink: 0; }
/* And it must not wrap. `.pad` sets `flex-wrap: wrap` for the rows it is
   normally used as; a *column* that wraps and is finally given a height does
   what a wrapping column does — it starts a second column beside the first,
   off the side of the dialog. It read as a scroll bar that went the wrong
   way. A stacked body is one stack. */
.sheet > .pad.col { flex-wrap: nowrap; }
.sheet > header {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-bottom: 1px solid var(--line);
}
.sheet > header input {
  flex: 1;
}
.sheet > footer { padding: 8px 12px; border-top: 1px solid var(--line); }
/* The close button always sits at the far (right) end of its header row, even
   in the dialogs whose title is short enough that it would otherwise hug the
   title instead of the corner. */
.x { background: none; border: 0; color: var(--dim); cursor: pointer; font-size: 14px;
     margin-inline-start: auto; }
.x:hover { color: var(--text); }
/* Window controls (minimize / maximize) sit with the close button; they must not
   each grab the auto margin, or they would spread across the header. */
.sheet > header .wmin, .sheet > header .wmax { margin-inline-start: 0; font-size: 13px; }
.sheet > header .wmax { transform: scale(.92); }
/* Maximize: grow the window to nearly the whole screen.
 *
 * This was a list of three window ids - journal, analysis, lab - and the
 * button is on five. On the other two (saved runs, the prop challenge) it
 * toggled the class, flipped its own glyph, and nothing happened. Reported as
 * «the maximize button does not work on many windows», which is exactly what
 * a list that did not grow with the buttons looks like from outside.
 *
 * Any sheet now. `!important` because a maximized window has to beat every
 * per-window size rule there is and every one there will be - #prop's
 * min(780px, 94vw), .wide's 620px, whatever the next window brings - and the
 * id-scoped list was the last attempt at doing that without it. A list is
 * what went stale; this cannot. */
.modal > .sheet.maxed {
  width: 96vw !important; height: 94vh !important;
  max-width: 96vw !important; max-height: 94vh !important;
}
/* The bar of minimized windows, along the bottom. */
#winbar { position: fixed; bottom: 12px; inset-inline-start: 12px; z-index: 60;
  display: flex; gap: 8px; }
.winchip { display: flex; align-items: center; gap: 7px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 9px; padding: 8px 13px; color: var(--text);
  font: inherit; font-size: 12px; cursor: pointer; box-shadow: var(--elev-2);
  transition: border-color .14s ease; }
.winchip:hover { border-color: var(--accent); }
.winchip .wdot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.winchip .wup { color: var(--dim); font-size: 10px; }
.pad { padding: 14px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pad p { width: 100%; margin: 0; }
/* The Expert (JS) code editor - a calm dark code surface.
   The ground is deeper than a field's on purpose: that is what says this is a
   place to write a program rather than a name. Everything else about the box
   is the shared field, including the ring it draws when the keyboard is in
   it, which this used to take away and replace with a border. */
.codebox { background-color: var(--bg); background-image: none;
  padding: 10px 12px; line-height: 1.55; resize: vertical;
  font-family: var(--code); tab-size: 2; white-space: pre; overflow: auto; }

.picklist { flex: 1; overflow-y: auto; }
.pickgroup { padding: 8px 14px 4px; font-size: 10px; letter-spacing: 1.2px;
             text-transform: uppercase; color: var(--faint);
             display: flex; justify-content: space-between; align-items: baseline; }
.pickgroup .more { letter-spacing: 0; text-transform: none; font-size: 10px;
                   color: var(--dim); }
.pickrow {
  display: grid; grid-template-columns: 20px 84px 1fr auto auto;
  gap: 10px; align-items: center;
  padding: 7px 14px; cursor: pointer; border-bottom: 1px solid var(--line-soft);
}
.pickrow:hover { background: var(--panel-2); }
.pickstar { background: none; border: 0; padding: 0; width: 20px; font-size: 15px;
  color: var(--faint); cursor: pointer; line-height: 1; }
/* A star is gold, everywhere. It was the accent in three places, a
   hard-coded gold in a fourth, and `--news` in the fifth - so the same
   mark meant "kept" in four different colours, one of which was the
   colour that means "chosen" on every other control in the program. */
.pickstar.on { color: var(--gold-ink); }
.pickstar:hover { color: var(--text); }
.pickstar.on:hover { color: var(--gold-ink); }
/* Open and Update/Download share one grid cell so the row never wraps a button
   onto a line of its own. */
.pickacts { display: flex; gap: 6px; align-items: center; justify-content: flex-end; }
/* The app's own tooltip — styled, and able to hold a sentence. */
#tooltip {
  position: fixed; z-index: 200; pointer-events: none;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 7px;
  padding: 6px 10px; font-size: 12px; line-height: 1.45;
  /* Wide enough for a sentence. At 280 five of the fifty-five tooltips on
     the page wrapped onto two lines, all of them ordinary seven-to-twelve
     word labels; the widest tooltip in the application measures 355 across,
     so 380 puts every one of them on a single line. A tooltip is a label,
     and a label reads better on one line than in a paragraph.

     `max-content` rather than leaving it to shrink-to-fit, so a box can
     never round down to a pixel less than its text wants and wrap for the
     sake of it. */
  width: max-content;
  max-width: min(380px, calc(100vw - 24px));
  box-shadow: 0 8px 26px rgba(0, 0, 0, .5);
}
#tooltip.hidden { display: none; }
/* Which way the box runs is set on the box itself, per tooltip, from the first
   strong character of what it is about to show. `start` then means the right
   edge for a Persian sentence and the left edge for a Latin one.
   This used to be `unicode-bidi: plaintext` with `text-align: left`, which is
   right for one line and wrong for two: soft wrapping does not begin a new
   paragraph, so a Persian tooltip long enough to wrap stayed one right-to-left
   paragraph pinned to the physical left, and every line began at the far end
   from where it is read. */
#tooltip { text-align: start; }

.pickrow .sym { font-weight: 600; font-family: var(--mono); }
.pickrow .nm { color: var(--dim); font-size: 12px; overflow: hidden;
               text-overflow: ellipsis; white-space: nowrap; }
.pickrow .cov { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.pickrow .get {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  border-radius: 5px; padding: 3px 9px; font-size: 11px; cursor: pointer;
}
.pickrow .get:hover { border-color: var(--accent); color: var(--accent); }
.pickrow .get.busy { color: var(--accent); border-color: var(--accent); }
.pickrow.on { background: var(--sel); }

#toast {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%);
  background: var(--panel-2); border: 1px solid var(--line);
  padding: 9px 16px; border-radius: 8px; z-index: 90; font-size: 12px;
  box-shadow: 0 8px 30px rgba(0,0,0,.5);
}

/* ---------- added with the Soft4FX feature set ---------- */

.tools {
  flex: 0 0 34px; display: flex; flex-direction: column; gap: 2px;
  padding: 6px 3px; background: var(--panel);
  border-right: 1px solid var(--line);
}
.tools button {
  width: 28px; height: 26px; background: none; border: 0; border-radius: 5px;
  color: var(--dim); cursor: pointer; font-size: 13px; line-height: 1;
}
.tools button:hover { color: var(--text); background: var(--hover); }
.tools button.active { background: var(--accent); color: #fff; }

.seg { display: flex; gap: 2px; background: var(--panel-2);
       border: 1px solid var(--line); border-radius: 6px; padding: 2px;
       margin-bottom: 9px; }
.seg button {
  flex: 1; background: none; border: 0; border-radius: 4px; color: var(--dim);
  padding: 5px 0; cursor: pointer; font: inherit; font-size: 12px;
}
.seg button:hover { color: var(--text); }
.seg button.on { background: var(--sel); color: var(--text); }
.seg.small button { padding: 3px 0; font-size: 11px; }

/* ---- Forex / Crypto mode ------------------------------------------------
   One panel, two audiences. `body.crypto` flips which rows and which words
   show; nothing about the engine changes. */
/* Where the trading controls appear: two INDEPENDENT switches, not a choice
 * between two things. Either, both or neither is a valid answer.
 *
 * It used to take the full accent while a chosen segment below it takes the
 * sunk one, and the difference was doing two jobs badly. It made the panel's
 * loudest thing a layout preference somebody sets once - louder than Buy and
 * Sell, and in direct competition with the equity rings underneath, which are
 * the same accent and are data. And it signalled "these two behave
 * differently" through a shade of one hue, while signalling "these are the
 * same kind of control" through identical shape, height and container. The
 * strong channel said one thing and the weak channel said the opposite.
 *
 * So: the same blue as every other chosen thing, and a tick to say this is a
 * STATE rather than a selection. Making the colour match without the tick was
 * the other half-answer - it reads as a single-choice control, and then both
 * switches on looks like a broken one.
 */
.modeswitch { margin-bottom: 8px; }
.modeswitch button.on { background: var(--sel); color: var(--text); }
.modeswitch button.on::before {
  content: '\2713';
  margin-inline-end: 6px;
  font-weight: 700;
  opacity: .9;
}
/* Two switches that happen to sit together, not two halves of one choice, so
   both can be lit at once and neither is lit by default of the other. The
   divider makes them read as separate controls rather than as a slider with
   two positions. */
#tradeMode { gap: 4px; }
#tradeMode button + button { border-inline-start: 1px solid var(--line); }
.cx-only { display: none; }
body.crypto .fx-only { display: none; }
body.crypto .cx-only { display: flex; }
body.crypto .row.cx-only { display: flex; }        /* account rows are flex rows */
body.crypto #rowPct.cx-only { display: block; }     /* the % block stacks */
/* Button labels swap with the mode. */
.cx-lbl { display: none; }
body.crypto .fx-lbl { display: none; }
body.crypto .cx-lbl { display: inline; }
/* In crypto, Long is green (buy) and Short is red (sell) — same as the engine's
   buy/sell, just the exchange's words. */
.field .unit { font-style: normal; color: var(--dim); font-size: 10px; }
.unittog { background: none; border: 1px solid var(--line); border-radius: 4px;
  color: var(--dim); cursor: pointer; font-size: 11px; width: 22px; }
.unittog:hover { color: var(--text); }
.pctfield { margin-bottom: 4px; }
#rowPct #pctSlider { width: 100%; margin: 2px 0 6px; }
.pctquick { display: flex; gap: 4px; margin-bottom: 9px; }
.pctquick button { flex: 1; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 5px; color: var(--dim); font-size: 11px; padding: 4px 0; cursor: pointer; }
.pctquick button:hover { color: var(--text); border-color: var(--accent, #2f81f7); }
/* The price at which the position would be closed out, printed before
   anything is open. A reading rather than a warning, so it is written in
   the quiet grey: red here is what a loss and a sell are, and spending it
   on a figure nobody has to act on is how a real warning stops being
   noticed. */
.cxliq { min-height: 14px; text-align: end; color: var(--faint); }
.cxliq b { color: var(--dim); font-weight: 600; }

/* The two lines under the ticket, lined up with the figures they add up.
 *
 * Every row of the ticket is a label at the start and its value at the END, so
 * the numbers run down the right in English and down the left in Persian.
 * These lines are the sum of those numbers - what the size comes to and what
 * it costs if the stop is hit - so `end` is where they belong, and it is the
 * same rule in both languages rather than two arrangements that happen to
 * meet.
 *
 * They were `center`, and in Persian they were pushed the other way again by
 * a rule in shell.css that read them as sentences. That rule is gone; this is
 * the one place either line is told where to sit. */
#riskLine.riskline { min-height: 15px; margin: 2px 0 0; text-align: end; }
/* The size does not fit the account. Read as a warning, not as another
   figure: it is the one line that says the press will be refused. */
#riskLine.over { color: var(--sell); }
.riskline b { color: var(--text); font-family: var(--mono); }

.closers { display: flex; gap: 6px; margin-top: 8px; }
/* Three ways to get out of the market, so they are read at a glance rather
   than squinted at. They were 11px Arial directly under a 14px Vazirmatn
   `Buy`, which made the two look like they came from different programs. */
/* `flex: 1` belongs to the three closing buttons, which share a row and are
   meant to be equal thirds of it. On `.mini` itself it stretched every small
   button that carries the class - and the worst of them was "Sign out" in the
   profile card, which took 139px of a 354px row while the name it sits beside
   got 119. Clicking the empty space next to your own name signed you out. */
.closers .mini { flex: 1; }
.mini {
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--dim); border-radius: 10px; padding: 8px 6px;
  font-size: 12px; font-weight: 500; line-height: 1.2;
  cursor: pointer; white-space: nowrap;
}
.mini:active { transform: translateY(1px); }
.mini:hover { color: var(--text); border-color: var(--line-strong); }

/* The last column, said out loud. Without `grid-column` these buttons are an
   item locked to a row and no column, and grid places those before it places
   anything else - so they took column one, which is the wide one the side pill
   is meant to spread out in, and the trade was pushed to the far end behind
   its own buttons. */
.pos .acts {
  grid-column: 3; grid-row: 1 / span 2;
  display: flex; gap: 4px; align-self: start;
}
.pos .act {
  width: 26px; height: 24px; border-radius: 7px;
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--dim); cursor: pointer; font-size: 11px; line-height: 1;
  transition: color .12s, border-color .12s, background .12s;
}
.pos .act:hover { color: var(--text); border-color: var(--line-strong); background: var(--panel); }
.pos .act.kill:hover { color: var(--down-ink); border-color: var(--down); }

.pad.col { flex-direction: column; align-items: stretch; }
.pad.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.pad.grid2 label { display: flex; flex-direction: column; gap: 4px;
                   font-size: 11px; color: var(--dim); }
/* A field, and only a field. A tick box and a slider are not things anybody
   types in, and both of them are drawn from the palette themselves - left in
   here, this rule wins on specificity and turns a 16px box into a 24x18 pill
   with an 11px corner, which is what it did. */
/* The figures in a two-column grid are the shared field. All this row ever
   really said was that they are figures, and that is said once now. */
/* Direct children only. Written as a descendant rule it reached every button
   anywhere inside the window, which is harmless while nothing between them is
   a grid - and the moment one was (the four currency tiles), all four were
   handed the full width and stacked. `grid-column` does nothing to an element
   that is not a grid item, so narrowing this changes nothing else. */
.pad.grid2 > p, .pad.grid2 > button { grid-column: 1 / -1; }

.addrow { display: flex; gap: 8px; }
/* Words in a row line up with the controls beside them.
 *
 * The row does not set `align-items`, so every child stretches to the tallest
 * one. For a field or a button that is exactly what makes them match; for a
 * piece of text it means the box is stretched and the writing stays at the top
 * of it. The boxes line up and the words sit high - and the words are the only
 * part anybody sees.
 *
 * `align-items: center` on the row would fix the words and cost the match:
 * measured on the MetaTrader export row, the buttons drop from 37 to 33 while
 * the field stays at 37. So the rule is put the other way round - a control
 * keeps its height, and everything that is not one is centred against them.
 * A wrapper around a field counts as a control for this. */
.addrow > :not(input):not(select):not(textarea):not(button):not(.numfield):not(.stepper) {
  align-self: center;
}

/* A button beside a captioned field lines up with the field, not with the
   caption above it.
 *
 * `.labfield` is a column - a caption with an input under it - so it is 19
 * pixels taller than the input alone. A button in the same row was stretched
 * to the whole stack and came out 54 tall against a 35 field, which reads as a
 * button somebody made enormous on purpose. Measured on every one of them in
 * the laboratory: 19px too tall, every time, which is the caption and its gap
 * exactly.
 *
 * To the end rather than centred, because the thing it belongs beside is the
 * field, and the field is at the bottom of that stack. */
.addrow:has(> .labfield) > button { align-self: flex-end; }
/* The one button that closes this window sits on the right in both
   languages, and `right` is meant physically - which is rare enough here to
   be worth saying why. It used to be `flex-end` written inline, and
   `flex-end` is the end of the line: in Persian that is the left, so the
   button walked to the far corner while the two buttons above it stayed in
   the middle. Asked for as "right-align everything", and the same corner in
   both languages is also the answer that does not have to be remembered. */
.addrow.jsfoot { justify-content: right; }
/* What is actually this row's: the share of the line. The box it used to
   paint - its own ground, its own 5px corner - is the shared one now.

   A DIRECT child, which it was not.

   `flex: 1` is `flex-basis: 0%`, and a row in the laboratory holds captioned
   fields - a `label.labfield` that is itself a COLUMN. The descendant form
   reached through the label and gave the select inside it a basis of zero in
   the wrong axis: `#labScore` and `#vsSession` measured 22 tall against
   everyone else's 34, and no rule said 22 anywhere. Only something that is
   really a cell of this row gets a share of it. */
.addrow > select, .addrow > input { flex: 1; }

.indrow {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 8px 0; border-bottom: 1px solid var(--line-soft);
}
.indrow .nm { flex: 1 0 100%; font-size: 12px; font-weight: 600; }
.indrow label { display: flex; align-items: center; gap: 4px;
                font-size: 11px; color: var(--dim); }
/* Narrow, because a period is two digits. The rest is the shared field. */
.indrow input { width: 58px; }
.indrow .rm { margin-left: auto; background: none; border: 0; color: var(--dim);
              cursor: pointer; font-size: 13px; }
.indrow .rm:hover { color: var(--down-ink); }

.sesslist { max-height: 220px; overflow-y: auto; }
.sessrow {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 0; border-bottom: 1px solid var(--line-soft);
}
/* A saved run's row is dressed in shell.css, beside the window it belongs to.
 *
 * What used to be here was written for markup this program no longer has —
 * `.nm` and `.when`, where the row now holds `.sessname` and `.sesswhat` — and
 * its `button` rule was still landing on the two live buttons, setting a
 * font-size nobody had chosen and a radius that lost every argument. A rule
 * that survives the markup it was written for is exactly how the 30px squares
 * happened; see the note at the top of the sessions block in shell.css. */

/* ---------- the report: figures in one half, the curve in the other ----------
 *
 * Every figure used to be a row across the whole panel, so the word sat
 * against one wall and its number against the other. Cards fix that by being
 * narrow: nothing here sets a gap between a label and its value, the card
 * simply is not wide enough for one to open up.
 */
.report {
  flex: 1; min-height: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px;
}
/* Their own scroll, so the curve beside them does not travel with them. */
/* Columns rather than a grid, so a short card is followed by the next one
   instead of by the hole left under the tallest card in its row. */
.repstats {
  overflow-y: auto; min-height: 0;
  columns: 184px; column-gap: 8px;
}
.statcard {
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 10px; box-shadow: var(--sheen); overflow: hidden;
  break-inside: avoid; margin: 0 0 8px; width: 100%;
}
/* A table of tags needs the width of them all rather than one column of it. */
.statcard.wide { column-span: all; padding-bottom: 6px; }
.statcard.wide .tagtable { padding: 0 10px; }
.repchart {
  min-height: 0; display: flex;
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 10px; box-shadow: var(--sheen); overflow: hidden;
}
#equity { flex: 1; width: 100%; height: 100%; display: block; }

/* Not enough width to be two things side by side. Asked of the panel, not of
   the window: this one is a strip the customer drags to whatever width they
   like, and a media query would be answering about the whole application. */
@container dock (max-width: 700px) {
  .report { grid-template-columns: minmax(0, 1fr); grid-template-rows: 1fr auto; }
  .repchart { height: 150px; flex: 0 0 150px; }
}

.statgrid.tight { grid-template-columns: 1fr auto; gap: 2px 8px; padding: 2px 10px 8px; }

/* A block of figures sitting straight under a row of controls.
 *
 * `.statgrid.tight` is written for the case it was made for: a heading with
 * figures under it inside a card, where the heading's own bottom padding is
 * the whole of the air needed. Under an input and a button there is no
 * heading and no padding, so the box arrived welded to the field above it -
 * 0px, measured, on a panel whose other blocks sit 12 apart.
 *
 * Twelve, because that is what the rest of the panel uses. The top padding
 * comes back up to match the bottom, or the figures sit against the top edge
 * of their own box. */
.addrow + .statgrid { margin-top: 12px; }
.addrow + .statgrid.tight { padding-top: 8px; }

/* And the invite box against whatever is above it, which was the other zero.
 * Measured at 0 on a panel whose blocks sit 12 apart. */
#refBox { margin-top: 12px; }
.statgrid.tight span { font-size: 11.5px; }
.statgrid.tight b { font-size: 12px; }
.stathead {
  padding: 8px 10px 4px; font-size: 9.5px; letter-spacing: 1.1px;
  text-transform: uppercase; color: var(--faint);
}
.pos .note { grid-column: 1 / -1; font-size: 10px; color: var(--accent);
             font-style: italic; margin-top: 4px; padding: 5px 8px;
             background: color-mix(in srgb, var(--accent) 10%, transparent);
             border-radius: 6px; display: flex; align-items: center; gap: 6px; }
/* The small ✕ that removes a tag or a note in one click. */
.pos .tag, .pos .note { position: relative; }
.chipx { border: 0; background: none; color: inherit; opacity: .5; cursor: pointer;
  font-size: 9px; padding: 0 2px; line-height: 1; }
.chipx:hover { opacity: 1; color: var(--down-ink); }
.pos.open { border-color: color-mix(in srgb, var(--accent) 38%, var(--line)); }
/* The full, MetaTrader/exchange-style detail of one closed trade. */
.posgrid { grid-column: 1 / -1; margin-top: 8px; padding: 9px 10px;
  background: var(--bg); border: 1px solid var(--line-soft); border-radius: 8px;
  display: grid; grid-template-columns: auto 1fr auto 1fr; gap: 5px 12px;
  font-size: 11px; align-items: baseline; }
.posgrid span { color: var(--dim); white-space: nowrap; }
.posgrid b { color: var(--text); font-weight: 600; text-align: end;
  font-variant-numeric: tabular-nums; }
@media (max-width: 340px){ .posgrid { grid-template-columns: auto 1fr; } }

.rule { border: 0; border-top: 1px solid var(--line); margin: 4px 0; width: 100%; }

.choices { display: flex; flex-direction: column; gap: 6px; }
.choice {
  display: flex; align-items: baseline; gap: 10px; text-align: left;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px;
  padding: 9px 12px; color: var(--text); font: inherit; cursor: pointer;
}
.choice:hover { border-color: var(--line-strong); }
.choice.on { border-color: var(--accent); background: var(--sel); }
.choice .span { font-weight: 600; min-width: 92px; }
.choice .est { color: var(--dim); font-size: 11px; font-family: var(--mono); }
.choice .have { margin-left: auto; color: var(--up-ink); font-size: 11px; }

.diag { display: flex; align-items: baseline; gap: 8px; padding: 5px 0;
        border-bottom: 1px solid var(--line-soft); font-size: 12px; }
.diag .dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; }
.diag .dot.up { background: var(--up); }
.diag .dot.down { background: var(--down); }
.diag .nm { font-weight: 600; min-width: 78px; }
.diag .why { color: var(--dim); font-size: 11px; flex: 1; }
.diag .ms { color: var(--faint); font-family: var(--mono); font-size: 10px; }
.verdict { padding: 8px 0 2px; font-size: 12px; color: var(--text); line-height: 1.5; }
.verdict.bad { color: var(--down-ink); }
.joberr { padding: 6px 14px; color: var(--down-ink); font-size: 11px; line-height: 1.5; }
.jobnote { padding: 0 14px 6px; color: var(--dim); font-size: 11px; }

.secline { font-size: 12px; }

/* The higher timeframe, beside the one being traded. Read-only by being
   untouchable rather than by trusting every handler to check a flag. */
/* A flex sibling of the chart, not an overlay: the chart is `flex: 1 1 0`, so
   taking this out of the flow left the canvas at full width with the pane on
   top of it. */
#context { flex: 0 0 38%; min-width: 260px; border-left: 1px solid var(--line-soft);
           background: var(--bg); display: flex; flex-direction: column;
           overflow: hidden; }
#context.hidden { display: none; }
#context .ctxbar { display: flex; align-items: center; gap: 8px;
                   padding: 4px 8px; border-bottom: 1px solid var(--line-soft); }
#context .ctxbar .lbl { font-size: 10px; letter-spacing: 1.2px;
                        text-transform: uppercase; color: var(--faint); flex: 1; }
/* It used to be `pointer-events: none`, which meant the second chart could
   not be scrolled, zoomed, dragged by an axis or even clicked. It is a chart;
   it takes the same gestures as the first one. */
#context canvas { flex: 1 1 0; width: 100%; min-height: 0; cursor: crosshair; }
/* Lit like every other switch in the top bar - an outline, not a gold slab
   that swallows the icon and leaves nobody able to say what the button was. */

#reviewBar { position: absolute; left: 50%; transform: translateX(-50%);
             bottom: 18px; display: flex; align-items: center; gap: 10px;
             padding: 8px 14px; border-radius: 10px; z-index: 5;
             background: color-mix(in srgb, var(--panel) 96%, transparent); border: 1px solid var(--line);
             box-shadow: 0 8px 26px rgba(0,0,0,0.5); font-size: 13px; }
#reviewBar.hidden { display: none; }
/* One line: «What do you do here?» broke over three beside the answers. */
#reviewAsk { white-space: nowrap; }

/* Blind controls, top-right corner of the chart — out of the price action,
   mirror of the review bar, always in the same place so it never hunts. */
#blindBar { position: absolute; top: 12px; right: 12px; display: flex;
            align-items: center; gap: 8px; padding: 6px 10px; border-radius: 10px;
            z-index: 6; background: color-mix(in srgb, var(--panel) 96%, transparent); border: 1px solid var(--line);
            box-shadow: 0 8px 26px rgba(0,0,0,0.5); font-size: 12px;
            /* Inside the chart on a narrow window: with «Leave the challenge»
               beside Next and Reveal it ran off the chart's far edge (the
               round-7 area-11 review, S1). */
            flex-wrap: wrap; max-width: calc(100% - 24px); box-sizing: border-box; }
#blindBar.hidden { display: none; }
#blindBar .blindtag { color: var(--accent); font-weight: 600; letter-spacing: .3px; }
#blindBar .chip { padding: 4px 10px; font-size: 12px; }
#blindBar .blindrules { color: var(--dim); }
body.fa #blindBar { unicode-bidi: plaintext; }
#reviewBar .chip.good { background: var(--up); color: #04150f; border-color: var(--up); }
/* Filled like every other filled sell, rather than with the candle red and
   somebody else's ink. */
#reviewBar .chip.bad { background: var(--sell-solid); color: var(--on-sell);
                       border-color: var(--sell-solid); }

.sheet.wide { max-width: 720px; }

.mark { font-size: 9px; letter-spacing: 0.8px; text-transform: uppercase;
        color: var(--faint); padding-left: 6px; }
.mark.on { color: var(--up-ink); }

/* --------------------------------------------------------------------------
   Persian
   --------------------------------------------------------------------------
   The interface turns around; the chart does not. A time axis runs left to
   right in every market there is, and a trader reads it without thinking —
   mirroring it would be the one change nobody asked for and everybody would
   notice. So `#chartWrap` is pinned back the other way, and with it the price
   axis, the crosshair readout and the panes beside it.

   Numbers stay in Latin digits and keep their monospace face: a price, a lot
   size and a ticket are read against a broker's own screen. */
body.fa { font-family: Vazirmatn, var(--ui); }
body.fa .mono,
body.fa [class*="mono"],
body.fa input[type="number"],
body.fa input[type="date"],
body.fa input[type="time"] { font-family: var(--mono); direction: ltr; }

/* Text over the chart is still Persian text: each line resolves its own
   direction, which fixes the punctuation without moving the panel.
 *
 * `start`, not `left`. When this was written nothing turned round, so the two
 * meant the same thing and the physical side got used. Twenty windows turn
 * round now, and in every one of them `left` is the far end of the line: the
 * caption sat against one edge while the heading above it sat against the
 * other. Under `unicode-bidi: plaintext` this follows each paragraph's own
 * direction, so an English sentence inside a Persian window still begins on
 * the left, which is the other half of what the rule is for. */
body.fa #reviewBar, body.fa #noData, body.fa #context .ctxbar,
body.fa .sub, body.fa p, body.fa .note, body.fa .joberr, body.fa .msg,
body.fa small, body.fa label, body.fa .secline, body.fa #toast {
  unicode-bidi: plaintext; text-align: start;
}
/* The review bar is a flex ROW, and `plaintext` above sets the direction of
   the text inside a box, not the order of the boxes in a row. So the question
   stayed on the left with the three buttons trailing after it, measured at
   +15, +190, +274, +318 inside a bar that reads from the right. The row has
   to turn as well; the question keeps `plaintext` from the rule above, so a
   price or a Latin symbol inside it still reads the way it should. */
body.fa #reviewBar { direction: rtl; }

/* Letter-spacing on uppercase Latin headings shreds Persian, which joins.
   `.labsec` is the laboratory's own, added when that window was rebuilt and
   left out of this list at the time - which is exactly the fault this line
   exists to prevent, committed by the person who read the line. */
body.fa .pickgroup, body.fa .sechead, body.fa .stathead,
body.fa .tagtable th, body.fa .mark,
body.fa #lab .labsec { letter-spacing: 0; }

/* The alignment overrides that used to undo the mirroring are gone with it:
   every column now sits where it sits in English. */

/* ---------- the one place that does turn around ---------- */
/* The account panel, and only it.
 *
 * Everywhere else the rule above holds: the interface is translated in place
 * and nothing changes sides, so the two languages are one application rather
 * than two to learn. That rule is about the working surface — the chart, the
 * toolbars, the panels somebody uses every day and reaches for without
 * looking.
 *
 * This is not that. It is a page: a paragraph, a row of tabs read as a
 * sequence, and a form. Left to right it read wrongly in both senses. The row
 * of tabs put "Sign in" — the one almost everybody wants — at the far end from
 * where a Persian reader starts. And a sentence ending in a full stop, in a
 * heading with no bidi handling at all, put the full stop at the beginning of
 * the line: «هنوز اشتراکی روی این دستگاه .نیست». That is not a nicety, it is a
 * sentence a person cannot read.
 */
/* Every window, not a list of them.
 *
 * This used to be one rule per window, each naming its own id, and the list
 * was kept by hand. A window added later was simply missing from it, and
 * nothing said so: the words were still Persian, only the sides were wrong -
 * the title at the far end from where reading starts, the close button where
 * the title belongs, the buttons piled against the wrong edge. Five windows
 * had drifted out that way, one of them the update notice that every customer
 * meets, and a sixth is built in code and never had a rule at all.
 *
 * So the default is turned round instead. A window is right-to-left in
 * Persian because it is a window; anything that must stay left-to-right - a
 * code, a price, a date - says so for itself, one line at a time, and those
 * exceptions are all still below.
 *
 * On the sheet, not on the modal around it. The modal is the flex box that
 * decides where the sheet sits on the screen, and turning *that* round moves
 * the whole panel to the other edge of the window - which is a change nobody
 * asked for and the opposite of the rule above. This way the panel stays
 * where it is and only its contents turn. */
body.fa .sheet { direction: rtl; }

/* Inside it, the rules above would still force text to the left, which in a
   right-to-left box is the far edge. They resolve their own direction now,
   and `start` is whichever side that turns out to be. */
body.fa #welcome .sub, body.fa #welcome p, body.fa #welcome label,
body.fa #welcome small, body.fa #welcome .note, body.fa #welcome .msg,
body.fa #welcome .secline {
  unicode-bidi: normal; text-align: start;
}

/* What must not turn around: anything typed in Latin or in digits. A username
   is Latin, a telephone number and a code from a text message are digits, and
   a field that reverses them while they are being typed is unusable. */
body.fa #welcome input { direction: ltr; text-align: left; }

/* The picture window, for the same reason and on the same terms.
 *
 * It is a page rather than a working surface: a heading, a grid of pictures
 * read as a sequence, two buttons and a paragraph. Nobody reaches for it
 * without looking - it is opened rarely and read - so the argument above for
 * leaving the working surface alone does not reach it.
 *
 * On the sheet, never on the modal: the modal is what decides where the window
 * sits on screen, and turning that round would move the whole window to the
 * other edge. This way it stays put and only its contents turn. */

/* `body.fa .sub` sets `text-align: left`, which is a physical side: in a
   right-to-left box that is the far edge, which is where the note under the
   pictures ended up. `start` is whichever side the reader starts on. */
body.fa #avatarPick .sub {
  unicode-bidi: normal; text-align: start;
}

/* The first-run question. Deliberately the whole window: it is the only thing
   being asked, and it is asked once. */
#pickLang { position: fixed; inset: 0; z-index: 50; display: flex;
            align-items: center; justify-content: center; background: var(--bg); }
#pickLang.hidden { display: none; }
#pickLang .box { text-align: center; }
#pickLang h1 { font-size: 17px; font-weight: 500; margin: 0 0 4px; }
#pickLang p { color: var(--dim); font-size: 12px; margin: 0 0 22px; }
#pickLang .row { display: flex; gap: 12px; justify-content: center; }
#pickLang button { min-width: 150px; padding: 13px 18px; font-size: 15px;
                   border-radius: 10px; cursor: pointer;
                   background: var(--panel-2); color: var(--text);
                   border: 1px solid var(--line); }
#pickLang button:hover { border-color: var(--accent); }
#pickLang .fa { font-family: Vazirmatn, var(--ui); }

#pineBox.hidden { display: none; }
#pineSrc { width: 100%; box-sizing: border-box; resize: vertical;
           background: var(--bg); color: var(--text); border: 1px solid var(--line);
           border-radius: 6px; padding: 9px 10px; font: 11px/1.5 var(--code);
           direction: ltr; text-align: left; }
#pineSrc:focus { outline: none; border-color: var(--accent); }

.secline { font-size: 12px; }

/* Blind practice. The instrument button still works — revealing it is a
   deliberate act — but it stops advertising what it would reveal. */
/* Jumping to a date is the one control that undoes blind practice: it both
   tells you where you are and lets you go somewhere else. Gone while blind,
   in both languages, rather than left there to be pressed by accident.
   The instrument's name is NOT dimmed any more - it is not hidden at all. */
body.blind #btnJump { display: none; }
body.blind #btnBlind { background: var(--up); color: #04150f; border-color: var(--up); }

.pos .tag { grid-column: 1 / -1; justify-self: start; margin-top: 4px;
            padding: 2px 9px; border-radius: 999px; font-size: 10px; font-weight: 600;
            background: color-mix(in srgb, var(--accent) 16%, transparent);
            color: var(--accent); font-family: var(--mono); }

.sechead { padding: 12px 0 4px; font-size: 10px; letter-spacing: 1.2px;
           text-transform: uppercase; color: var(--faint); }
.tagtable { width: 100%; border-collapse: collapse; font-size: 12px; }
.tagtable th { text-align: right; font-weight: 500; color: var(--faint);
               font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
               padding: 3px 6px; }
/* The label column sits where the line starts: on the left in English, on
   the right in Persian. `left` put a Persian label in the middle of the
   table, against its count, not under «چی» (seen by the owner on the
   rules table, 2026-10-02). */
.tagtable th:first-child, .tagtable td:first-child { text-align: start; }
.tagtable td { text-align: right; padding: 4px 6px; font-family: var(--mono);
               border-top: 1px solid var(--line-soft); }
.customrow { display: flex; justify-content: space-between; align-items: baseline;
             gap: 10px; padding: 5px 0; border-bottom: 1px solid var(--line-soft);
             font-size: 12px; }
.customrow .cov { color: var(--faint); font-family: var(--mono); font-size: 11px; }

.mirrorrow { display: flex; align-items: baseline; gap: 8px;
             padding: 6px 0; border-bottom: 1px solid var(--line-soft); font-size: 12px; }
.mirrorrow .sym { font-weight: 600; font-family: var(--mono); min-width: 74px; }
.mirrorrow .cov { color: var(--dim); font-size: 11px; flex: 1;
                  font-family: var(--mono); }
.mirrorrow button { background: var(--panel-2); border: 1px solid var(--line);
                    color: var(--text); border-radius: 5px; padding: 3px 10px;
                    font-size: 11px; cursor: pointer; }
.mirrorrow button:hover { border-color: var(--accent); color: var(--accent); }
.mirrorrow button:disabled { opacity: .5; cursor: default; }

/* ---------- strategy laboratory ---------- */

.sheet.huge { width: 860px; max-width: 96vw; height: 88vh; }
.labpane .pad.col { align-items: stretch; }

.labgrid { display: flex; flex-wrap: wrap; gap: 8px; width: 100%; }
.labfield { display: flex; flex-direction: column; gap: 3px; font-size: 11px;
            color: var(--dim); }
.labfield span { white-space: nowrap; }
/* A name and a date both need room to be read; the rest of the box is the
   shared one. */
.labfield input, .labfield select { min-width: 92px; }

/* One row, one line, one size.
 *
 * Reported with a photograph of the laboratory's top row: «why are these not
 * aligned? Line them up with the ones beside them, and make them the same
 * size and shape as each other.»
 *
 * They were not, and the reason is that `.labfield` is a COLUMN - a caption
 * with its control under it - while `datefield.js` puts the calendar button
 * `afterend` of the input. In a field laid out as a row that is exactly
 * beside it, which is what the note there says and means. In a column it is
 * the next thing DOWN: a third row in the stack, which made the two date
 * fields taller than the three beside them, and `align-self: center` on the
 * row then lifted their caption and their box 12.2px above everything else.
 * The little glyph under each date in the photograph is that button.
 *
 * So a field holding one is a two-column grid instead: the caption across the
 * top, the box and the button side by side under it. No element moves in the
 * markup, which matters - every `.labfield input` selector and every id still
 * finds what it found before. */
.labfield:has(> .pickopen) {
  display: grid; grid-template-columns: 1fr auto;
  align-items: center; column-gap: 2px;
}
.labfield:has(> .pickopen) > span { grid-column: 1 / -1; }

/* And the same height, exactly rather than nearly.
 *
 * `.labstatic` was already matched to the controls by measurement - the note
 * on it says 29 against 38 and five pixels high. The date inputs were the
 * other way and much smaller about it: 37.4 against 38, which nobody would
 * see on its own and which stops the row being one row. Five kinds of control
 * have five sets of font metrics; the only way they come out identical is to
 * be told to.
 *
 * Not `.wide`, which is a row with its label beside the box and no stack to
 * line up. */
.labfield:not(.wide) > input,
.labfield:not(.wide) > select,
.labfield:not(.wide) > .labstatic {
  height: var(--field-h); box-sizing: border-box;
}
.labfield.wide { flex-direction: row; align-items: center; gap: 7px; }
.labfield.wide input { min-width: 0; }
/* And its caption is a SENTENCE, so it wraps.
 *
 * `.labfield span` is `nowrap` a few lines up, and that is right for the
 * ordinary kind: a caption sitting over its box in a row of fields beside
 * other fields, where "Positions at once" breaking after "Positions" reads as
 * two fields rather than one. A `.wide` field is the other shape - a switch
 * with a whole sentence next to it - and a sentence that may not wrap is as
 * wide as it is long.
 *
 * Measured: «A signal the other way closes what is open» came out 209px in a
 * column with 206 of room, so the side column grew a sideways scrollbar under
 * a stack of fields there is nothing to scroll sideways TO. Persian is longer
 * again. `design/side-overflow.mjs` names the offender rather than reporting
 * that something, somewhere, overflows. */
.labfield.wide > span { white-space: normal; min-width: 0; }

.labsweep {
  display: grid; grid-template-columns: 1fr 78px 78px 78px; gap: 6px;
  align-items: center; padding: 4px 0;
}
.labsweep label { font-size: 12px; color: var(--text); display: flex;
                  align-items: center; gap: 6px; }


#lab textarea {
  /* A code well is deliberately deeper than a field - that is what tells you
     it is a place to write a program rather than a name. The corner is the
     shared one, and the border is too. */
  width: 100%; background-color: var(--bg); background-image: none;
  padding: 9px 10px;
  font-family: var(--code); font-size: 12px; line-height: 1.5; resize: vertical;
  /* Pine is written left to right whatever the interface is doing around it. */
  direction: ltr; text-align: left;
}

.labchart { width: 100%; height: 140px; display: block;
            border: 1px solid var(--line); border-radius: 6px; }
.labhist  { width: 100%; height: 96px; display: block; }

.labtable { width: 100%; border-collapse: collapse; font-size: 11px;
            font-family: var(--mono); margin: 4px 0 10px; }
.labtable th {
  text-align: right; font-weight: 500; font-family: var(--sans, inherit);
  color: var(--faint); font-size: 10px; text-transform: uppercase;
  letter-spacing: .8px; padding: 5px 6px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.labtable th:first-child, .labtable td:first-child { text-align: left; }
.labtable td { text-align: right; padding: 4px 6px;
               border-bottom: 1px solid var(--line-soft); white-space: nowrap; }
.labtable tbody tr:hover { background: var(--panel-2); }
.labtable td.up { color: var(--up-ink); }
.labtable td.down { color: var(--down-ink); }
.labtable td.dim { color: var(--faint); }
.labtable td:first-child { font-size: 10px; color: var(--dim); }

#lab .statgrid b.up { color: var(--up-ink); }
#lab .statgrid b.down { color: var(--down-ink); }

/* the update button, when there is one */
#btnUpdate { border-color: var(--accent); color: var(--accent); font-weight: 600; }
#btnUpdate:hover { background: rgba(38,166,123,.12); }
#upBody p.sub b { color: var(--text); }
#upNotes {
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  padding: 10px 12px; margin: 8px 0; font-size: 12px; color: var(--dim);
  white-space: pre-wrap; max-height: 180px; overflow-y: auto;
}

/* signing in from inside the application */
.chip.mini { padding: 3px 9px; font-size: 11px; margin-inline-start: 6px; }
#acctOrders { margin: 8px 0; }
.acctrow {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 7px; margin-bottom: 6px; font-size: 12px;
}
/* The reference is the only thing here that may shrink. Everything else is a
   word or a button, and a Persian state that wraps to two lines takes the day
   count with it and turns a row into a paragraph. */
.acctrow > span:first-child { flex: 0 0 auto; white-space: nowrap; }
.acctrow .ref {
  font-family: var(--mono); color: var(--dim); font-size: 11px;
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.acctrow .sp { flex: 0 0 0; }
.acctrow button { padding: 5px 11px; font-size: 12px; }
/* What the order is doing, at the end of the row and in its own colour:
   amber while it is still waiting for money, quiet once it can no longer be
   paid at all. */
.acctrow .why {
  font-size: 11.5px; color: var(--faint); text-align: end;
  flex: 0 0 auto; white-space: nowrap;
}
.acctrow button { flex: 0 0 auto; white-space: nowrap; }
.acctrow .why.wait { color: var(--gold-ink, var(--gold)); }
.acctrow.done { opacity: .72; }
/* A code somebody is GIVEN - an order number, a recovery key, an amount to
   transfer - and this is not the box they write one in.
   It was called `.codebox` too, and there are two rules under that name in
   this file doing two unrelated jobs. Nothing showed it while the code
   editor happened to overrule every line of this one; the moment the editor
   stopped repeating what it could inherit, the editor came out dashed and
   blue and its text dropped to 4.22 against its own ground. Two things with
   one name is a fault waiting for somebody to tidy up. */
.paycode {
  font-family: var(--mono); font-size: 16px; letter-spacing: 2px;
  background: var(--bg); border: 1px dashed var(--accent); border-radius: 7px;
  padding: 11px; text-align: center; color: var(--accent);
  direction: ltr; margin: 8px 0; word-break: break-all;
}

/* The buy button, and the old price beside a discounted one.
   It used to be a `.chip`, which reads as a label rather than something to
   press — a customer entered a free code, was told the copy was free, and had
   no idea the price beside it was the button. */
.acctrow .payBuy { font-weight: 600; padding: 7px 14px; }

/* One plan, two prices, two acts - «two rows», picked from five drawings.
 *
 * The plan's name and length on top; under it one pressable row per way to
 * pay, each carrying its own figure and a dot in the way's own colour. Toman
 * is the product's blue and goes to the bank card; USDT is the colour USDT
 * has in the world and goes to a chain. The row IS the button: there is
 * nothing else on it to press. */
.acctrow.plan { flex-direction: column; align-items: stretch; gap: 6px; }
.acctrow.plan .top { display: flex; align-items: center; gap: 8px; }
.acctrow.plan .way {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  border-radius: 8px; background: var(--field); border: 1px solid var(--line);
  color: var(--text); font: 12.5px var(--ui); cursor: pointer; text-align: start;
  transition: border-color .12s ease, background-color .12s ease;
}
.acctrow.plan .way:hover { border-color: var(--line-strong); background: var(--panel-3); }
.acctrow.plan .way:disabled { opacity: .55; cursor: default; }
.acctrow.plan .way i { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.acctrow.plan .way.tm i { background: var(--accent); }
.acctrow.plan .way.us i { background: var(--usdt); }
.acctrow.plan .way small { color: var(--faint); font-size: 11px; }
.acctrow.plan .way b {
  margin-inline-start: auto; font-weight: 600; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* The plan's price struck through when credit takes some of it off, and
   the line under the rows that names the credit. */
.acctrow.plan .way b s { color: var(--faint); font-weight: 400; margin-inline-end: 4px; }
.credline { margin: 2px 0 0; color: var(--gold-ink); }
.ordhead + .credline { margin: -4px 0 8px; }

/* The head of an open order: what it is for and what it asks, in both
   currencies when it is sold in both, and under it the one line about a
   discount code. */
.ordhead {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  flex-wrap: wrap; margin-bottom: 8px;
}
.ordhead .what { font-weight: 600; }
.ordhead .how { display: flex; align-items: baseline; gap: 8px;
  font-variant-numeric: tabular-nums; }
.ordhead .how b { font-weight: 700; }
.ordhead .sep { color: var(--faint); }
.codeline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 12px; min-height: 24px; }
.codeline .lnk { background: none; border: 0; padding: 0; color: var(--accent);
  font: 12.5px var(--ui); cursor: pointer; }
.codeline .lnk:hover { text-decoration: underline; }
/* `.codeentry`, not `.codebox`: that name is the Expert code editor's
   (`.codebox` above, with its padding, its vertical resize grip and its
   `overflow: auto`), and this span wore it too - which is where the black
   band, the grip in the corner and the scrollbar under the row came from,
   not from widths (the adversary, eighth pass, 16 September 2026). The
   file's own note at «two rules under that name» had warned of exactly this.

   The field and its button share the line rather than each insisting on a
   width: the box takes the room that is left, the button keeps its own, and
   when the line is too narrow for both the button drops under the field
   rather than the field shrinking under its own placeholder - at 400px the
   field was 110px and showed «Discount or inv». */
.codeline .codeentry {
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap;
  flex: 1 1 170px; min-width: 0;
}
.codeline .codeentry .chip { flex: 0 0 auto; }
.codeline .codeentry.hidden, .codeline .lnk.hidden { display: none; }
.codeline .codeentry input {
  /* No narrower than its own placeholder, in either language, whatever the
     window: see design/payflow.mjs, which measures the placeholder against
     the font the field is drawn in - at 1400 and at 400. */
  flex: 1 1 auto; min-width: 14ch; width: auto;
  height: 30px; padding: 0 10px; border-radius: 8px;
  background: var(--field); border: 1px solid var(--line); color: var(--text);
  font: 13px var(--ui); box-shadow: none;
}
.codeline .codeentry input:focus { outline: 0; border-color: var(--accent); }
/* --up, not --buy. «Code applied» is a thing that went well, not a purchase,
   and the buy colour means one thing in this program. The test that counts
   where the buy colour is read caught it. */
.codeline .good { color: var(--up); }
.acctrow .payBuy.deal { background: var(--accent); border-color: var(--accent); }
.acctrow .payBuy .was { opacity: .55; font-weight: 400; margin-inline-end: 4px; }

/* The amount to transfer. Bigger than everything around it on purpose: a Blu
   notification names no sender, so this number is the only thing that will
   connect the payment to the person who made it, and somebody who reads it
   carelessly and rounds it has paid into a void. */
.paycode.big { font-size: 26px; font-weight: 700; letter-spacing: 1px;
  padding: 16px; border-style: solid; }

/* ---------- signing in ---------- */
/*
   The dialog somebody meets before they have seen anything else, so it is the
   one place in this interface that is allowed to look designed rather than
   merely quiet. Everything else stays out of the way of a chart; this has no
   chart to stay out of the way of.
*/
#welcome .sheet {
  width: 420px;
  background:
    radial-gradient(120% 80% at 50% -20%,
      color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
    var(--panel);
  border-color: var(--line-strong);
}
#welcome > .sheet > header { border-bottom: 0; padding-bottom: 0; }
#welcome > .sheet > header b { font-size: 15px; letter-spacing: .2px; }
#welcome .pad { padding: 6px 22px 22px; gap: 0; }

/* The badge and the name live in `shell.css`, in one rule, laid out as a
   column. There were two definitions of this class - this one for a centred
   column and another for a row - and between them the badge was pushed to one
   wall of the window and the name to the other. This one also carried the
   blue of the palette from before Photoshop, written as a literal. */
#welcome p.sub { text-align: center; margin: 0 0 16px; line-height: 1.7; }

/* the three ways in, as one control rather than three buttons */
#welcome .seg.small {
  display: flex; background: var(--bg); border: 1px solid var(--line);
  border-radius: 9px; padding: 3px; gap: 2px; margin: 0 0 14px;
}
#welcome .seg.small button {
  flex: 1; border: 0; background: none; color: var(--dim);
  padding: 8px 4px; border-radius: 7px; font-size: 12px; margin: 0;
  transition: background .12s, color .12s;
}
/* `--sel`, the chosen row's colour everywhere else (`.seg button.on`): the
   light theme's `--panel-2` on `--bg` was 1.01 to 1, no chosen tab at all
   (the round-3 area-13 adversary, F4). */
#welcome .seg.small button.on { background: var(--sel); color: var(--text); }
#welcome .seg.small button:hover:not(.on) { color: var(--text); }

#welcome .field { display: block; margin: 0 0 11px; }
#welcome .field > span {
  display: block; font-size: 11px; color: var(--dim); margin: 0 0 5px;
  letter-spacing: .2px;
}
/* The first window anybody sees, and the only place a field is deliberately
   bigger than the standard one: a name and a password typed once, on an empty
   screen, with nothing to be dense about. Bigger is all it says now - the
   ground, the border and the ring it used to draw for itself are the shared
   ones, and its ring is the one they all use. */
#welcome .field input {
  width: 100%; height: 44px; padding: 0 13px; font-size: 14px;
}
#welcome .field input::placeholder { color: var(--faint); }

#welcome #acctGo {
  width: 100%; background: var(--accent); border-color: var(--accent);
  color: #fff; font-weight: 600; font-size: 14px; padding: 12px;
  border-radius: 9px; margin: 4px 0 0;
}
#welcome #acctGo:hover { filter: brightness(1.08); }
#welcome #acctGo:disabled { filter: none; }

/* This panel is a full-height sheet down one side, so with the sign-in at the
   top there is room under it. The language question takes the foot of it
   rather than leaving the space empty: `margin-top: auto` on the line above
   pushes the line and the question below it down together. */
#welcome .pad > .rule { margin: 16px 0 12px; margin-top: auto; }

#welcome #acctOut2 { margin-top: 12px; text-align: center; }
#welcome .paycode { letter-spacing: 3px; font-size: 17px; }

/* ---------- nothing escapes its box ---------- */
/*
   Reported: the Indicators dialog had its buttons and the custom-indicator
   names hanging out past the right edge.

   The cause is worth writing down, because it is not the obvious one. `.pad.col`
   is a single-line column flex container, so every child sits on one flex line,
   and the cross size of that line is the *widest* child. `align-items: stretch`
   then stretches every other child to match. So one row that could not fit —
   three buttons ending in "Paste a TradingView script", 367px of min-content
   against 330px of room — did not merely overflow itself: it widened the line,
   and every sibling stretched with it. That is why "None yet" was hanging out
   of the box too, and why it looked like the whole panel had come apart.

   Hence a guard rather than a patch. A row of buttons wraps; a flex child may
   shrink; a long word breaks; and the sheet clips whatever is left. Any one of
   those alone would have fixed this instance and left the next one to be
   reported by a customer.
*/

/* Rows of controls wrap instead of growing past the edge. */
.addrow { flex-wrap: wrap; }

/* A flex child may be narrower than its content. Without this, `min-width:
   auto` means "never smaller than min-content", which is what let one row set
   the width of the whole column. */
.pad > *, .pad.col > *, .addrow > *, .labgrid > *, .col > * { min-width: 0; }
.pad > *, .pad.col > * { max-width: 100%; }

/* A long unbroken run of characters — a path, a URL, a licence id — breaks
   rather than pushing the panel open. `break-word` only breaks when there is
   no other option, so ordinary prose is untouched. */
.sheet, .panel, .modal { overflow-wrap: break-word; }

/* And the last line of defence: the rounded box clips. If some future content
   still finds a way to be too wide, it is cut off at the border instead of
   being drawn over the page — visibly wrong inside the dialog rather than
   invisibly wrong outside it. The scrolling body inside is unaffected. */
.sheet { overflow: hidden; }

/* Long names in a two-column row: the name takes the room, the code shrinks
   and ellipses rather than pushing. */
.customrow { min-width: 0; }
.customrow .nm { min-width: 0; overflow-wrap: break-word; }
.customrow .cov { min-width: 0; overflow: hidden; text-overflow: ellipsis;
                  white-space: nowrap; }

/* ---------- who is signed in ---------- */

/* The same person drawn the same way in three places — the top bar, the
   dialog, and settings — because a profile that looks different in each is
   three things to recognise instead of one. */
.avatar {
  /* One number for how big the disc is, because the mark inside it is a
     fraction of that number rather than a percentage of the box. See the note
     on `.avatar svg` for what a percentage did here. */
  --disc: 40px;
  /* The grid is for the letter and the question mark. The mark is placed
     against this box instead - see the note on `.avatar > svg`. */
  display: grid; place-items: center; position: relative;
  width: var(--disc); height: var(--disc); border-radius: 50%;
  background: linear-gradient(140deg, #3b6ea8, #2b4f79);
  color: #fff; font-weight: 600; font-size: 17px;
  flex: 0 0 auto; text-transform: uppercase; user-select: none;
}
.avatar.mini { --disc: 20px; font-size: 11px; }
.avatar.out { background: var(--panel-2); color: var(--faint);
              border: 1px solid var(--line); }

/* A chosen mark, or a chosen photograph. Both fill the disc completely, so
   the padding is what keeps a mark from touching the rim. */
/* The marks are silhouettes rather than line drawings, so they can be drawn
   larger than an outline could: 0.62 left a small shape adrift in a lot of
   ground and everything looked the same at toolbar size.
 *
 * A fraction of the disc, not a percentage of the box. This was `74%`, and a
 * percentage on a grid item in an auto-sized track is circular: the track is
 * sized from the item and the item from the track, so what comes back is the
 * user agent's default for a replaced element - which is 2:1, not a square.
 * At forty pixels it resolved anyway; on the twenty pixel toolbar button it
 * came out four pixels by one and a half, and the button was black. Every
 * reading said the mark was there, because it was. */
/*
 * Placed against the disc, not laid out inside it. As a grid item the mark had
 * nothing definite to resolve against - the track sizes itself from the mark
 * and the mark from the track - so both its size and its position came out of
 * that circle. At forty pixels it landed right anyway. On the twenty pixel
 * toolbar button the mark measured four pixels by one and a half, and a shape
 * that fills the disc sat six pixels right and eight down of it with
 * `overflow: hidden` cropping the rest. The button was black, or a corner of
 * the art. Every reading said the mark was there, because it was.
 */
.avatar > svg {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: calc(var(--disc) * .74); height: calc(var(--disc) * .74); display: block;
}
.avatar.haspic { background-size: cover; background-position: center; }

/* The one in the dialog is also the button that changes it, so it says so on
   hover rather than only in a tooltip. */
button.avatar { border: 0; padding: 0; cursor: pointer; position: relative;
                overflow: hidden; }
button.avatar::after {
  content: '';
  position: absolute; inset: 0; border-radius: 50%;
  box-shadow: inset 0 0 0 2px var(--text);
  opacity: 0; transition: opacity .14s ease;
}
button.avatar:hover::after { opacity: .55; }

/* Above the other dialogs, because it is opened from inside one.
   Every `.modal` shares a z-index, so the one later in the markup wins — and
   this one is earlier than both the account panel and settings, which are the
   two places it opens from. It appeared underneath them: open, invisible, and
   swallowing no clicks because they were landing on the panel on top of it.
   Which read, correctly, as "it does not work at all". */
#avatarPick { z-index: 70; }

/* A row of buttons with no field in it sits in the middle.
 *
 * `.addrow` is built for a field with a button after it: it packs its children
 * against the start and lets the field take up the slack. Used for buttons
 * alone there is no field to take the slack, so they pile against one edge and
 * the rest of the line is empty - which reads as something missing rather than
 * as the end of a row.
 *
 * Asked of the row itself rather than listed window by window, so a row built
 * later is right without anybody remembering to add it. The middle of a line
 * is the same place in both languages, so this needs saying only once. */
.addrow:not(:has(input, select, textarea)) { justify-content: center; }

/* Picking one. Big enough to tell apart, small enough that twelve fit without
   the dialog needing to scroll. */
.avgrid {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px;
  margin-bottom: 12px;
}
.avgrid button {
  aspect-ratio: 1; width: 100%; padding: 0; border: 0; border-radius: 50%;
  cursor: pointer; display: grid; place-items: center; position: relative;
}
.avgrid button svg { width: 60%; height: 60%; }

/* The door to somebody's own colours, in its two states.
 *
 * There used to be a tick here called "Use the look we ship", ticked, sitting
 * directly above a brightness slider, a contrast slider and five swatches -
 * all drawn exactly as they are when they work, none of them doing anything.
 * A tick that turns three visible controls into decoration is the whole
 * reason the window could not be read, so it is gone and the two states are
 * separate rows: only one of them is ever on screen.
 *
 * The state is read from `Theme.builtin()` rather than stored here, so the
 * window cannot end up saying one thing while the program does another. */
.lookrow {
  display: flex; align-items: center; gap: var(--s3);
  flex-wrap: wrap; margin: var(--s2) 0 2px;
}
.lookrow .lookwhat { flex: 1 1 220px; min-width: 0; }
.lookrow .lookwhat b { display: block; font-size: 12.5px; }
.lookrow .lookwhat .sub {
  display: block; margin-top: 2px; font-size: 11px; color: var(--faint);
  white-space: normal;
}
/* The one that says you have left the shipped look. It is the accent because
   it is a state rather than a control - the same reason a selected thing is
   the accent everywhere else in this program. */
.ownbanner {
  display: flex; align-items: center; gap: var(--s2);
  flex-wrap: wrap; margin: var(--s2) 0 var(--s1);
  padding: 9px var(--s3); border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
}
.ownbanner b { font-size: 12.5px; flex: 1 1 auto; min-width: 0; }
/* Everything that only exists once the door is open. */
.ownonly { display: flex; flex-direction: column; gap: 0; }

/* A shape is not a mark on a disc, it is the disc: it goes edge to edge and
   the element supplies nothing but the circle that clips it. Both selectors
   are needed because the tiles in the picker are not `.avatar` elements, and
   both have to out-specify the 74%/60% above rather than merely repeat it. */
.avatar.full, .avgrid button.full { background: none; border: 0; overflow: hidden; }
/* These two fill the disc rather than sitting on it, so they take the whole
   number instead of a fraction of it. The picker's tiles are not `.avatar`
   elements and keep their own percentage, which resolves there. */
.avatar.full > svg { width: var(--disc); height: var(--disc); }
.avgrid button.full svg { width: 100%; height: 100%; }

/* The two groups are headed, so each heading takes a whole row of the grid
   rather than a cell of it. */
.avgrid .avhead {
  grid-column: 1 / -1; font-size: 11px; color: var(--dim);
  margin: 6px 0 -2px; align-self: end;
}
.avgrid .avhead:first-child { margin-top: 0; }
.avgrid button::after {
  content: ''; position: absolute; inset: -3px; border-radius: 50%;
  border: 2px solid transparent; transition: border-color .14s ease;
}
.avgrid button:hover::after { border-color: var(--line); }
.avgrid button.on::after { border-color: var(--accent); }

/* In the top bar, the circle alone. The bar is the most contested strip in
   the application — a name there costs about eighty pixels and pushes real
   buttons out of reach on a laptop. The name is on the button's tooltip, in
   the dialog it opens, and in settings; the circle is what makes it findable
   at a glance, and that is what it is for. */
.chip.person { display: flex; align-items: center; gap: 7px; padding: 5px 7px; }
.chip.person > span:last-child { display: none; }

/* Room to spare: say who it is outright. */
@media (min-width: 1650px) {
  .chip.person { padding: 5px 11px; max-width: 190px; }
  .chip.person > span:last-child {
    display: block;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  }
}

.profile {
  display: flex; align-items: center; gap: 12px;
  padding: 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-2);
}
.profile .who { display: flex; flex-direction: column; min-width: 0; flex: 1 1 0; }
.profile .who b { font-size: 15px; overflow: hidden;
                  text-overflow: ellipsis; white-space: nowrap; }
.profile .who .sub { font-size: 12px; }

/* The licence, said once and prominently. It is the thing somebody signed in
   to sort out, so it does not belong at the bottom in grey. */
.licrow {
  display: flex; align-items: center; gap: 8px;
  margin: 10px 0 4px; padding: 9px 11px; border-radius: 8px;
  border: 1px solid var(--line); font-size: 13px;
}
.licrow.good { border-color: color-mix(in srgb, var(--up) 55%, var(--line));
               background: color-mix(in srgb, var(--up) 12%, var(--panel)); }
.licrow.none { border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
               background: color-mix(in srgb, var(--accent) 12%, var(--panel)); }
.licrow .dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.licrow.good .dot { background: #4caf7d; }
.licrow.none .dot { background: #d08a45; }

/* Folded away: it matters to a handful of people once, and it was sitting
   open above the sign-out button asking everybody else for a reference. */
details.quiet { margin-top: 12px; }
details.quiet > summary {
  cursor: pointer; color: var(--dim); font-size: 12px; list-style: none;
}
details.quiet > summary::-webkit-details-marker { display: none; }
details.quiet > summary::before { content: "＋ "; color: var(--faint); }
details.quiet[open] > summary::before { content: "− "; }
details.quiet > summary:hover { color: var(--text); }

/* ==========================================================================
   Long-session polish layer — purely cosmetic (colour, depth, focus, motion).
   Nothing here changes behaviour or layout: it adds the quiet depth and the
   calm, responsive feel that makes a screen comfortable to sit in front of for
   hours. Kept at the end so its refinements win the cascade where intended.
   ========================================================================== */

/* Thin, themed scrollbars everywhere — the interface had one only on the top
   bar; now the dock, watchlist and panels get the same quiet treatment. */
/* From the palette, not from a hex.
 *
 * These were two fixed colours with a light-theme override beside them, and
 * both faults followed from that. A fixed colour does not move when the
 * brightness does, so dimming the screen left the bar sitting where it was
 * while everything around it went; and against the profile drawer it measured
 * 1.18 to one, under the floor every other edge in this program has to clear.
 * Reported as a drawer with no scroll bar at all, which is what 1.18 looks
 * like.
 *
 * `--line-strong` is the border of a control, which is what this is: 1.86 to
 * one in the dark theme and 2.35 in the light one, and it is one of the toned
 * colours, so it holds those figures wherever the brightness is set. */
* { scrollbar-color: var(--line-strong) transparent; }
/* Kept for the width, and only for it. Setting `scrollbar-color` makes
   Chromium ignore these pseudo-elements entirely - measured, the bar came out
   15px wide while this rule asked for 10 - so the colours below are what the
   engine falls back to if that ever changes, and never what it uses today. */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line-strong); border: 2px solid transparent;
  background-clip: padding-box; border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--dim); }
::-webkit-scrollbar-corner { background: transparent; }

/* Text selection and keyboard focus in the interface's own accent, so a
   selection reads as intentional and a keyboard user can always see where
   they are — without changing anything for the mouse. */
::selection { background: color-mix(in srgb, var(--accent) 30%, transparent); }
:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; border-radius: 5px; }
/* A window holds the keyboard as it opens (crash.js `moveInto`), on the sheet
   itself so the next Tab is its first control. The sheet is not a control:
   no ring round the whole window. */
.sheet[tabindex="-1"]:focus, .sheet[tabindex="-1"]:focus-visible { outline: none; }

/* One calm transition curve across the small controls, so hovers and presses
   feel responsive rather than instant-flat. Cosmetic properties only. */
.chip, .icon, .tab, .primary, .act, .mini, .kill,
.tfs button, .seg button, .stepper button, #topbar .iconbtn, .pctquick button {
  transition: background-color .14s ease, border-color .14s ease,
              color .14s ease, box-shadow .14s ease, transform .12s ease;
}

/* A hairline of lift under the top bar so it sits above the chart rather than
   merely bordering it. */
#topbar { box-shadow: 0 6px 16px -12px rgba(0,0,0,.8); }

/* The three-step elevation made visible: the raised quote block and the
   account rows get the faintest inner separation, and floating surfaces cast a
   real shadow so they read as above the page. */
.quote .side { box-shadow: var(--elev-1); }
.quote .buy  { background: color-mix(in srgb, var(--buy) 9%,  var(--panel-2)); }
.quote .sell { background: color-mix(in srgb, var(--sell) 9%, var(--panel-2)); }
.sheet, .topmenu, #tooltip, #toolFlyout, .flyout, #diagOverlay .diagsheet {
  box-shadow: var(--elev-2);
}

/* The primary and play buttons are where the eye goes to act — give them a
   soft glow on hover so the most important controls feel alive. */
.primary:hover { box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--accent) 65%, transparent); }
.icon.play.on { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent),
                            0 4px 16px -6px color-mix(in srgb, var(--accent) 55%, transparent); }

/* Calmer chip/icon hover — a touch of the accent's neighbourhood instead of a
   flat grey jump. */
.chip:hover, .icon:hover { border-color: var(--line-strong); background: var(--hover); }

/* The active timeframe and dock tab carry the accent a little more confidently. */
.tfs button.active { box-shadow: 0 2px 8px -3px color-mix(in srgb, var(--accent) 70%, transparent); }

/* ---------- when something breaks ---------- */
#crash {
  position: fixed; inset: 0; z-index: 90; display: flex;
  align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .55);
}
#crash .crashcard {
  width: 420px; max-width: 92vw; padding: 20px 22px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .6);
  display: flex; flex-direction: column; gap: 10px;
}
#crash .crashtitle { font-size: 15px; color: var(--text); }
#crash p { margin: 0; font-size: 13px; line-height: 1.6; color: var(--dim); }
#crash p b { color: var(--text); }
#crash .sub { font-size: 12px; color: var(--faint); }
#crash .crashrow { display: flex; gap: 8px; margin-top: 4px; }

/* ---------- a copy that may not keep running ---------- */
#stopped {
  position: fixed; inset: 0; z-index: 95; display: flex;
  align-items: center; justify-content: center; background: var(--bg);
}
/* The update window is the way out of this screen, so it opens above it. */
body:has(#stopped) #update { z-index: 96; }
#stopped .stopcard {
  width: 440px; max-width: 92vw; padding: 24px 26px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  display: flex; flex-direction: column; gap: 11px;
}
#stopped .stoptitle { font-size: 16px; color: var(--text); }
#stopped p { margin: 0; font-size: 13px; line-height: 1.65; color: var(--dim); }
#stopped .sub { font-size: 12px; color: var(--faint); }
#stopped .paycode { font-size: 12px; word-break: break-all; }
#stopped .stoprow { display: flex; gap: 8px; margin-top: 4px; }

/* ---------- trading from the chart ---------- */
/* The chart's top-left, which is the corner MetaTrader uses for one-click
   trading. Never the right: the price axis and its labels live there. */
/* Smaller than it was. This sits *on* the chart, so every pixel it takes is a
   pixel of price nobody can see, and at the old size it covered a candle and a
   half at a normal zoom. Everything here is proportional to that: the box, the
   two buttons, the figures and the volume input all came down together, and
   the price stayed monospaced so it does not jitter as it ticks. */
/* Trading from the chart, in MetaTrader 5's shape.

   It used to be two filled slabs of red and blue with the price printed small
   inside them, which is a lot of paint to hang over a chart and made the price
   - the only thing on it that changes - the quietest part. Here the colour is
   a stripe on the outside edge, the price is the largest thing, and the strip
   is low enough to sit above the candles without covering them.

   Forced left-to-right: SELL is on the left of BUY on every trading platform
   there is, and mirroring that in Persian would put a trader's hand on the
   wrong button. The numbers are Latin either way. */
/* ONE width for both faces, written once.
 *
 * The strip measured 337 wide and the opened panel 268, so the thing changed
 * shape under the hand every time it opened - and the strip, which is the
 * face somebody looks at most, was the wider of the two while holding less.
 * Its three columns were 96, 120 and 96 for a word and a price each.
 *
 * 268 rather than something smaller, and the panel decides it rather than the
 * strip: the open face puts a minus, a label, a figure, a unit and a plus in
 * one row, twice, and 268 is what those need. Below it the English REWARD
 * starts eating the number - measured at 21px and clipped, earlier today,
 * which is how that fault nearly shipped. So the strip comes down to the
 * panel rather than the panel down to nothing. */
#chartTrade {
  --ct-w: 268px;
  width: var(--ct-w);
  position: absolute; left: 12px; top: 8px; z-index: 8;
  direction: ltr;
  display: flex; align-items: stretch;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 7px; overflow: hidden; box-shadow: var(--elev-2);
}
#chartTrade.hidden { display: none; }
/* The strip's handle. Same three dots as the open panel's, because it is the
   same gesture and a second symbol for it would be a second thing to learn.
   Gone when the panel is open, where the header is the handle instead. */
#chartTrade .ct-grip {
  flex: none; display: flex; flex-direction: column; justify-content: center;
  gap: 2.5px; padding: 0 4px; cursor: move; user-select: none;
  border-right: 1px solid var(--line-soft);
}
#chartTrade .ct-grip i {
  width: 2.5px; height: 2.5px; border-radius: 50%; background: var(--faint);
}
#chartTrade .ct-grip:hover i { background: var(--dim); }
#chartTrade.adv .ct-grip { display: none; }
#chartTrade.dragging { transition: none; }
#chartTrade button { border: 0; cursor: pointer; font: inherit; }
/* They share the width now instead of each demanding a floor of their own.
   `min-width: 0` is the part that matters: without it a flex child will not
   go below its content, and three columns that each refuse to shrink push the
   strip back out to 337 however narrow the parent is told to be. */
/* Asked a third time to make this smaller, and the row itself is what is
 * left. The label line and the figure are stacked with room around them: the
 * padding comes down and the gap between them goes, and the PRICE does not
 * move. It is 15px because it is the thing somebody is reading, and shrinking
 * it would be cutting the one part of this that is doing work. */
#chartTrade .ct-sell, #chartTrade .ct-buy {
  display: flex; flex-direction: column; gap: 0;
  flex: 1 1 0; min-width: 0; padding: 3px 5px; background: transparent;
  overflow: hidden;
}
#chartTrade .ct-sell { align-items: flex-start; color: var(--sell);
                       border-left: 3px solid var(--sell); }
#chartTrade .ct-buy  { align-items: flex-end;   color: var(--buy);
                       border-right: 3px solid var(--buy); }
#chartTrade .ct-sell:hover { background: color-mix(in srgb, var(--sell) 14%, transparent); }
#chartTrade .ct-buy:hover  { background: color-mix(in srgb, var(--buy) 14%, transparent); }
/* Capitals by the rule rather than by how the word happens to be typed:
   SELL and BUY are written in capitals in the markup and `spread` is not, so
   the three small lines were two shapes. Persian has no capitals, so this
   changes nothing there and the Persian labels stay as they are written. */
#chartTrade .ct-lbl {
  font-size: 9px; font-weight: 700; letter-spacing: 1.3px; opacity: .75;
  text-transform: uppercase;
}
/* One height for the figure line in all three columns, so the price, the
   volume and the price sit on the same baseline. The volume carries a border
   and the prices do not, which on its own left them two pixels apart. */
/* The figures stay 15px - they are what somebody is reading - but the line
   they sit on no longer reserves more room than they use, and a price too
   long for a narrower column is clipped rather than allowed to push the whole
   strip wider. */
/* 13px, and this is a promise being taken back rather than a tidy-up.
 *
 * I said the figures would not move: they are what somebody reads, and
 * shrinking them is cutting the part of the strip that does the work. Then
 * the picture showed «1.1752'» and «1.1753'» - the last digit clipped off
 * both prices, by the very `overflow: hidden` put there to stop a long price
 * widening the bar. The numbers never said so; only looking did.
 *
 * At 268 wide, a 15px price does not fit beside a lot box and two icons. One
 * of those has to give, and a whole price at 13px beats a cut one at 15. The
 * width is the thing that was asked for three times; the size of the digits
 * was not.
 *
 * `clip` rather than an ellipsis on purpose: if this is ever wrong again, a
 * price ending mid-digit is meant to look broken. An «…» reads like a
 * decision somebody made. */
#chartTrade .ct-px {
  font: 600 13px var(--mono); font-variant-numeric: tabular-nums; line-height: 1.1;
  min-height: 17px; display: flex; align-items: center;
  max-width: 100%; overflow: hidden; text-overflow: clip;
}
/* The middle column: how much, and what it costs to cross.
   Same two lines and the same padding as the sides, so the three columns are
   one object. It used to have its own darker ground as well as its own type
   scale, and between them it read as something stuck on afterwards. */
/* The middle holds the lot box, which cannot shrink past its own controls -
   so it is the one column given a fixed share, and the two prices take what
   is left. `flex: none` says that out loud rather than leaving it to a
   min-width that the next person would read as a guess. */
#chartTrade .ct-mid {
  display: flex; flex-direction: column; align-items: center; gap: 0;
  flex: none; width: 78px; padding: 3px 4px; background: transparent;
  border-left: 1px solid var(--line); border-right: 1px solid var(--line);
}
#chartTrade .ct-vol { display: flex; align-items: center; gap: 3px; height: 19px; }
/* The figure line, and it is a figure like the two prices are: same size,
   same weight, same face, same baseline. It was 11px against their 15px. */
#chartTrade .ct-vol { gap: 3px; }
#chartTrade .ct-vol input {
  /* 19 now, from the row above it: this one floats over the chart in a strip a
     line tall, so it is the one field that cannot be 34. Transparent for the
     same reason - a ground here would be a tile on the candles. */
  width: 32px; height: 19px; text-align: center;
  background-color: transparent; background-image: none;
  border-color: var(--line-soft);
  border-radius: 6px; padding: 0 2px;
  font: 600 15px var(--mono); line-height: 1.1;
  box-shadow: none;
}
#chartTrade .ct-vol input:hover { border-color: var(--line); }
/* Grown with the figure they change. At 16 wide against a 15px number they
   were something to aim at rather than something to press. */
#chartTrade .ct-step {
  width: 17px; height: 19px; border-radius: 6px;
  background: var(--panel-2); color: var(--dim);
  font-size: 13px; line-height: 1;
  transition: background-color .12s ease, color .12s ease;
}
#chartTrade .ct-step:hover { color: var(--text); background: var(--panel-3); }
#chartTrade .ct-step:active { transform: translateY(1px); }
/* The spread, in points. It belongs here rather than in the settings window:
   it is the number that decides whether a trade was worth taking, and it is
   the one thing on this strip a person cannot work out from the other two.
   On the label line, in the label's own size and weight, so the tops of the
   three columns line up as well as the bottoms. */
#chartTrade .ct-spread {
  color: var(--accent); font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 4px;
}
#chartTrade .ct-spread b { font-weight: 700; font-family: var(--mono); }

/* ---------------------------------------------------------------------------
   The same strip, opened out.

   One element with two faces rather than a second window. In the small face
   the row of three columns is the whole thing; in the open one that row is put
   away and a form takes its place, anchored to the other side of the chart
   because it is tall and the candles that matter are the recent ones on the
   right... which is exactly why it does NOT go there: it sits on the left,
   over the oldest bars on screen, where a tall panel costs the least.

   Every field here is a second way of typing into the order ticket. Nothing
   is stored in this panel: the risk is `#inRisk`, the stop is `#inSL`, the
   target is `#inTP` worked out from R, and the kind is `S.orderKind`. Two
   panels that each remembered their own answer would disagree the first time
   somebody used both.
--------------------------------------------------------------------------- */
/* The door, as a row of its own under the three columns.

   Taken out of the strip's own sizing altogether. As a wrapped flex item it
   still offered its content width to the container - measured, 349px against
   337 - and in the state where it reads «no target» it was the longest thing
   on the bar, so adding it made the bar wider, which is the one thing it was
   not allowed to do. Absolutely positioned it offers nothing, and the strip
   reserves its height with padding instead. */
/* The door is a column on the end now, not a row underneath.
 *
 * Measured: the strip was 268x75 and that row was 27 of it - thirty-six per
 * cent of the height, to carry two small figures and a chevron. Asked twice
 * to make it smaller, and this is where the room actually is: narrowing the
 * columns took nine pixels off the height and this takes twenty-seven.
 *
 * What is given up, said plainly rather than quietly: the risk and the target
 * no longer READ on the small face. That was a deliberate thing - a way in
 * that also tells you something - and it is a real loss. They are still one
 * press away and they are the first thing in the open face, which is why it
 * is the half worth giving up rather than the height.
 *
 * The chevron sits under the ×, in the column the × already owns, so the
 * strip's own row keeps every pixel of the width and the hand finds the close
 * exactly where it always was. */
#chartTrade .ct-door {
  flex: none; width: 23px; align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  gap: 0; background: none; color: var(--faint);
  border: 0; border-left: 1px solid var(--line-soft);
}
#chartTrade .ct-door:hover { background: var(--panel-3); color: var(--text); }
/* The figures are in the markup still - a screen reader reads the way in as
   «1.0% and no target», which is what it opens - but they are not drawn. */
#chartTrade .ct-door b,
#chartTrade .ct-door i,
#chartTrade .ct-door > svg:first-of-type { display: none; }
#chartTrade .ct-door .v { color: inherit; }
/* The × and the way in share one narrow column, stacked. */
#chartTrade .ct-x { padding: 0 5px; }
#chartTrade .cta { display: none; }

/* The open face. */
#chartTrade.adv {
  /* The same width as the strip, from the same place. It was written here as
     a second 268 that happened to agree with nothing; now there is one number
     and the two faces cannot drift apart. */
  display: block; width: var(--ct-w); border-radius: 12px; padding-bottom: 0;
}
/* The strip does NOT turn, opened out or not.
   It is the working surface - a panel reached for without looking - and the
   rule here is that only windows and the review bar change sides. Turning the
   whole thing also swapped the minus and the plus against the small strip's
   own, which is the hand landing on the wrong end of a stepper.
   What did have to change is the note underneath: see `.cta-say`. */
#chartTrade.adv .ct-sell, #chartTrade.adv .ct-mid,
#chartTrade.adv .ct-buy, #chartTrade.adv .ct-door,
#chartTrade.adv > .ct-x { display: none; }
#chartTrade.adv .cta { display: block; }

/* ==========================================================================
 * The open ticket, made smaller and movable  (2026-09-10)
 *
 * Reported: «too big, and it cannot be moved». Measured first, on the running
 * program: 268x439, standing on a third of the chart at 1280x720, pinned at
 * left:12 top:8 with nothing able to shift it. Broken down block by block,
 * only 198px of the 439 was the order - the rest was a header, a banner
 * saying in words what a colour already said, a permanently dark Close
 * button, a two-line note and the gaps between them.
 *
 * So four decisions, each giving a real thing up:
 *
 *   the lines banner   38px -> a dot in the head, its words kept for a
 *                      screen reader rather than deleted
 *   Close position     32px -> a chip in the head, and only while there IS
 *                      something to close
 *   risk and reward    126px -> 58, side by side; still two fields, two
 *                      labels, two pairs of steppers
 *   the note           two lines -> one, and it keeps its own direction
 *
 * What is NOT given up: every control, every id, and every sentence the panel
 * could say. This is a smaller drawing of the same ticket, not a smaller
 * ticket.
 * ====================================================================== */

/* The head is the handle. `cursor: move` is on the head itself rather than
   the panel, because the panel is full of things that are not handles and a
   move cursor over a stepper is a lie. */
#chartTrade.adv .cta-hd { cursor: move; user-select: none; }
#chartTrade.adv.dragging { transition: none; }
#chartTrade.adv.dragging .cta-hd { cursor: grabbing; }

#chartTrade .cta-grip {
  display: flex; gap: 2.5px; flex: none; margin-right: -1px;
}
#chartTrade .cta-grip i {
  width: 2.5px; height: 2.5px; border-radius: 50%; background: var(--faint);
}
#chartTrade.adv .cta-hd:hover .cta-grip i { background: var(--dim); }

/* The lines, as ONE chip in the head (the owner's pick from ten previews,
   2026-09-14, design/ticket-ten.html number four; the two keys they replace
   were «too many»). Lit in the stop line's own gold while they are on the
   chart, and pressing it does the one thing the state allows - on, or off.
   The dot is the state for anyone who cannot read the colour of a border. */
#chartTrade .cta-lines {
  display: flex; align-items: center; gap: 5px; height: 20px; padding: 0 8px 0 6px;
  border-radius: 999px; font-size: 10.5px; font-weight: 500; color: var(--dim);
  background: var(--field); border: 1px solid var(--line); cursor: pointer;
  white-space: nowrap; flex: none;
}
#chartTrade .cta-lines i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--panel-3);
}
#chartTrade .cta-lines:hover { color: var(--text); border-color: var(--line-strong); }
#chartTrade .cta-lines[aria-pressed="true"] { color: var(--text); border-color: var(--gold); }
#chartTrade .cta-lines[aria-pressed="true"] i {
  background: var(--gold); box-shadow: 0 0 6px var(--gold);
}
/* «Place them again», only when the market has walked a stop's distance from
   where they were laid - the one moment the verb means something. */
#chartTrade .cta-again {
  width: 20px; height: 20px; border-radius: 6px; font-size: 13px; line-height: 1;
  color: var(--gold); background: none; border: 1px solid var(--line); flex: none;
}
#chartTrade .cta-again:hover { background: var(--panel-3); }
#chartTrade .cta-again[hidden] { display: none; }

/* Close, in the head, and only when there is a position. */
#chartTrade .cta-shut {
  height: 24px; padding: 0 8px; font-size: 11px; border-radius: 7px;
  border: 1px solid var(--line); background: none; color: var(--dim);
  width: 100%;
}
#chartTrade .cta-shut:hover { color: var(--text); border-color: var(--line-strong); }
#chartTrade .cta-shut[hidden] { display: none; }

/* Risk and reward, together. */
/* The rest of the trim, and each of these is a real give-up rather than a
   free win: the tabs read one point smaller, the two keys lose ten pixels of
   height, and the body breathes a little less. Scoped to `.adv` so the small
   strip, which is a different control with a different job, keeps its own
   sizes. */
#chartTrade.adv .cta-bd { padding: 7px; gap: 5px; }
/* In the head now. It keeps its own shape - a two-part key, not a tick box -
   but it is sized to a 26px row rather than to a row of its own, and it no
   longer stretches: in the head it takes the width of its two words and the
   spacer after it swallows the rest. */
#chartTrade.adv .cta-seg {
  height: 20px; padding: 2px; border-radius: 6px; flex: none;
}
#chartTrade.adv .cta-seg button {
  font-size: 10.5px; height: 16px; border-radius: 4px; flex: none;
  padding: 0 8px;
}
#chartTrade.adv .cta-key { height: 34px; font-size: 13px; }

/* ==========================================================================
 * Shorter still  (2026-09-10, second pass)
 *
 * Reported: «why is it needlessly this long». Measured before touching it, at
 * 1280x720: 268x230, and the 230 went
 *
 *     39  head            26  a title row for a panel that has SELL and BUY
 *     16  body padding    14  in it does not need a title
 *     28  tabs            22
 *      7  gap              5
 *     58  risk/reward     32  the LABEL had a row of its own above the box
 *      7  gap              5
 *     34  the two keys    34  untouched
 *     41  the note        25  more padding around one line than the line
 *
 * Every one of those is a give-up rather than a free win, and the give-ups
 * are all in how loudly the panel talks, never in what it can do. Every
 * control, every id and every sentence is still here.
 *
 * The two keys are the ONE block that does not move. They are the act, and
 * the act does not get shaved to make room for a panel nobody is looking at
 * in the moment they press it.
 * ====================================================================== */
#chartTrade.adv .cta-hd { height: 26px; padding: 0 7px; gap: 5px; }
#chartTrade.adv .cta-back { height: 20px; width: 20px; padding: 0; font-size: 11px; }
/* Both chips in the head are 20px, which is what the Close chip already was:
   the head is 26px now, and two chips a pixel apart in the same row is the
   sort of thing nobody can name and everybody can see. */
#chartTrade.adv .cta-back { height: 20px; width: 20px; padding: 0; font-size: 11px; justify-content: center; }

/* Four tiles. Two of them are the fields - the risk and the reward keep their
   ids, their inputs and their steppers - and read as figures first: the
   steppers show on hover or focus. The other two report: the volume the risk
   buys, and the stop as the line on the chart has it. Each carries its own
   colour as a 2px foot that glows - the stop in the sell colour, the target
   in the buy colour, the risk in the lines' gold - the Trade Analysis
   vocabulary, reused rather than invented. */
#chartTrade.adv .cta-tiles {
  display: grid; grid-template-columns: 1fr 1fr; gap: 5px;
}
#chartTrade.adv .cta-tile {
  position: relative; display: block; min-width: 0; padding: 4px 7px 5px;
  border-radius: 8px; background: var(--field); border: 1px solid var(--line);
  box-shadow: var(--sheen); text-align: start; overflow: hidden;
}
/* The tiles are READ, so in Persian everything in them starts at the right -
   without turning the box: the working surface keeps its sides, and only
   windows and the review bar are ever given `direction: rtl`. The name and
   the small line are single runs and simply align right; the figure rows are
   flex rows, so «46 پوینت» is reversed (number at the right, word to its
   left, the way Persian reads it) while «2.0 R» and «1 %» stay Latin tokens,
   left to right, pushed to the right end. */
body.fa #chartTrade.adv .cta-tile small { text-align: right; }
body.fa #chartTrade.adv .cta-tile b { flex-direction: row-reverse; justify-content: flex-start; }
body.fa #chartTrade.adv .cta-fig { justify-content: flex-end; }
body.fa #chartTrade.adv .cta-fig input { text-align: right; }
body.fa #chartTrade.adv .cta-steps { right: auto; left: 3px; }
#chartTrade.adv .cta-tile small {
  display: block; font-size: 9px; line-height: 1.3; color: var(--faint);
  letter-spacing: .02em;
}
#chartTrade.adv .cta-tile b, #chartTrade.adv .cta-fig {
  display: flex; align-items: baseline; gap: 3px; height: 20px;
  font: 600 14px/20px var(--code); color: var(--text); white-space: nowrap;
}
#chartTrade.adv .cta-tile b i, #chartTrade.adv .cta-fig i {
  font: 500 9.5px/1 var(--code); color: var(--faint); font-style: normal;
}
#chartTrade.adv .cta-fig input {
  width: 2.8em; min-width: 2ch; field-sizing: content; border: 0; background: none;
  color: var(--text); font: inherit; text-align: left; padding: 0; outline: none;
  height: 20px; direction: ltr;
  -moz-appearance: textfield; border-radius: 3px;
}
#chartTrade.adv .cta-fig input::-webkit-outer-spin-button,
#chartTrade.adv .cta-fig input::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
#chartTrade.adv .cta-tile:focus-within {
  border-color: var(--accent); box-shadow: var(--sheen), 0 0 0 2px var(--ring);
}
#chartTrade.adv .cta-tile em {
  display: block; font: 400 9.5px/1.3 var(--code); font-style: normal;
  color: var(--faint); min-height: 12px;
  /* Two lines, not an ellipsis: «96 pts · 1.17631 · now 2.3R» is wider than
     a 108px tile and so is an index's price at rest (the second pass). */
  white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  /* «= 99.82 USD» is Latin and «مارجین 2,550 USD» is Persian; each lays
     itself out from its own first letter, at the tile's start. */
  unicode-bidi: plaintext; text-align: left;
}
body.fa #chartTrade.adv .cta-tile em { text-align: right; }
#chartTrade.adv .cta-tile em:empty { visibility: hidden; }
#chartTrade.adv .cta-tile::after {
  content: ""; position: absolute; left: 9px; right: 9px; bottom: -1px;
  height: 2px; border-radius: 2px; background: var(--foot, transparent);
  box-shadow: 0 0 8px var(--foot, transparent);
}
#chartTrade.adv .cta-tile.risk { --foot: var(--gold); border-color: color-mix(in srgb, var(--gold) 45%, var(--line)); }
#chartTrade.adv .cta-tile.stop { --foot: var(--down); border-color: color-mix(in srgb, var(--down) 40%, var(--line)); }
#chartTrade.adv .cta-tile.target { --foot: var(--up); border-color: color-mix(in srgb, var(--up) 40%, var(--line)); }
/* A size the account cannot carry: the volume tile goes the colour of a
   refusal, and its small line says the two figures. */
#chartTrade.adv .cta-tile.over { --foot: var(--down); border-color: var(--down); }
#chartTrade.adv .cta-tile.over em { color: var(--down); }
/* The steppers: top-right of the tile, and DRAWN all the time. They used
   to appear only under the hand or with focus, and then the two tiles that
   can be typed into looked exactly like the two that cannot - the owner's
   word for it was «گیج‌کننده» (2026-09-15). The number itself still takes
   typing, the wheel and the arrow keys. */
#chartTrade.adv .cta-steps {
  position: absolute; top: 3px; right: 3px; display: flex; gap: 2px;
}
#chartTrade.adv .cta-step {
  width: 16px; height: 16px; border-radius: 4px; font-size: 12px; line-height: 1;
  background: var(--panel-2); color: var(--dim); border: 1px solid var(--line);
}
#chartTrade.adv .cta-step:hover { background: var(--panel-3); color: var(--text); }

/* The sentence under the keys is DRAWN again: the owner's pick carries it
   («the stop is under the price, so this is a buy»), two lines at most, in
   its own direction. It was taken out of the drawing on 11 September when the
   panel was fighting for height; the tiles gave that height back. */
#chartTrade.adv .cta-say {
  white-space: normal; line-height: 1.5; padding: 0 9px 7px; font-size: 10.5px;
  background: none; border-top: 0; color: var(--faint);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

#chartTrade .cta-hd {
  display: flex; align-items: center; gap: 6px; padding: 8px 10px;
  background: var(--panel-2); box-shadow: var(--sheen);
  border-bottom: 1px solid var(--line-soft);
}
#chartTrade .cta-hd b { font-size: 12.5px; }
#chartTrade .cta-hd .grow { flex: 1; }
/* The way back: a chevron alone since 2026-09-14, when the lines chip took
   the room its word had; the title says where it goes. */
#chartTrade .cta-back {
  display: flex; align-items: center; justify-content: center; height: 22px;
  padding: 0 8px; background: none; color: var(--faint); border-radius: 6px;
  font: 500 11.5px/1 var(--ui); white-space: nowrap;
}
#chartTrade .cta-back:hover { color: var(--text); background: var(--panel-3); }
#chartTrade .cta-bd {
  padding: 11px; display: flex; flex-direction: column; gap: 10px;
}

/* Market or pending, as one two-part key rather than a tick box: a tick says
   a thing is on or off, and these are two states of one question. */
#chartTrade .cta-seg {
  display: flex; gap: 3px; padding: 3px; border-radius: 9px;
  background: var(--field); border: 1px solid var(--line);
}
#chartTrade .cta-seg button {
  flex: 1; height: 28px; border-radius: 7px; background: none;
  color: var(--dim); font-size: 12.5px; white-space: nowrap;
}
#chartTrade .cta-seg button.on {
  background: var(--panel-3); color: var(--text); font-weight: 500;
  box-shadow: var(--elev-1);
}

/* The tiles are drawn under `.adv` above; nothing of the old boxes remains. */

/* The lines, and whether they are on the chart. Lit in the colour the stop
   line is drawn in, so the button and the thing it puts there are one. */
/* The banner these rules dressed is gone: the lines switch is a dot in
   the head now. Removed rather than left behind, because `#chartTrade
   .cta-line.on` weighed exactly the same as the head rule and sat later
   in the file, so it won on order and painted a 38px banner onto a
   20px button. See the block above. */

/* SELL left of BUY, whatever the language does, for the same reason the small
   strip is forced: a trader's hand goes where it always goes. */
#chartTrade .cta-keys { display: flex; gap: 8px; direction: ltr; }
#chartTrade .cta-key {
  flex: 1; height: 46px; border-radius: 10px; box-shadow: var(--sheen);
  font: 600 15px/1 var(--ui); letter-spacing: .03em; white-space: nowrap;
}
#chartTrade .cta-key.buy { background: var(--buy-solid); color: var(--on-buy); }
#chartTrade .cta-key.sell { background: var(--sell-solid); color: var(--on-sell); }
/* The one the lines forbid. Not hidden: somebody has to be able to see that
   the other direction exists and why it is not available. */
#chartTrade .cta-key.off {
  background: none; color: var(--faint); box-shadow: none;
  border: 1px dashed var(--line); cursor: not-allowed;
}
/* The lit key carries the price it would fill at, the way the small strip's
   keys do; the dark one carries only its name. */
#chartTrade .cta-key .px {
  font: 500 10.5px/1 var(--code); letter-spacing: 0; opacity: .9;
  /* both sides: the key is left-to-right and the Persian name is a run
     inside it, so a margin on one side landed outside the word */
  margin: 0 6px;
}
#chartTrade .cta-key.off .px { display: none; }
/* The one thing here that is prose, and the one thing that reads in its own
   direction. `plaintext` takes the paragraph's direction from its first strong
   letter, so a Persian sentence lays itself out right to left and starts at
   the right - inside a box that has not moved and among controls that have not
   moved. The same mechanism the review bar uses, for the same reason. */
#chartTrade .cta-say {
  padding: 9px 11px; font-size: 11.5px; line-height: 1.75; color: var(--dim);
  background: var(--bg); border-top: 1px solid var(--line-soft);
  unicode-bidi: plaintext; text-align: start;
}
#chartTrade .cta-say:empty { display: none; }

/* The account, directly under the tabs rather than floating over the chart or
   sitting at the foot of the window. A balance belongs with the trades it came
   from — and it belongs where the eye lands on its way into the panel, not
   somewhere it has to travel to the bottom of the screen to find. */
#chartAcct {
  display: flex; align-items: center; gap: 18px;
  flex: 0 0 auto; padding: 5px 10px;
  border-bottom: 1px solid var(--line); background: var(--panel);
  font-size: 11px; overflow-x: auto; scrollbar-width: thin;
}
#chartAcct.hidden { display: none; }
#chartAcct span { display: flex; align-items: baseline; gap: 6px; flex: 0 0 auto; }
#chartAcct .grow { flex: 1 1 auto; }
#chartAcct i { color: var(--faint); font-style: normal; }
#chartAcct b { font: 12px var(--mono); color: var(--text); font-variant-numeric: tabular-nums; }
/* The one figure that moves while you watch it, and the only one worth
   picking out of the row. */
#chartAcct .pl b { font-size: 13px; }

/* ---------- the data window ---------- */
#dataWin {
  position: absolute; right: 74px; top: 42px; z-index: 6; min-width: 168px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 6px 20px rgba(0,0,0,.45); overflow: hidden; font-size: 11px;
}
#dataWin.hidden { display: none; }
#dataWin .dw-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 4px 6px 4px 9px; background: var(--panel-2);
  border-bottom: 1px solid var(--line); color: var(--dim);
}
#dataWin .dw-x { border: 0; background: none; color: var(--dim); cursor: pointer; }
#dataWin .dw-x:hover { color: var(--sell); }
#dataWin #dwBody { padding: 6px 9px; display: flex; flex-direction: column; gap: 2px; }
#dataWin .dw-row { display: flex; justify-content: space-between; gap: 14px; }
#dataWin .dw-row span { color: var(--faint); }
#dataWin .dw-row b {
  font: 11px var(--mono); color: var(--text); font-variant-numeric: tabular-nums;
}

/* ---------- the indicator browser ---------- */
.sheet.indbrowse { width: 640px; height: 70vh; }
.sheet.indbrowse > header input { max-width: 240px; }
.indbody { display: flex; min-height: 0; flex: 1; }
/* The shelves are a surface, not a column with a line down one side.
   A border alone puts two panes on one sheet of paper; a step puts the list
   on top of the shelves, which is what they are. */
#indSide {
  width: 176px; flex: 0 0 176px; overflow-y: auto; padding: 8px 6px;
  background: var(--panel-2);
  border-inline-end: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px;
}
#indSide .shelf {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: none; border: 0; border-radius: 7px; padding: 7px 9px;
  color: var(--dim); cursor: pointer; font: inherit; font-size: 12px; text-align: start;
}
#indSide .shelf:hover { background: var(--panel-2); color: var(--text); }
#indSide .shelf.on { background: var(--panel-2); color: var(--text); font-weight: 600; }
#indSide .shelf i {
  font-style: normal; font-size: 10px; color: var(--faint);
  font-variant-numeric: tabular-nums;
}
/* A column, so that an empty state's `margin: auto` can actually centre it.
   It claimed to be centred and sat against the top of a six-hundred-pixel
   pane, because auto margins have nothing to work with in a block. */
.indmain {
  flex: 1; min-width: 0; overflow-y: auto; padding: 8px 10px;
  display: flex; flex-direction: column;
}
/* And the empty state's own room. It is one line of text in the largest region
   this program draws; pinned to the top of it, it reads as a page that failed
   to load rather than as a shelf with nothing on it yet. A column that takes
   the height gives `margin: auto` something to centre against; rows stack
   exactly as they did. */
.indmain > #indList { flex: 1; display: flex; flex-direction: column; }
.indpick {
  display: flex; align-items: center; gap: 8px; padding: 6px 7px;
  border-radius: 7px;
}
.indpick:hover { background: var(--panel-2); }
.indpick .nm { flex: 1; font-size: 12.5px; }
.indpick .star {
  background: none; border: 0; cursor: pointer; color: var(--faint);
  font-size: 13px; line-height: 1; padding: 2px;
}
.indpick .star.on, .indpick .star:hover { color: var(--gold-ink); }
.indpick .own {
  font-size: 10px; color: var(--faint); border: 1px solid var(--line);
  border-radius: 4px; padding: 0 4px;
}
/* Same badge, in the colour this program marks with rather than acts with.
   It says the line rewrites its own past; see `hindsight` in indicators.js. */
.indpick .redraws {
  font-size: 10px; color: var(--gold-ink); border-radius: 4px; padding: 0 4px;
  border: 1px solid color-mix(in srgb, var(--gold) 42%, transparent);
  cursor: help;
}
/* Nothing to draw, and the row says which. Dimmed rather than removed: a
   person looking for On balance volume should find it and be told why it is
   not on offer here, not conclude the program does not have it. */
.indpick.novol .nm { color: var(--dim); }
.indpick.novol .star { opacity: .45; }
.indpick .novolbadge {
  font-size: 10px; color: var(--faint); border-radius: 4px; padding: 0 4px;
  border: 1px solid var(--line);
  cursor: help;
}
.indpick .addc {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px;
  color: var(--text); font: inherit; font-size: 11px; padding: 3px 9px;
  cursor: pointer; opacity: 0; transition: opacity .12s;
}
.indpick:hover .addc, .indpick.live .addc { opacity: 1; }
.indpick .addc:hover { border-color: var(--accent); color: var(--accent); }
.indpick .dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; }
.indpick .rm { background: none; border: 0; color: var(--dim); cursor: pointer; }
.indpick .rm:hover { color: var(--sell); }

/* ---------- one indicator's settings ---------- */
/* One block per thing the indicator draws, each with its own name over it.
   An indicator that draws a single line gets no name — there is nothing to
   tell apart, and a heading over one row is noise. */
/* One row per thing the indicator draws. */
.isline {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: 7px 2px;
}
.isline + .isline { border-top: 1px solid var(--line-soft); }
.isname { flex: 1; font-size: 12.5px; color: var(--text); }

/* The thickness, drawn at the width it sets and in the colour of the line it
   belongs to — so the row shows what it is going to look like. */
.iswid { display: inline-flex; gap: 4px; }
.iswid .wd {
  width: 26px; height: 22px; padding: 0;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  color: inherit; cursor: pointer;
}
.iswid .wd:hover { border-color: var(--line-strong); }
.iswid .wd.on { border-color: var(--accent); background: var(--sel); }
.iswid .wd i { display: block; width: 14px; background: currentColor; border-radius: 2px; }

/* The colour, as a chip that opens the palette. */
.ischip {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 7px;
  padding: 3px 7px 3px 5px; cursor: pointer; font: inherit;
}
.ischip:hover { border-color: var(--line-strong); }
.ischip.on { border-color: var(--accent); }
.ischip em {
  width: 14px; height: 14px; border-radius: 4px; display: block;
  /* Its own edge, or a pale colour vanishes into a pale panel. */
  box-shadow: 0 0 0 1px rgba(120,132,158,.45) inset;
}
.ischip .car { color: var(--faint); font-size: 9px; line-height: 1; }

/* The palette, floating over the panel rather than inside the row: choosing a
   colour for one line must not move the lines under it. */
.ispop {
  position: absolute; top: calc(100% - 2px); inset-inline-end: 0; z-index: 3;
  background: var(--panel); border: 1px solid var(--line-strong);
  border-radius: 9px; box-shadow: var(--elev-2); padding: 8px;
  display: grid; grid-template-columns: repeat(5, 22px); gap: 6px;
}
.ispop.above { top: auto; bottom: calc(100% - 2px); }
/* The palette in an indicator's popover, in the same halo as everywhere
   else. The frame is the button; the colour is what is inside it. */
.ispop { grid-template-columns: repeat(5, 30px) !important; gap: 3px !important; }
.ispop .sw {
  width: 30px; height: 30px; padding: 4px; border: 1px solid transparent;
  border-radius: 11px; background: none; cursor: pointer; box-shadow: none;
}
.ispop .sw i {
  display: block; width: 100%; height: 100%; border-radius: 7px; font-style: normal;
  background: var(--glow); box-shadow: inset 0 0 0 1px rgba(255,255,255,.16),
                                       0 3px 10px -4px var(--glow);
}
.ispop .sw:hover { background: var(--panel-2); }
.ispop .sw.on { background: var(--panel-2); border-color: var(--accent); outline: 0; }
#indSetup { z-index: 56; }
#indSetup .sheet { width: 320px; }
/* ---- Fibonacci, set up ---- */
.sheet.fibset { width: min(420px, 94vw); }
.fibbody { padding: 0 14px 12px; max-height: 66vh; overflow: auto; }
.fibtabs { display: flex; gap: 2px; margin: 0 -4px 6px; flex-wrap: wrap; }
.fibbody > .sub { margin: 0 0 10px; line-height: 1.75; }
.fiblist { display: flex; flex-direction: column; gap: 4px; }
.fibrow {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 7px; background: var(--panel);
}
/* The number is the row. It is what somebody came here to change, so it is
   the widest thing on the line and set in the figures face. */
.fibrow .fibnum {
  flex: 1 1 auto; min-width: 0; direction: ltr; text-align: start;
  background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 6px; padding: 6px 8px; font: inherit;
  font-family: var(--mono); min-height: 32px;
}
/* What the ratio comes to, said as a percentage beside it. A level is thought
   of as 61.8 and typed as 0.618, and having both on the row is what stops the
   second from looking like a typing mistake. */
.fibrow .fibpct {
  flex: 0 0 auto; width: 54px; text-align: end;
  color: var(--faint); font-size: 11.5px; font-family: var(--mono);
  direction: ltr; unicode-bidi: isolate;
}
.fibrow .chip.mini { flex: 0 0 auto; min-height: 28px; }
/* The switches are the product's own `.tg`, untouched. A rule here that set
   its own layout is a second toggle style in a program that already has
   one. */
.fibshow { display: flex; flex-direction: column; gap: 4px; }
#fibSetup .addrow { margin-top: 8px; }
#fibSetup .secline { margin: 16px 0 8px; }

.istabs { display: flex; gap: 2px; padding: 8px 10px 0; }
.istab {
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--dim); cursor: pointer; font: inherit; font-size: 12px;
  padding: 5px 10px;
}
.istab.on { color: var(--text); border-bottom-color: var(--accent); }
.isrow {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 12px; color: var(--dim);
}
.isrow input { width: 92px; }
.isfoot { display: flex; align-items: center; gap: 8px; }
.isfoot .primary { margin-inline-start: auto; }
.isfoot .danger:hover { color: var(--sell); border-color: var(--sell); }


/* ---------- number fields ---------- */
/* The two grey nubs a browser stacks inside every number field belong to the
   operating system, not to this. They are the same shape in every program on
   the machine, they do not follow the theme, and next to everything else here
   they look like a control panel from another decade. Off, in both engines. */
input[type=number] { appearance: textfield; -moz-appearance: textfield; }
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* What replaces them: two chevrons in the leading colour of everything else,
   inside the field rather than glued to its edge, and only while the field is
   under the pointer or holds the caret - a row of settings should read as
   numbers, not as a stack of arrows. */
/* Left to right on the wrapper, not only on the field: `inset-inline-end`
   resolves against whatever direction it inherits, so inside a Persian window
   the arrows landed on the left, on top of the number. A number reads one way
   in both languages and so does the box around it. */
.numfield { position: relative; display: block; direction: ltr; }
.numfield > input[type=number] { width: 100%; padding-inline-end: 24px; }
.numspin {
  position: absolute; inset-inline-end: 4px; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 1px;
  opacity: 0; transition: opacity .12s ease; pointer-events: none;
}
.numfield:hover .numspin,
.numfield:focus-within .numspin { opacity: 1; pointer-events: auto; }
.numspin button {
  display: flex; align-items: center; justify-content: center;
  width: 17px; height: 11px; padding: 0;
  border: 0; border-radius: 3px; background: none;
  color: var(--faint); cursor: pointer;
  transition: color .1s ease, background .1s ease;
}
.numspin button:hover { color: var(--text); background: var(--hover); }
.numspin button:active { color: var(--accent); }
.numspin svg { width: 9px; height: 6px; display: block; }
/* A field holding a number it cannot take says so on its own edge as well as
   in the box below it, so the two are obviously about the same field. */
input[type=number].numbad { border-color: var(--down); }

/* The sentence itself, in the same small box a tooltip uses - same ground,
   same corner, same size - so being told a number is wrong feels like part of
   this program and not like a browser interrupting it. The border is the
   losing colour because that is what this box always means. */
#numhint {
  position: fixed; z-index: 210; pointer-events: none;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--down); border-radius: 7px;
  padding: 6px 10px; font-size: 12px; line-height: 1.45;
  max-width: 380px; width: max-content;
  box-shadow: var(--elev-2);
  text-align: start;
}
#numhint.hidden { display: none; }

/* ---------------------------------------------------------------- challenge
   A challenge is read, not operated: what it was, who won, and by how much.
   So these are mostly tables, and the table is the design. */

/* These sheets are a plain `.pad`, and the sheet field look only ever
   existed under `.pad.grid2`. Rather than force the grid on a form that is
   not two columns, the same look is asked for by name. */
#challenge label, #challenge label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 11px; color: var(--dim);
}
/* Wide enough for the conditions to sit two-up. At 360 they stacked, which
   is what made this the tallest small window in the application. */
#challenge .sheet { width: 460px; }
#challenge label.wide, #challenge label.wide { width: 100%; }
/* Was two rules, both this one, and both describing a field this file now
   describes once. */
/* The two columns the `grid2` class was asking for and never got: the rule
   that draws them is `.pad.grid2`, which wants both classes on one element,
   and this element has only the one. Four small numbers filled four rows and
   made the window twice as tall as it needed to be. */
#chalRules {
  width: 100%;
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px;
}
@media (max-width: 420px) { #chalRules { grid-template-columns: 1fr; } }
/* A section head is a line of its own, whatever it is inside. It only ever
   worked because every sheet that had one was a grid. */
#challenge .secline, #chalResult .secline { width: 100%; margin-top: 6px; }
#challenge .secline .sub { margin-inline-start: 8px; }

/* `body.fa label` sets `text-align: left`, which is physical: a Persian label
   then sits against the left edge of a sheet that reads from the right. The
   settings sheet already puts this back; these need the same. */
body.fa #challenge label, body.fa #challenge label,
body.fa #challenge .secline, body.fa #chalResult .secline,
body.fa .chalwhat, body.fa .chalrow { text-align: start; }

/* The code the join field takes is Latin and is typed left to right, even in
   a sheet that reads the other way. */
#chalJoinCode { text-transform: uppercase; letter-spacing: 3px;
                direction: ltr; text-align: center; font-size: 18px; }

/* What you are about to send, before you send it.
   Pairs on a grid rather than a wrapping row: as a row the five facts ran
   into one another and nothing said which word was the question. */
.chalwhat {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 9px 16px;
  background: var(--top), var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 12px; padding: 12px 14px; margin-bottom: 14px;
  box-shadow: var(--sheen);
}
.chalwhat > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.chalwhat b {
  font-variant-numeric: tabular-nums; font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chalwhat span {
  color: var(--faint); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase;
}

/* The code itself. Big, because it is the thing being read aloud into a
   group chat, and monospaced so O and 0 cannot be confused. */
.chalcode {
  display: flex; align-items: center; gap: 10px; margin-top: 12px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 12px;
}
/* Typed as it is read out: big, spaced, and monospaced so O and 0 cannot be
   confused - the same treatment the code gets when it is handed back. */
#chalJoinCode {
  font: 700 20px/1.4 var(--mono) !important; letter-spacing: 4px;
  text-align: center;
}
.chalcode b {
  font: 700 22px/1 var(--mono); letter-spacing: 3px; color: var(--accent);
  /* A Latin code inside a Persian sentence is still read left to right. */
  direction: ltr; unicode-bidi: isolate;
}

/* The reveal: what the chart actually was. */
.chalreveal {
  font-size: 15px; font-weight: 600; margin-bottom: 4px;
}
.chalreveal .sym { color: var(--accent); }
.chalverdict { color: var(--dim); margin-bottom: 14px; }
.chalverdict.won { color: var(--up-ink); font-weight: 600; }
/* Not red. Somebody else winning is a fact, not an error, and painting it
   the colour of a losing trade reads as a scolding. */
.chalverdict.lost { color: var(--text); font-weight: 600; }
.chalverdict.over { color: var(--sell); }

/* Two columns of numbers, one row per thing worth comparing. The winner of a
   row is marked rather than merely being the larger number, because "larger"
   is the wrong answer for a drawdown. */
.chaltable { display: grid; grid-template-columns: 1fr auto auto; gap: 0; }
.chaltable > div {
  padding: 7px 10px; border-bottom: 1px solid var(--line-soft);
  font-variant-numeric: tabular-nums;
}
.chaltable > div:nth-child(3n + 1) { color: var(--dim); }
.chaltable > div:nth-child(3n + 2),
.chaltable > div:nth-child(3n) { min-width: 96px; }
.chaltable .head { color: var(--text); font-weight: 600; border-bottom-color: var(--line); }
/* A minus sign is a neutral character, so in a right-to-left cell it drifts
   to the far end of the number it belongs to and a loss reads `1.40-`. The
   number is its own little left-to-right island. */
.chaltable > div:nth-child(3n + 2),
.chaltable > div:nth-child(3n),
.chalboard .num { direction: ltr; text-align: start; }
/* Which side won a row, marked by weight rather than by colour. Green and
   red already mean made-money and lost-money everywhere else in this
   application, and a green minus sign - "he lost less than you" - is the
   sort of thing a person reads twice and still gets wrong. */
.chaltable .win { color: var(--text); font-weight: 700; }
.chaltable .lose { color: var(--dim); }

/* The board. */
.chalboard { display: grid; grid-template-columns: auto 1fr auto auto auto; }
.chalboard > div {
  padding: 7px 10px; border-bottom: 1px solid var(--line-soft);
  font-variant-numeric: tabular-nums;
}
.chalboard .head { color: var(--dim); font-weight: 600; }
.chalboard .me { background: var(--sel); }
.chalboard .place { color: var(--faint); min-width: 28px; }
.chalboard .place.first { color: var(--accent); font-weight: 700; }

.chalboard .up { color: var(--up-ink); }
.chalboard .down { color: var(--down-ink); }

/* The shelf. */
.chalshelf { display: flex; flex-direction: column; gap: 8px; }
.chalrow {
  display: flex; align-items: center; gap: 12px;
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 8px; padding: 10px 12px;
}
/* The title somebody typed when they made the challenge, so it reads in its
   own direction like every other piece of typed text in the program. It is not
   cut short the way a saved run's name is, so nothing is lost here without it
   — what it fixes is an English title starting at the far end of the line from
   where it is read. Same rule as `.sesstext > .sessname`. */
.chalrow .nm { font-weight: 600; unicode-bidi: plaintext; text-align: start; }
.chalrow .sub2 { color: var(--dim); font-size: 12px; }
.chalrow .grow { flex: 1 1 auto; min-width: 0; }
.chalrow .cd {
  font: 600 13px/1 var(--mono); letter-spacing: 2px; color: var(--accent);
  direction: ltr; unicode-bidi: isolate;
}


#chalResult .pad, #challenge .pad, #challenge .pad { overflow-y: auto; }
#chalResult .addrow, #challenge .addrow, #challenge .addrow { flex-wrap: wrap; }


/* ================================================================ the windows
 *
 * The tile language, carried into every dialog. All of it is by class, so no
 * window's markup had to change and none of them can be missed.
 */
.sheet {
  border-radius: var(--tile, 18px);
  box-shadow: 0 1px 2px rgba(0,0,0,.2), 0 26px 64px -24px rgba(0,0,0,.7);
}
:root.light .sheet {
  box-shadow: 0 1px 2px rgba(30,40,60,.06), 0 26px 64px -26px rgba(30,40,60,.35);
}

/* A window says what it is, at the size a title is said. It used to be set at
   the same weight as the labels inside it. */
.sheet > header {
  padding: 15px 18px 13px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--wash), linear-gradient(180deg, var(--panel-2), transparent);
}
.sheet > header { gap: 12px; align-items: flex-start; }
.sheet > header b { font-size: 15px; font-weight: 600; letter-spacing: -.2px;
                    display: block; }
/* The mark, in the accent's own tint rather than in the accent: it names the
   window, it is not something to press. */
.sheet > header .wicon {
  width: 38px; height: 38px; border-radius: 12px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent);
  background:
    linear-gradient(150deg,
      color-mix(in srgb, var(--accent) 26%, transparent),
      color-mix(in srgb, var(--accent) 10%, transparent));
  box-shadow: var(--sheen), var(--glow-soft);
}
.sheet > header .wtitle { min-width: 0; flex: 1 1 auto; }
.sheet > header .wtitle span {
  display: block; color: var(--dim); font-size: 11.5px; font-weight: 400;
  margin-top: 1px;
}
body.fa .sheet > header .wtitle { text-align: start; }
.sheet > header .x {
  width: 30px; height: 30px; border-radius: 9px; color: var(--faint);
  display: inline-flex; align-items: center; justify-content: center;
}
.sheet > header .x:hover { background: var(--hover); color: var(--text); }

/* A section, rather than a sentence in bold. The rule runs out of the label
   to the end of the row, which is what makes a long window read as parts. */
.secline {
  display: flex; align-items: center; gap: 10px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .4px;
  color: var(--faint); margin-top: 6px;
}
.secline::after {
  content: ''; flex: 1 1 auto; height: 1px; background: var(--line-soft);
}
.secline .sub { font-weight: 400; letter-spacing: 0; color: var(--faint); }

/* The hollow-body switch, under the three swatches it belongs with.
 *
 * Inside one candle group the gaps ran 8 then 0: the heading has a margin of
 * its own and the switch had none, so it sat welded to the row of colours
 * while everything above it breathed. The same shape of fault as the invite
 * box, found by measuring every window rather than by reading any of them -
 * see `design/gap-audit.mjs`.
 *
 * Eight, to match the gap above it. The switch stays part of the group; it
 * simply stops touching. */
.candleside .colgrid + .tg { margin-top: 8px; }

/* Room to type - which every field now has, from the one rule above, so the
   three lists of inputs that used to be repeated here have gone with it. The
   button is not a field and keeps its own padding; it takes the corner so it
   still belongs to the row it sits in. */
.pickrow .open { border-radius: var(--field-r); padding: 8px 11px; }
.pad.grid2 label { font-size: 10.5px; letter-spacing: .3px; }

/* The thing that does the thing. Heavier than what surrounds it, because it
   is - and with the corner everything else on the screen now has. */
.primary {
  border-radius: 12px; padding: 9px 18px; font-weight: 600;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
  color: var(--ink);
  box-shadow: var(--sheen), var(--glow);
  transition: box-shadow .16s ease, transform .06s ease;
}
.primary:hover {
  box-shadow: var(--sheen),
    0 8px 22px -8px color-mix(in srgb, var(--accent) 90%, transparent);
}
.primary:active { transform: translateY(1px); }
.chip, .act, .btn, .mini { border-radius: 10px; }
.seg { border-radius: 11px; }
.seg button { border-radius: 8px; }

/* Anything that groups rows inside a window gets the tile's corner too, so a
   dialog is not a set of eighteen-pixel edges around a set of four. */
.jcard, .grp, .choice, .statgrid, .tagtable, .sessrow, .customrow,
.mirrorrow, .indrow { border-radius: 12px; }

/* One chip stretched across the whole row reads as a bar, not as a choice.
   The switch is as wide as what it holds. */
/* Left from the segmented control that used to be here: an id selector, so it
   beat everything the tiles are styled with and pinned the row at 150px with
   four 31px columns inside it. */
#rowCcy > span:first-child { color: var(--dim); font-size: 11px; }

/* ---------- The screenshot gallery ----------
 *
 * Nearly the whole screen, because a chart shrunk to fit a dialog is the thing
 * this window exists to stop being. The picture is the only thing sized in
 * pixels; everything around it is a line of text and a strip of thumbnails.
 */
#shotShow { z-index: 72; }
.sheet.shotsheet {
  width: 96vw; max-width: 96vw; height: 92vh; max-height: 92vh;
}
.shotsheet > header { gap: 8px; }
.shotsheet > header .sub { font-size: 12px; }
/* Entry or exit, in the colours the rest of the program already uses for
   getting in and getting out, so the word is read once and recognised after. */
.shotwhich {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--faint);
}
.shotwhich.entry { color: var(--up-ink); border-color: color-mix(in srgb, var(--up) 45%, transparent); }
.shotwhich.exit { color: var(--down-ink); border-color: color-mix(in srgb, var(--down) 45%, transparent); }
.shotcount { font-size: 12px; color: var(--faint); }

/* The picture, and the two ways past it. `min-height: 0` because a flex child
   defaults to never shrinking below its content, and an image is content: the
   stage grew to the picture's natural height and pushed the strip off the
   bottom of the window. */
.shotstage {
  position: relative; flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); overflow: hidden;
}
#shotBig {
  max-width: 100%; max-height: 100%;
  object-fit: contain; display: block;
}
.shotnav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 68px; border-radius: 10px;
  background: color-mix(in srgb, var(--panel) 78%, transparent);
  border: 1px solid var(--line-soft); color: var(--text);
  font-size: 17px; line-height: 1; cursor: pointer;
  opacity: .5; transition: opacity .12s ease, border-color .12s ease;
}
.shotnav:hover { opacity: 1; border-color: var(--line); }
/* Logical, not physical: in Persian the window is turned round and "previous"
   has to stay on the side the reading comes from. */
/* The side is logical; the glyph is a triangle for a reason, and the reason is
   worth keeping. The angle characters tried first - the two that look like
   chevrons - carry Unicode's Bidi_Mirrored property, so a right-to-left box
   draws their mirror image and a right-pointing arrow came out pointing left.
   Mirroring it back with a transform looked like it did nothing, because that
   and the bidi mirroring cancelled; pinning the button to `ltr` fixed the
   glyph and moved the button to the wrong side, because `inset-inline-start`
   then resolved against the button's own direction. The triangles are not
   mirrored by anything, so what is written is what is drawn. */
.shotnav.prev { inset-inline-start: 12px; }
.shotnav.next { inset-inline-end: 12px; }

.shotempty {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; text-align: center; padding: 24px;
}
.shotempty .shoticon { font-size: 30px; opacity: .5; }
.shotempty .sub { max-width: 46ch; }

/* The pile, so a picture is reachable without stepping through the ones
   before it. Scrolls sideways on its own; the window never does. */
.shotstrip {
  flex: 0 0 auto; display: flex; gap: 6px;
  padding: 8px 10px; overflow-x: auto; overflow-y: hidden;
  border-top: 1px solid var(--line-soft); background: var(--panel);
  /* `safe`, and it matters: a plain `center` on an overflowing row pushes the
     first items past the scroll origin, where nothing can scroll back to them.
     With few pictures the strip is centred; with many it fills and scrolls. */
  justify-content: safe center;
}
.shotstrip button {
  flex: 0 0 auto; width: 92px; height: 56px; padding: 0;
  border: 1px solid var(--line-soft); border-radius: 6px; overflow: hidden;
  background: var(--bg); cursor: pointer; opacity: .55;
  transition: opacity .12s ease, border-color .12s ease;
}
.shotstrip button img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shotstrip button:hover { opacity: .85; }
.shotstrip button.on { opacity: 1; border-color: var(--accent); }

/* ==========================================================================
   The crypto order ticket
   ==========================================================================
   Built by web/ticket.js from what the market is, rather than by hiding rows
   that do not belong to it. Every class here is prefixed `tk` because two of
   the names this wants - `wrow` and `act` - are already taken elsewhere in
   this file, and a silent collision in a stylesheet is a bug that only shows
   up as something looking slightly wrong. */

#ticketForm { display: flex; flex-direction: column; gap: 9px; }

/* --- the price strip ---------------------------------------------------- */
.tkstrip {
  display: flex; gap: 10px; padding: 6px 10px;
  background: var(--sunken, rgba(0,0,0,.18));
  border-block: 1px solid var(--line);
  /* No negative margins to bleed to the panel edge. They overflowed it, the
     panel grew a horizontal scrollbar, and the scrollbar sat directly under
     the size field where it read as the percent rail. */
}
.tktile { flex: 1; min-width: 0; }
.tktile em { display: block; font-style: normal; color: var(--faint); font-size: 10.5px; }
.tktile b {
  display: block; font: 700 13px/1.25 var(--mono);
  direction: ltr; unicode-bidi: isolate;
}
.tktile b.up { color: var(--up); }
.tktile b.down { color: var(--down); }
.tktile .tkclk {
  display: block; color: var(--dim); font-size: 11px;
  direction: ltr; unicode-bidi: isolate;
}

/* --- margin mode and leverage ------------------------------------------
   Two controls and not three choices out of one set: one is a pair, the
   other is a number. Drawn as one segmented control, the leverage read as a
   third margin mode. */
.tkmargin { display: flex; gap: 8px; align-items: stretch; }
.tkmargin .seg { flex: 1; }
.tklev {
  display: flex; align-items: center; gap: 5px; padding: 0 10px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  color: var(--text); font: 500 11.5px/1 var(--ui); white-space: nowrap;
  cursor: pointer;
}
.tklev b { font: 700 13px/1 var(--mono); direction: ltr; }
.tklev:hover { background: var(--hover); }

/* --- the side --------------------------------------------------------- */
/* The side, tinted rather than written, so both take the FILL tokens. `--buy`
   is the colour a buy is written in - a price, a label, a border - and it is
   held to that on purpose: it was doing both jobs once, and thirty-seven
   rules that meant "highlighted" said "buy". */
.seg.tkside button.on.long {
  background: color-mix(in srgb, var(--buy-solid) 26%, var(--hover));
  color: var(--text);
}
.seg.tkside button.on.short {
  background: color-mix(in srgb, var(--sell-solid) 26%, var(--hover));
  color: var(--text);
}

/* --- a field ----------------------------------------------------------- */
.tkf { display: flex; flex-direction: column; gap: 4px; }
.tklab {
  display: flex; align-items: baseline; gap: 6px;
  color: var(--dim); font-size: 11.5px; margin: 0 2px;
}
.tklab .tkavail {
  margin-inline-start: auto; font-style: normal;
  color: var(--faint); font-size: 11px;
  direction: ltr; unicode-bidi: isolate;
}
.tkbox {
  display: flex; align-items: stretch; background: var(--sunken, rgba(0,0,0,.22));
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
}
.tkbox:focus-within { border-color: var(--ring, var(--accent)); }
.tkbox input {
  flex: 1; min-width: 0; border: 0; background: none; color: var(--text);
  font: 500 14px/1 var(--mono); padding: 9px 10px; outline: none;
  direction: ltr; text-align: right;
}
.tkbox input::-webkit-outer-spin-button,
.tkbox input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.tkunit {
  display: flex; align-items: center; gap: 3px; padding: 0 9px;
  color: var(--dim); font-size: 11.5px;
  border-inline-start: 1px solid var(--line);
  background: color-mix(in srgb, var(--hover) 60%, transparent);
}
button.tkunit { cursor: pointer; }
button.tkunit:hover { color: var(--text); }
.tkunit i { font-style: normal; font-size: 9px; color: var(--faint); }
.tkghost {
  display: flex; align-items: center; padding: 0 10px; cursor: pointer;
  color: var(--accent); font-size: 11.5px; background: none; border: 0;
  border-inline-start: 1px solid var(--line);
}
.tkghost:hover { background: var(--hover); }
.tkecho {
  display: block; margin: 1px 2px 0; color: var(--faint); font-size: 11px;
  min-height: 14px;
}
.tkecho b {
  color: var(--dim); font-weight: 500;
  direction: ltr; unicode-bidi: isolate;
}

/* --- the percent rail --------------------------------------------------- */
.tkrail { margin: 1px 2px 0; }
.tkrail input[type=range] { width: 100%; margin: 0; }
/* Left to right, like the rail above them.
 *
 * Measured: the range input computes as `ltr` whatever the panel around it
 * does, so its zero is on the left. The labels were laid out by the Persian
 * panel and put their zero on the right, and the two ends of the same control
 * disagreed about which end was none. */
.tkticks {
  display: flex; justify-content: space-between; margin-top: 3px;
  direction: ltr;
}
.tkticks b {
  color: var(--faint); font: 400 10.5px/1 var(--mono);
  direction: ltr; unicode-bidi: isolate;
}

/* --- a switch that opens something --------------------------------------- */
.tkchk {
  display: flex; align-items: center; gap: 7px; width: 100%;
  background: none; border: 0; padding: 2px; cursor: pointer;
  color: var(--dim); font: 400 12px/1.4 var(--ui); text-align: start;
}
.tkchk i {
  width: 13px; height: 13px; border-radius: 4px; border: 1px solid var(--line);
  display: inline-block; flex: 0 0 13px;
}
.tkchk[aria-pressed=true] { color: var(--text); }
.tkchk[aria-pressed=true] i {
  background: var(--accent); border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--panel);
}

.tkdrawer {
  padding: 9px; background: var(--sunken, rgba(0,0,0,.18));
  border: 1px solid var(--line); border-radius: 9px;
  display: flex; flex-direction: column; gap: 7px;
}
.tkunits { display: flex; gap: 3px; }
.tkunits button {
  font: 500 10.5px/1 var(--ui); color: var(--dim); background: var(--hover);
  border: 0; border-radius: 5px; padding: 5px 8px; cursor: pointer;
}
.tkunits button.on {
  background: color-mix(in srgb, var(--accent) 34%, var(--hover));
  color: var(--text);
}
.tkslrow { display: flex; align-items: center; gap: 7px; }
.tkslrow .tktag { width: 46px; flex: 0 0 46px; color: var(--dim); font-size: 11.5px; }
.tkslrow .tkbox { flex: 1; min-width: 0; }
.tkslrow .tkbox input { padding: 7px 9px; font-size: 13px; }
.tkslrow .tkout {
  width: 90px; flex: 0 0 90px; font-size: 11px; color: var(--faint);
  direction: ltr; unicode-bidi: isolate; text-align: left;
}
.tkslrow .tkout b { display: block; font-weight: 500; font-size: 12px; }
.tkslrow .tkout b.up { color: var(--up); }
.tkslrow .tkout b.down { color: var(--down); }

/* --- what the order makes ------------------------------------------------ */
.tkwhat {
  margin: 2px 0 0; padding: 9px 10px 4px;
  background: var(--sunken, rgba(0,0,0,.18));
  border: 1px solid var(--line); border-radius: 9px;
}
/* A button, because it folds. The two figures that decide whether to press
   the order stay on the line beside its name; everything else is behind it. */
.tkwhead {
  display: flex; align-items: center; gap: 7px; width: 100%;
  background: none; border: 0; padding: 0 0 5px; cursor: pointer;
  color: var(--dim); text-align: start;
}
.tkwhead b { font: 700 11.5px/1 var(--ui); color: var(--dim); white-space: nowrap; }
.tkwhead .tksum {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; text-align: end;
  color: var(--faint); font: 400 11px/1 var(--ui);
}
.tkwhead i {
  font-style: normal; font-size: 9px; color: var(--faint);
  transition: transform .12s ease;
}
.tkwhead[aria-expanded=false] i { transform: rotate(-90deg); }
.tkwhead[aria-expanded=false] + #cxWhat { display: none; }
.tkwrow {
  display: flex; align-items: baseline; gap: 8px; padding: 2.5px 0;
  font-size: 12px;
}
.tkwrow .k { color: var(--faint); }
.tkwrow .k em { font-style: normal; color: var(--line); }
.tkwrow .v {
  margin-inline-start: auto; font-weight: 500;
  direction: ltr; unicode-bidi: isolate;
}
.tkwrow .v small { color: var(--faint); font-weight: 400; font-size: 10.5px; }
.tkwrow.big .v { font: 700 14px/1.3 var(--mono); }
.tkwrow.liq .v { color: var(--down); }
.tkwrow .chip {
  font-size: 10.5px; border-radius: 5px; padding: 1.5px 6px;
  background: var(--hover); color: var(--dim);
}

/* --- the one button ------------------------------------------------------ */
.tkact { padding-top: 2px; }
.tkact button {
  width: 100%; border: 0; border-radius: 9px; padding: 13px 10px;
  font: 700 14px/1 var(--ui); color: var(--ink); cursor: pointer;
  box-shadow: var(--sheen);
}
.tkact button.long { background: var(--buy-solid); color: var(--on-buy); }
.tkact button.short { background: var(--sell-solid); color: var(--on-sell); }
.tkact button:disabled { opacity: .45; cursor: default; }
.tknote {
  text-align: center; color: var(--faint); font-size: 10.5px; margin-top: 6px;
  min-height: 13px;
}

/* Where the trading account stands, above the settings that shape it. The
   same two figures the account drawer used to carry, in the window they are
   actually about. */
/* The card that says where the account stands is a flex ITEM in `.pad`, which
 * is itself a flex row - so without this it takes the default `flex: 0 1 auto`
 * and shrinks to its own contents, sitting against one edge of the sheet.
 * `.pad p { width: 100% }` exists a few lines up for exactly this reason.
 * This was three tiles that came out 85px wide in a 530px window; it is one
 * card now, and the same rule is what makes it span. */
.acctcard { width: 100%; }

/* ==========================================================================
   The account drawer
   ==========================================================================
   One block that says the state, why it matters and what to press about it;
   then three named groups of rows; then the way out.

   What it replaced: a ring saying the subscription had ended, a line under it
   saying it was in use on another computer, and the button that fixes either
   of them four sections below - ten unrelated sections in one scroll, with
   nothing grouped and the practice balance sitting beside real money. */

.lichead {
  position: relative; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 17px; box-shadow: var(--sheen);
  margin-bottom: 4px;
}
/* Light in the state's own colour, and a foot that glows in it. Warm while
   something wants doing, the accent while nothing does. */
.lichead::before {
  content: ""; position: absolute; width: 170px; height: 170px; border-radius: 50%;
  inset-inline-start: -55px; top: -75px; pointer-events: none;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 26%, transparent), transparent 66%);
}
.lichead::after {
  content: ""; position: absolute; inset-inline: 14px; bottom: -1px; height: 2px;
  border-radius: 2px; background: var(--accent);
  box-shadow: 0 0 14px 2px color-mix(in srgb, var(--accent) 45%, transparent);
}
.lichead.warn::before {
  background: radial-gradient(circle, color-mix(in srgb, var(--down) 24%, transparent), transparent 66%);
}
.lichead.warn::after {
  background: var(--down);
  box-shadow: 0 0 14px 2px color-mix(in srgb, var(--down) 45%, transparent);
}
.lichead .licsay {
  display: block; font-size: 19px; font-weight: 700; line-height: 1.5;
  margin-top: 6px;
}
.lichead.warn .licsay { color: var(--down); }
.lichead #licWhy { margin-top: 5px; font-size: 12.5px; }
.lichead .primary { margin-top: 12px; width: 100%; }

/* The name over each group. Not a rule with a word on it - a quiet label, so
   the eye can skip a whole group without reading its rows. */
.grouphead {
  color: var(--faint); font-size: 11px; margin: 16px 0 8px 2px;
}

/* One row, whether it opens or not. `details` where something unfolds, a
   plain div where the value IS the answer. */
.setrow {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 11px; box-shadow: var(--sheen); margin: 0 0 7px;
  padding: 0;
}
.setrow > summary,
.setrow.flat {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 13px; font: 500 13px/1.5 var(--ui); cursor: pointer;
  list-style: none;
}
.setrow.flat { cursor: default; }
.setrow > summary::-webkit-details-marker { display: none; }
/* `details.quiet` puts a plus before its summary. A row with a chevron on its
   far end does not want a second marker at its start as well. */
/* `details.quiet > summary::before` is one element more specific than
   `.setrow > summary::before`, so the plainer selector lost and the plus stayed
   on every row. Matched, not out-shouted with !important. */
details.quiet.setrow > summary::before { content: none; }
.setrow > summary::after {
  content: "\203A"; color: var(--faint); font-size: 15px; line-height: 1;
  margin-inline-start: auto;
}
/* One auto margin to a row, not two.
   The value already has one, and a flex line with two of them SPLITS the
   spare room between them - so "4 not paid yet" sat marooned in the middle of
   its own row with a gap on either side, while every other row's value sat
   tidily at the end. Where there is a value, the value does the pushing and
   the chevron follows it. */
.setrow > summary:has(.rowsay)::after { margin-inline-start: 0; }
.setrow[open] > summary::after { transform: rotate(90deg); }
.setrow .rowname { font-weight: 500; }
/* Pushed to the far end, so every row's value lines up whatever its name. */
.setrow .rowsay {
  margin-inline-start: auto; color: var(--dim); font-size: 12.5px; font-weight: 400;
}
.setrow > summary .rowsay { margin-inline-end: 2px; }
/* `margin-inline-start` resolves against the ELEMENT's own direction, not its
   row's. In Persian `.mono` turns numbers round to ltr, so on the version row
   the auto margin landed on the value's left and pushed it back against its
   own name, while every other row's value sat out at the far end beside its
   button. Same margin, stated from the side the turned-round box calls the
   end. */
body.fa .setrow .rowsay.mono { margin-inline-start: 0; margin-inline-end: auto; }
.setrow .rowsay.warn { color: var(--down); }
.setrow .chip.mini { margin-inline-start: 0; }

/* The one word beside the version number. It sits between the number and the
   button, so it takes no auto margin of its own: `.rowsay` has already pushed
   the pair to the far end and a second one here would split the free space
   between them - which is the trap this row has fallen into before. */
/* No margin of its own. The row is a flex line with a 9px gap and that gap is
   what spaces every other pair on it; 8px added here made this one row's
   spacing 17px where every other was 9, which `test_boots.mjs` measures and
   refused. The layout does the spacing. */
.versay { font-size: 12px; white-space: nowrap; }
/* The version row: the name never wraps and the button never leaves the
   row; a sentence too long for what is left folds within its own span (the
   channel's adversary pass, 2026-09-13, measured «{v} is out, early»
   folding the NAME and pushing the button past the row's edge). */
.setrow.flat:has(#verState) .rowname { white-space: nowrap; }
.setrow.flat:has(#verState) .versay { min-width: 0; white-space: normal; }
.versay.quiet { color: var(--faint); }
.versay.good { color: var(--up); }
.versay.warn { color: var(--down); cursor: help; }
.setrow.flat .langpick { margin-inline-start: auto; display: flex; gap: 6px; }
/* Only what UNFOLDS under a summary. A flat row has no summary, so every one
   of its parts counted as unfolded content and took a 13px bottom padding:
   `align-items: center` then centred boxes that were 13px too tall, which put
   the words 6.5px above the middle. The row measured level and looked crooked.

   `:not(button)` for the same fault one layer down, and the note that used to
   be here had the reason wrong: it said the button out-specifies this with its
   own padding. It does not. This is two classes and an element, `.primary` is
   one class, and this wins - so «Make a recovery key» was laid out with NO
   padding above it and thirteen pixels below, and the words sat 6.5px high in
   their own button. Reported with a photograph on 7 September and measured at
   6x by `design/button-ink-centre.mjs`: 3.17px of space above the word and
   16.17px below it.

   A row like this is arranging what is inside it. A control's padding is its
   shape, not the row's business - and `#waysDo` carries its own 13px of inset
   as a margin, so nothing here is lost by leaving it alone. */
.setrow:not(.flat) > *:not(summary):not(button) { padding: 0 13px 13px; }
.setrow > summary:hover { background: var(--hover); border-radius: 10px; }

/* The way out, drawn as one.
   It was a `chip mini` at the top beside the name, the same weight as
   "Attach" - the one control here that reads as irreversible, given the size
   of a footnote. Outlined and not filled, because it is not what anybody
   opened this drawer to press. */
/* Support: a row at the foot of the account sheet, and the window it opens.
   Telegram's own blue for the one thing to press, the way the picture
   window's «Send to Telegram» wears it; the halo is the Trade Analysis
   vocabulary, in that colour. */
.suprow .suphint { margin-inline-start: -2px; flex: 1; }
.sheet.support { width: 400px; position: relative; overflow: hidden; }
.sheet.support::after {
  content: ''; position: absolute; inset: auto -40px -70px auto; width: 240px; height: 150px;
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(42,171,238,.22), rgba(42,171,238,0));
}
.suplead { margin: 0 0 12px; color: var(--dim); font-size: 13px; }
.suphandle {
  font: 600 14px ui-monospace, Consolas, monospace; color: #2aabee; direction: ltr;
  unicode-bidi: isolate; letter-spacing: .2px; cursor: pointer; background: none; border: 0; padding: 0;
}
.suphandle:hover { text-decoration: underline; }
.supdoors { display: flex; gap: 14px; align-items: center; }
/* The square is white in both themes, so the ink is set here and not
   inherited: in the dark theme the inherited text colour is near-white, and
   the first pass on 1.1.109 measured the QR at a contrast of 1.04 to 1. */
.supqr { width: 136px; height: 136px; flex: none; background: #fff; color: #000; border-radius: 10px; padding: 8px; }
.supqr svg { width: 100%; height: 100%; display: block; }
.supqr.empty {
  background: var(--panel-2); border: 1px dashed var(--line); color: var(--faint);
  font-size: 11.5px; display: grid; place-items: center; text-align: center; padding: 10px;
}
.supsay { flex: 1; min-width: 0; }
.supsay b { display: block; font-size: 13px; }
.supsay b + .sub { margin: 0 0 10px; }
.supqr.empty span { font-size: 22px; color: var(--faint); }
.supsay .sub { font-size: 12px; }
.supgo {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
  margin-top: 14px; padding: 12px 14px; border-radius: 12px; border: 0; cursor: pointer;
  background: linear-gradient(180deg, #2aabee, #229ed9); color: #fff;
  font: 700 14.5px var(--ui); box-shadow: var(--sheen), 0 6px 18px -8px rgba(42,171,238,.7);
}
.supgo:disabled { opacity: .6; cursor: default; }
.suprow2 { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; justify-content: center; }
.suprow2 .sub { font-size: 12px; }

.signout {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; margin-top: 16px; padding: 12px;
  background: transparent; border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--down) 42%, transparent);
  color: var(--down); font: 600 13.5px var(--ui); cursor: pointer;
}
.signout:hover {
  background: color-mix(in srgb, var(--down) 10%, transparent);
  border-color: color-mix(in srgb, var(--down) 62%, transparent);
}

/* ==========================================================================
   The list a select opens
   ==========================================================================
   It used to be a window of the operating system's, above the page, drawn in
   whatever palette the browser felt like. `color-scheme` is the only thing a
   stylesheet can say to such a window, we said it, and a customer photographed
   a white list standing over the dark interface regardless.

   The deeper trouble was that nobody could ever have caught it here: a window
   that is not part of the page never appears in a screenshot of the page, so
   no check on any build has ever seen one. Now the list is a `div` and every
   rule below applies to it - which also means `design/select-list.mjs` can
   photograph it and `tests/test_web.mjs` can hold it to this.

   `web/selectlist.js` is what draws it. The `select` itself is untouched. */

.optlist {
  position: fixed; z-index: 320;   /* over every window, including #shotShow */
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--panel-2, var(--panel));
  border: 1px solid var(--line); border-radius: 10px;
  box-shadow: var(--elev-2, 0 14px 40px -12px rgba(0, 0, 0, .55));
  padding: 4px; min-width: 120px; max-width: min(420px, 92vw);
  font: 400 12.5px/1.35 var(--ui);
  color: var(--text);
}

.optlist .optrow {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 9px; border-radius: 7px; cursor: pointer;
  white-space: nowrap;
}
/* The row under the pointer and the row the keyboard is on are the SAME mark.
   Two different highlights on one list is two answers to "which one am I
   about to choose". */
/* A row the search has ruled out.
 *
 * `sift()` hides one by setting `hidden` on it, which is the browser's own way
 * and needs no class - except that the rule above sets `display` on the same
 * element, and an author's `display` beats the browser's `[hidden]`. So the
 * filter ran, marked every row it had rejected, and every one of them stayed
 * on the screen: typing into a thirty-six row list left thirty-six rows.
 * Reported as «تایپ میکنیم لیست کوتاه نمیشه».
 *
 * Written with the attribute in the selector rather than with `!important`,
 * because it only has to beat one rule and it is next to it. */
.optlist .optrow[hidden],
.optlist .optgroup-label[hidden],
.optlist .optmiss[hidden] { display: none; }
.optlist .optrow.at { background: var(--hover, rgba(255, 255, 255, .07)); }
.optlist .optrow.on { color: var(--accent); }
.optlist .optrow.off { color: var(--faint); cursor: default; }

/* The tick keeps its width whether or not it is showing one, so the names
   line up in a column instead of shifting by a character as the choice
   moves. */
.optlist .opttick {
  flex: 0 0 12px; text-align: center; font-size: 11px; color: var(--accent);
}
.optlist .opttext { overflow: hidden; text-overflow: ellipsis; }

.optlist .optgroup-label {
  padding: 7px 9px 3px; color: var(--faint); font-size: 11px;
  /* No letter-spacing and no uppercase: both are Latin devices, and this
     heading is a Persian word as often as an English one. */
}
.optlist .optnone { padding: 10px 12px; color: var(--faint); }

/* ---- the filter on a long list ------------------------------------------
   Design 10 of the ten. It is only drawn over twelve options or more - see
   `SIFT_AT` in `selectlist.js` for why twelve - and it is a picture of what
   the keyboard is holding rather than a field of its own: the select keeps
   focus, because focus is what keeps this list open at all.

   Sticky, so it stays while the rows run under it, and painted so the rows do
   not show through the gap the scroller leaves. */
.optlist .optfind {
  position: sticky; top: -4px; z-index: 1;
  display: flex; align-items: center; gap: 7px;
  margin: -4px -4px 4px; padding: 9px 11px;
  background: var(--panel-2, var(--panel));
  border-bottom: 1px solid var(--line-soft);
  border-radius: 10px 10px 0 0;
  color: var(--faint);
}
.optlist .optfindbox {
  flex: 1 1 auto; min-width: 0;
  /* Out of the shared field on purpose: this one is inside a box that is
     already a box, and a second border here would draw a field within a
     field. */
  height: auto; padding: 0; border: 0;
  background: none; box-shadow: none;
  color: var(--text); font: 500 12.5px var(--ui);
  cursor: default;
}
.optlist .optfindbox::placeholder { color: var(--faint); }
.optlist .optmiss { white-space: normal; max-width: 260px; line-height: 1.5; }

/* The box while its list is open, so it does not look inert underneath it.
   The same border focus draws, because it is the same state to a reader. */
select[data-listing] {
  border-color: var(--accent);
  background-color: var(--field-hover);
}

/* ---------- the calendar and the clock ----------
   The last three native popups in the product: two dates in the laboratory
   and one time in Settings. Same story as the list a select opens - a window
   of the operating system's, above the page, that no rule here can dress and
   no screenshot of the page can hold. `web/datefield.js` draws these.

   The field itself keeps its type, so typing into its segments and its value
   format stay the browser's. Only the little indicator inside it goes, and
   with it the only thing that could open the browser's own picker. */

input[type=date]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator {
  display: none;
}
/* Chromium keeps a slot for it even when it is not drawn. */
input[type=date]::-webkit-inner-spin-button,
input[type=time]::-webkit-inner-spin-button { display: none; }

/* Ours, beside the field rather than inside it: the field is a row of
   segments the browser lays out, and anything put inside moves them. */
.pickopen {
  background: none; border: 0; cursor: pointer;
  color: var(--dim); font-size: 14px; line-height: 1;
  padding: 4px 6px; border-radius: 6px; margin-inline-start: -2px;
}
.pickopen:hover { background: var(--hover); color: var(--text); }
input[data-picking] + .pickopen { color: var(--accent); }
input[data-picking] { border-color: var(--accent); }

/* The sheet takes `.optlist` for its ground, border and shadow, so there is
   one popup surface in the product and not two that drift apart. */
.datesheet { padding: 8px; min-width: 236px; }

.datesheet .dhead {
  display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
}
.datesheet .dwhen { flex: 1; text-align: center; font: 500 12.5px/1 var(--ui); }
.datesheet .dstep {
  background: none; border: 0; color: var(--dim); cursor: pointer;
  font-size: 16px; line-height: 1; padding: 2px 8px; border-radius: 6px;
}
.datesheet .dstep:hover { background: var(--hover); color: var(--text); }

.datesheet .ddow, .datesheet .dgrid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
}
.datesheet .ddow span {
  text-align: center; color: var(--faint); font-size: 10.5px; padding: 2px 0;
}
.datesheet .dcell {
  background: none; border: 1px solid transparent; border-radius: 6px;
  color: var(--text); font: 400 12px/1 var(--ui);
  padding: 6px 0; text-align: center; cursor: pointer;
  /* Latin digits in a Persian calendar are still digits; what matters is that
     the column does not shift as the numbers change width. */
  font-variant-numeric: tabular-nums;
}
.datesheet .dcell.out { visibility: hidden; cursor: default; }
.datesheet .dcell:hover:not(.off) { background: var(--hover); }
.datesheet .dcell.today { border-color: var(--line-strong, var(--line)); }
.datesheet .dcell.on { background: var(--accent); color: #fff; }
.datesheet .dcell.off { color: var(--faint); cursor: default; }

.datesheet .dfoot { margin-top: 7px; display: flex; justify-content: center; }
.datesheet .dtoday {
  background: none; border: 1px solid var(--line); border-radius: 999px;
  color: var(--dim); font: 500 11.5px/1 var(--ui); padding: 5px 12px;
  cursor: pointer;
}
.datesheet .dtoday:hover { border-color: var(--accent); color: var(--text); }

.datesheet .thead {
  display: flex; justify-content: space-between; gap: 10px;
  color: var(--faint); font-size: 11px; padding: 0 4px 5px;
}
.datesheet .tcols { display: flex; gap: 6px; }
.datesheet .tcol {
  flex: 1; max-height: 210px; overflow-y: auto; overscroll-behavior: contain;
}
.datesheet .trow {
  display: block; width: 100%; background: none; border: 0; border-radius: 6px;
  color: var(--text); font: 400 12.5px/1 var(--mono); padding: 6px 0;
  text-align: center; cursor: pointer;
}
.datesheet .trow:hover { background: var(--hover); }
.datesheet .trow.on { background: var(--accent); color: #fff; }

/* ==========================================================================
   The rule builder
   ==========================================================================
   A row is one sentence: this, compared how, with that. It has to read as a
   sentence at a glance and wrap without becoming a column of orphaned boxes,
   which is what a plain flex row does the moment an indicator with two
   arguments is chosen. */

.bldrow {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  /* Room down the trailing edge for the x, which sits outside the flow.
   * In the flow it is the last thing on the line, so a row that fills the
   * width to within thirty pixels wraps the x onto a line of its own - one
   * lonely control under a finished sentence, looking like a third thing to
   * fill in. Persian did exactly that. */
  position: relative;
  padding: 7px 8px; padding-inline-end: 28px; margin-bottom: 6px;
  background: var(--sunken, rgba(0,0,0,.16));
  border: 1px solid var(--line); border-radius: 9px;
}
.bldrow .bldno {
  flex: 0 0 20px; text-align: center;
  color: var(--faint); font: 500 11px/1 var(--mono);
}
/* A rule of a strategy is a sentence built of fields, and a field in it may
   be as narrow as the sentence needs. Nothing else here is its own. */
.bldrow select,
.bldrow input { min-width: 0; }
/* A length is two or three digits and never needs the width of a name. The
   ten pixels off it are what puts the Persian sentence back on one line. */
.bldrow input[type=number] { width: 52px; font-family: var(--mono); direction: ltr; }
/* Narrow enough that a seven-control row fits on one line at the pane's
   width. It did not, and the only thing that wrapped was the × on the end,
   which then sat alone on a second line looking like a control of its own. */
.bldrow select { max-width: 150px; }
.bldrow .sub { font-size: 11px; }
.bldrow .bldx {
  position: absolute; inset-inline-end: 4px; top: 5px;
  background: none; border: 0; color: var(--faint);
  font-size: 15px; line-height: 1; padding: 3px 6px; cursor: pointer;
  border-radius: 6px;
}
.bldrow .bldx:hover { background: var(--hover); color: var(--down); }

/* The words that make the boxes a sentence. Quieter than the boxes on
   purpose: they are the grammar, not the choices. They must never wrap in
   the middle of themselves - "with a length of" breaking after "with" would
   read as two separate labels for two boxes. */
.bldword { color: var(--dim); font-size: 12px; white-space: nowrap; padding: 0 1px; }

/* Somewhere to start. Pressing one fills the form; it is not a mode and
   nothing stays selected, because the next thing you do is change it. */
.bldstarts { display: flex; flex-wrap: wrap; gap: 6px; }
.bldstart {
  background: var(--panel); color: var(--dim);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 6px 12px; font: 500 12px/1 var(--ui); cursor: pointer;
}
.bldstart:hover { border-color: var(--accent); color: var(--text); background: var(--hover); }

.bldexits { display: flex; gap: 10px; flex-wrap: wrap; }
.bldexits .labfield { flex: 1; min-width: 150px; }

.bldchk {
  display: flex; align-items: center; gap: 7px; margin: 8px 2px 0;
  color: var(--dim); font-size: 12px; cursor: pointer;
}

#bldPine {
  width: 100%; font-family: var(--mono); font-size: 12px;
  direction: ltr; text-align: left;
}
#bldCount { color: var(--faint); font-size: 11.5px; }

/* ---- the two ways back into an account ---- */

/* How many of the two are in place, as a picture.
 *
 * The section used to open with three lines of amber prose and nothing else,
 * and "how am I doing" was a thing you had to read for. Two segments answer
 * it before the sentence is reached, and a half-filled bar is the one shape
 * everybody already reads as unfinished work. */
.meter { display: flex; gap: 4px; margin: 2px 13px 10px; }
.meter i { height: 6px; flex: 1; border-radius: 3px; background: var(--bg); }
.meter i.on { background: var(--up); }
/* The missing one is gold rather than red: nothing is broken, something is
   unfinished, and red here would be the same alarm the four locked buttons
   use for a refusal. */
.meter i.miss { background: color-mix(in srgb, var(--gold) 55%, var(--bg)); }

/* One way back, as a row: a mark, what it is, what it costs, and at most one
   press. The two rows are the same shape so the pair reads as a pair.
 *
 * `#waysBox` on the selector, and that is the whole of a four-part bug.
 * `.setrow > *:not(summary)` insets every direct child by 13px. The
 * authenticator row IS a direct child, so it lost its own padding to that rule
 * and sat at 13; the key rows live inside `#waysKeys`, which took the 13 and
 * then let `.wayrow` add 13 more, so they sat at 26. Measured: the two row
 * titles thirteen pixels out of line with each other, the delete button
 * thirteen short of the edge the button below it reaches, and three different
 * left edges in one panel. Written with an id, both rows are the same row. */
#waysBox .wayrow {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px 13px; border-top: 1px solid var(--line-soft);
}
#waysBox .wayrow:first-of-type { border-top: 0; }
/* The list is a list, not a box with a box in it. */
#waysBox #waysKeys { padding: 0; }
/* The sentence reads from the start edge in both languages.
 *
 * `#welcome p.sub` centres every caption in this drawer, and `body.fa .sub`
 * sets `start` - so this one paragraph was centred in English and hard against
 * the right in Persian. The same shape of fault as the line under the order
 * ticket: a blanket rule for captions catching a line that is not one. */
#waysBox #waysWhy { text-align: start; padding: 0 13px; margin: 0 0 2px; }
.wayrow .what { flex: 1 1 auto; min-width: 0; }
/* The row's TITLE, and only that. Written as `.what b` it also caught the
   `<b class="num">` holding the date inside the line under it, turned it into
   a block, and dropped the date onto a line of its own in 12.5px bold - which
   is exactly what "Made on" / "4 Sept 2026" on two lines was. */
.wayrow .what > b { display: block; font-weight: 600; font-size: 12.5px; }
/* "Made on <date>" is one line. It wrapped, and a date on a line of its own
   under its own label reads as a second fact rather than the end of the
   first. `nowrap` and not a width: the row has the room once the date is
   written the way the rest of the product writes dates. */
.wayrow .what .sub { display: block; margin-top: 3px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
/* Centred against the row rather than stretched to it: a button as tall as
   two lines of writing is a button that looks like a mistake. */
.wayrow > button { align-self: center; flex: 0 0 auto; }
.mark {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; line-height: 1;
  margin-top: 1px;
}
.mark.on {
  background: color-mix(in srgb, var(--up) 22%, transparent);
  color: var(--up);
  border: 1px solid color-mix(in srgb, var(--up) 55%, transparent);
}
/* The same weight as the tick. It was a dashed outline with nothing behind
   it beside a filled green disc, and the pair read as two things from
   different families rather than one thing in two states. */
.mark.off {
  background: color-mix(in srgb, var(--panel-3) 45%, transparent);
  border: 1px solid var(--line-strong); color: var(--dim);
}

/* What stands between a press and an account that cannot be recovered.
 *
 * Opened under the row it belongs to, so what is about to be lost is still on
 * screen while the password is typed. The far end of this is the server, which
 * asks for the password too — this is the half that says why. */
.guard {
  margin: 0 13px 11px; padding: 10px; border-radius: 8px;
  background: color-mix(in srgb, var(--down) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--down) 32%, transparent);
}
.guard p { margin: 0 0 6px; font-size: 11px; line-height: 1.7; color: var(--dim); }
.guard p b { color: var(--down); }
.chip.danger {
  border-color: color-mix(in srgb, var(--down) 45%, var(--line));
  color: var(--down);
}
.chip.danger:hover { border-color: var(--down); }

/* Room above it, because the row it follows is writing and this is a press.
   And room under it: the second button was landing against its edge. */
#waysDo { margin: 14px 13px 0; width: calc(100% - 26px); }
/* The second button is the same shape as the first.
 *
 * `.addrow:not(:has(input,...))` centres a row of bare buttons everywhere in
 * the product, and the reasoning on it is sound: a lone button against one
 * edge reads as something missing. It is wrong only here, and only because
 * the button directly above it is full width and draws the edge itself, so a
 * centred chip under it reads as two buttons that disagree. Matching the
 * width answers both: nothing is against an edge with an empty line beside
 * it, and nothing is out of line. */
#waysBox #keyNewRow { padding: 8px 13px 13px; }
#waysBox #keyNew { flex: 1 1 auto; }
#waysBox #waysSaid { padding: 0 13px 10px; }
#waysBox .field { display: block; }
#waysBox .field input { display: block; width: 100%; margin-top: 4px; }

/* Thirty characters that somebody is going to read off a screen and type in
   somewhere else, so: monospace, spaced out, and `ltr` whatever language the
   interface is in. Without the direction it is a Latin run inside a Persian
   paragraph, and the browser puts the pieces where the paragraph wants them
   rather than where they were written. */
.keycode {
  font-family: var(--mono); font-size: 15px; letter-spacing: 1px;
  direction: ltr; unicode-bidi: isolate; text-align: center;
  background: var(--panel-2); border: 1px dashed var(--accent);
  border-radius: 8px; padding: 12px 10px; margin: 10px 0;
  color: var(--accent);
  /* Wraps at the dashes and nowhere else. `break-all` split a group down the
     middle - "…A0B6B-6" and then "X03S" on the next line - which is exactly
     the shape somebody copies down wrong. */
  overflow-wrap: break-word; word-break: normal;
}

/* When a key is made on the same day it is read, the row beside its name is a
   date, and a date is a run of Latin digits inside a Persian line: without
   isolation the browser hands the paragraph's direction to the digits and
   2026-09-02 is drawn as 02-09-2026. */
#waysKeys .num { direction: ltr; unicode-bidi: isolate; font-weight: 600; }

/* The state beside the title, in three colours because it has three meanings.
   Gold is one of the two, which is unfinished rather than broken; green is
   done; red is an account with no way back at all.

   The red is written past `#welcome .warn`, which paints every warning in this
   drawer gold. That rule is right for the drawer and wrong for exactly this
   one place: measured, "no way back at all" and "one of the two" came out the
   same colour, which is the whole distinction this line exists to draw. */
.setrow .rowsay.soft { color: var(--gold-ink); }
.setrow .rowsay.good { color: var(--up); }
#welcome .setrow .rowsay.warn { color: var(--down); }

/* The square is drawn in `currentColor`, so whatever it sits on decides its
   ink. White and black, always: a phone camera reading a dark code off a dark
   panel is a coin toss, and this is the one picture that has to work first
   time. */
.keyqr {
  max-width: 200px; margin: 12px auto; padding: 10px;
  border-radius: 8px; background: #fff; color: #000;
}
.keyqr svg { display: block; width: 100%; height: auto; }

/* `warn` was written into nineteen places in the account panel and styled in
   none of them: `.warn` has a colour only inside `.subinfo`, so every one of
   those sentences came out the same grey as the sentence beside it. The one
   that matters is "there is no way back into this account", which is the
   whole reason that box exists. */
#welcome .warn { color: var(--gold-ink); }

/* ---------- signing in with Google ---------- */

/* Not a `.primary`, on purpose.
 *
 * The accent belongs to this product and to the actions it owns; this button
 * hands the customer to somebody else's service, and dressing it in our own
 * colour makes it read as the thing we most want pressed. It is a surface
 * button — the same weight as the panel it sits on, one hairline above it —
 * so it is the FIRST thing on the panel by position, not by shouting.
 *
 * Google's mark keeps its four colours in both themes. It is a trademark, and
 * a recoloured one reads as a copy of a sign-in button rather than a sign-in
 * button.
 */
.googlebtn {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; padding: 9px 14px;
  border: 1px solid var(--line-strong, var(--line));
  border-radius: 6px;
  background: var(--panel-2);
  color: var(--fg); font: inherit; font-weight: 600;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.googlebtn:hover {
  background: var(--panel-3);
  border-color: var(--fg-dim, var(--line-strong, var(--line)));
}
.googlebtn:active { transform: translateY(1px); }
.googlebtn:disabled { opacity: .55; cursor: default; transform: none; }
.googlebtn .gmark { width: 17px; height: 17px; flex: 0 0 17px; }

/* The hairline with a word in it. Two rules rather than a border on the text:
 * a border under a centred word leaves the two halves different lengths as
 * soon as the word is translated, and «یا» is half the width of "or". */
.orline {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 0 10px; color: var(--dim); font-size: 11px;
}
.orline::before, .orline::after {
  content: ''; flex: 1 1 auto; height: 1px; background: var(--line);
}

#googleWait { margin-bottom: 10px; }
#googleWait p { margin: 0 0 8px; }
#googleWaitLink { word-break: break-all; }
#googleName { margin-bottom: 10px; }

/* The "getting back in" box, at the moment it is asked for rather than
 * stumbled on. A ring that fades, not a colour that stays: what it has to do
 * is catch the eye of somebody looking at the licence they just took, and
 * then stop being a decoration on a box they now have to read. */
#waysBox.askingnow {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 8px;
  animation: waysask 2.6s ease-out forwards;
}
@keyframes waysask {
  0%   { outline-color: var(--accent); }
  70%  { outline-color: var(--accent); }
  100% { outline-color: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  #waysBox.askingnow { animation: none; outline-color: var(--accent); }
}

/* Two small readings in the top bar: how long is left, and how many trades
 * are left. Both are STATES, not warnings that arrive - they sit there like a
 * battery indicator and never interrupt. That is why they are chips in the
 * row rather than a banner across the screen, and why neither can be
 * dismissed: there is nothing to dismiss, only something to fix. */
.chip.warnchip.calm { border-color: var(--line); color: var(--dim); font-weight: 500; }
.chip.warnchip {
  border-color: color-mix(in srgb, var(--gold-ink) 55%, var(--line));
  color: var(--gold-ink);
  font-weight: 600;
}
.chip.warnchip:hover {
  background: color-mix(in srgb, var(--gold-ink) 14%, transparent);
}
/* The last day is not the same as the last week, and a colour that never
 * changes says they are. */
.chip.warnchip.today {
  border-color: color-mix(in srgb, var(--sell) 60%, var(--line));
  color: var(--sell);
}
.chip.mutedchip { color: var(--dim); }
.chip.mutedchip.low { color: var(--gold-ink); font-weight: 600; }

/* A button that is going to ask for a subscription, saying so before it is
 * pressed. It still works and still reads as itself - pressing it is how
 * somebody learns what a subscription is for - it simply stops looking
 * identical to the buttons that open. */
.chip.locked { opacity: .72; }
.chip.locked::after {
  content: '';
  width: 9px; height: 9px;
  margin-inline-start: 5px;
  flex: 0 0 9px;
  background: currentColor;
  opacity: .75;
  /* A padlock, as a mask rather than a glyph: an emoji here would take the
     system's own colour and size and break the row's alignment in Persian. */
  -webkit-mask: var(--lockmark) center/contain no-repeat;
  mask: var(--lockmark) center/contain no-repeat;
}
:root {
  --lockmark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 10V7a6 6 0 0 1 12 0v3' fill='none' stroke='%23000' stroke-width='2.6'/%3E%3Crect x='3.5' y='10' width='17' height='12' rx='2.5' fill='%23000'/%3E%3C/svg%3E");
}

/* The instrument list, when the licence only reaches one of them.
 *
 * Dimmed and named, not hidden. A free account seeing the other sixty-two is
 * the argument for a subscription making itself, and hiding them would turn
 * a product with sixty-three instruments into one with one. */
.pickrow.beyond { opacity: .55; }
.pickrow.beyond:hover { opacity: .85; }
.pickrow.yours .sym::after {
  content: '';
  display: inline-block;
  width: 6px; height: 6px;
  margin-inline-start: 6px;
  border-radius: 50%;
  /* The accent, not the buy colour. Green here would mean a direction, and
     this dot is about a licence rather than a trade - the buy token is
     counted, on purpose, so nothing else borrows it. */
  background: var(--accent);
  vertical-align: middle;
}
/* A hundred and twenty-two identical gold buttons down one column is not
   sixty-two arguments for a subscription, it is a wall. Photographed on a
   free account: the Action column read the same word over and over, and the
   ONE row that could be pressed was in a different group behind a fold.
   So a locked row is quiet - a lock and a word, no border, no fill - and the
   weight on the screen goes back to the row that does something. */
.get.needsub {
  border-color: transparent; background: none; box-shadow: none;
  color: var(--faint); padding-inline: 4px;
  display: inline-flex; align-items: center; gap: 5px;
}
.get.needsub:hover { color: var(--gold-ink); background: none; }

/* The history server's list did not come (history.js, F12). */
.pickfail {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 4px; padding: 10px 14px; font-size: 12px; color: var(--text);
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--warn, #d9a441) 12%, transparent);
}
.pickfail > span { flex: 1 1 220px; min-width: 0; }
.pickfail > button { flex: 0 0 auto; }

/* And whose list this is, said once, above the groups.
   Pinned rather than sorted into place: it belongs to its own market, and
   moving it out of that market would be a second lie about where it lives. */
.pickmine {
  display: flex; align-items: center; gap: 11px;
  margin: 0 0 4px; padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 12%, transparent),
    color-mix(in srgb, var(--accent) 2%, transparent));
  position: relative;
}
.pickmine::after {
  content: ""; position: absolute; inset-inline: 18px; bottom: -1px; height: 2px;
  border-radius: 2px; background: var(--accent);
  box-shadow: 0 0 14px 2px color-mix(in srgb, var(--accent) 45%, transparent);
}
/* Its own name, and not `.mark`.
 *
 * `.mark` means three different things in this stylesheet: a small uppercase
 * label, a 20px round tick in the ways-back rows, and this. This rule set the
 * colours and the radius and never set a WIDTH, so `width: 20px` from the
 * round tick applied - specificity decides each property on its own, not the
 * whole rule - and the pill came out eighteen pixels wide with «Your free
 * instrument» printed straight out of it and across the symbol beside it.
 * Photographed by the owner; measured at 82px of words in 18px of box.
 *
 * The two other users of `.mark` set their own width and were unharmed, which
 * is why nothing else showed it. A name of its own is the fix rather than one
 * more `width` here, because the next generic rule would land on it again.
 */
.pickmine .minepill {
  flex: 0 0 auto;
  /* Said out loud rather than left to the cascade, which is what went wrong. */
  width: auto; height: auto; display: inline-block; white-space: nowrap;
  font-size: 10.5px; line-height: 1.7; color: var(--accent-ink, var(--accent));
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  border-radius: 999px; padding: 1px 9px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.pickmine .g { flex: 1 1 auto; min-width: 0; }
.pickmine .sym { font: 700 14px var(--mono); color: var(--text); }
.pickmine .s {
  display: block; color: var(--faint); font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pickmine .pickacts { display: flex; gap: 6px; flex: 0 0 auto; }

/* ---------- what a locked button leads to ---------- */

/* The picture on the "you do not have this yet" window.
 *
 * Built from the same tokens as the real panels rather than photographed: a
 * screenshot would need one per language and one per theme, and would be
 * wrong the day either panel changed. What it costs instead is that it has to
 * be honest - so it is labelled as an example, in the corner of the picture
 * rather than in small print underneath, where somebody skimming will see it.
 */
.lockshot {
  /* Measured against the card, not the window. A `min-width` media query here
     asked how wide the SCREEN is, and the screen is 1400px while this card is
     380 - so four columns stayed in force and every Persian label was cut in
     half on a wide monitor. */
  container-type: inline-size;
  position: relative;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px;
  margin: 4px 0 14px;
  display: flex; flex-direction: column; gap: 12px;
}
/* Said BEFORE the figures, not after them and not beside them.
 *
 * It was a floating tag in the top corner, at `inset-inline-end` - which is
 * the END of the line, the last place the eye goes, after every number has
 * already been read as somebody's own account. In Persian that put it top
 * left, adrift on the border of the box. It also wore `text-transform:
 * uppercase` and letter-spacing, both of which are Latin devices: spacing out
 * a joined script pulls the letters of a word apart.
 *
 * A caption row with a rule under it is read first and cannot cover anything.
 * Under the picture was the other candidate tried, and it is the exact fault
 * this label exists to prevent: you read the figures, and then find out.
 */
.lockeg {
  display: block;
  font-size: 11px;
  color: var(--faint);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}

/* Two across, not four.
 *
 * Four fitted the English labels and cut every Persian one in half:
 * "Max drawdown" is «بیشترین افت سرمایه», and at a quarter of a 380px sheet
 * it arrives as «بیشترین اُ…». A truncated label is worse than a missing one
 * - it looks like the product does that to real figures too. */
.locktiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.locktile {
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
  padding: 8px 10px;
  display: flex; flex-direction: column; gap: 2px;
  min-width: 0;
}
.locktile span {
  font-size: 10px; color: var(--dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Latin digits and a tabular face, like every other figure in the product: a
   price and a win rate are read against a broker's own screen. */
.locktile b {
  font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  /* A figure keeps its own order. "+9.2%" has no strongly-directional
     character in it, so in a right-to-left panel the browser hands it the
     panel's direction and the sign comes out on the wrong end: "9.2%+".
     `plaintext` gives each value its own base direction and falls back to
     left-to-right when there is nothing strong in it, which is every figure
     here. The tile's own alignment is unaffected. */
  unicode-bidi: plaintext;
}
.locktile b.good { color: var(--up); }
.locktile b.bad { color: var(--down); }

/* The two sides of a choice, where the window is about one.
   Four tiles listed the terms of the free tier and said nothing at all about
   the other half of the decision somebody was standing in front of. These are
   the halves. The chosen one carries the accent and a foot that glows in it,
   the same way the account drawer marks the state it is in. */
.lockcards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px; }
.lockcard {
  position: relative; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 12px 13px;
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.lockcard > b { font-size: 14px; font-weight: 700; }
.lockcard .what { font-size: 11px; color: var(--faint); }
.lockcard .has {
  font-size: 11.5px; color: var(--dim); line-height: 1.6;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--line-soft);
}
.lockcard.on { border-color: var(--accent); background: var(--sel); }
.lockcard.on::after {
  content: ""; position: absolute; inset-inline: 16px; bottom: -1px; height: 2px;
  border-radius: 2px; background: var(--accent);
  box-shadow: 0 0 14px 2px color-mix(in srgb, var(--accent) 50%, transparent);
}

.lockframe {
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
  padding: 8px;
}
.lockcurve { width: 100%; height: 64px; display: block; }
.lockcurve .line {
  fill: none; stroke: var(--up); stroke-width: 1.6;
  stroke-linejoin: round; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.lockcurve .fill {
  fill: color-mix(in srgb, var(--up) 16%, transparent);
  stroke: none;
}

.lockbars { display: flex; flex-direction: column; gap: 5px; }
.lockbar { display: flex; align-items: center; gap: 8px; }
/* Wide enough for a weekday written out. «چهارشنبه» does not fit in 34px and
   wrapped onto two lines, which turned a row of five bars into a ragged
   block. */
.lockbar .lb {
  width: 4.6rem; flex: 0 0 4.6rem;
  font-size: 11px; color: var(--dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lockbar .lt {
  flex: 1 1 auto; height: 8px; background: var(--panel);
  border-radius: 4px; overflow: hidden;
}
.lockbar .lt i { display: block; height: 100%; border-radius: 4px; }
.lockbar .lt i.up { background: var(--up); }
.lockbar .lt i.down { background: var(--down); }

.lockcode {
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
  padding: 10px 12px;
  font: 12px/1.7 ui-monospace, "Cascadia Mono", Consolas, monospace;
  white-space: pre-wrap;
  /* A rule is written left to right in every language: it is code. */
  direction: ltr; text-align: left;
  overflow-x: auto;
}
.lockcode .k { color: var(--accent); font-weight: 700; }
.lockcode .c { color: var(--dim); }

.lockpoints { margin: 0 0 4px; padding-inline-start: 1.1rem; }
.lockpoints li { margin: 0 0 7px; line-height: 1.6; }
.lockpoints li::marker { color: var(--accent); }

.lockfoot { margin-top: 4px; }

/* Four across only where the card itself is wide enough for four. */
@container (min-width: 560px) {
  .locktiles { grid-template-columns: repeat(4, 1fr); }
}

/* The fold on a panel heading, and the strip's own way off the chart. */
.sidehead { display: flex; align-items: center; gap: 8px; }
.foldhead {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  display: grid; place-items: center;
  background: none; border: 0; padding: 0;
  color: var(--dim); cursor: pointer;
}
.foldhead:hover { color: var(--text); }
.foldhead i {
  width: 7px; height: 7px;
  border-inline-end: 1.6px solid currentColor;
  border-block-end: 1.6px solid currentColor;
  transform: rotate(45deg);
  transition: transform .14s ease;
}
/* Folded, it points the way it will go when pressed. */
.foldhead[aria-expanded="false"] i { transform: rotate(-45deg); }

.ct-x {
  background: none; border: 0; padding: 0 6px;
  color: var(--dim); cursor: pointer; font-size: 12px;
  align-self: stretch;
}
.ct-x:hover { color: var(--text); }

/* A field in that row that is read rather than chosen.
 *
 * The instrument the laboratory runs on is whatever the chart is showing, so
 * it is a reading and not a control - and it has to LOOK like a reading, or
 * somebody presses it and nothing happens. Same height and same baseline as
 * the boxes beside it, so the row still reads as one row, but no border and
 * no ground: nothing to press.
 */
.labfield .labstatic {
  /* The same box as the controls beside it, and that is measured rather than
     eyeballed: at `padding: 6px 2px` it came out 29 tall against their 38 and
     sat five pixels high, which reads as a row that did not line up rather
     than as a reading among controls.

     Same padding and the same border width as a `select`, with the border
     transparent - so it occupies the same space and still has nothing to
     press. */
  padding: 6px 8px;
  border: 1px solid transparent;
  /* 38, because that is what a `select` in this row measures and because
     `box-sizing: border-box` is in force here - so this is the whole box and
     not the content inside it. Subtracting the padding and the border first
     was the previous version, and it left the reading 31 tall against their
     38, five pixels high, which reads as a row that did not line up. */
  min-height: var(--field-h);
  display: flex; align-items: center;
  font-size: 12px; font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  /* A symbol is Latin in both languages and keeps its own order. */
  direction: ltr; unicode-bidi: plaintext; text-align: start;
  justify-content: flex-start;
  min-width: 72px;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
 * The prop challenge window
 *
 * Every selector here is under `#prop`. The names inside it - .num, .lab,
 * .track, .dot, .btn - are the obvious ones for what they hold and several of
 * them are already used elsewhere in this file for something else. Scoping is
 * cheaper than inventing nine ugly names, and it means a change here cannot
 * reach a window nobody was looking at.
 * ----------------------------------------------------------------------- */
#prop .sheet { width: min(780px, 94vw); }
#prop .n { direction: ltr; unicode-bidi: plaintext; }
/* `.pad` is a flex ROW with wrapping, which is right for a sheet made of
 * controls and wrong for one made of stacked sections: the verdict strip came
 * out sitting beside the picker with half the window empty next to it. */
#prop .pad { padding: 0; display: block; overflow-y: auto; }

#prop .propctx {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  padding: var(--s3) var(--s4) var(--s2);
}
#prop .pickbox {
  display: flex; align-items: center; gap: 7px; background: var(--bg);
  border: 1px solid var(--panel-3); border-radius: 8px; padding: 5px 8px 5px 10px;
}
#prop .pickbox i { font-style: normal; color: var(--faint); font-size: 11px; }
#prop .propsel {
  background: transparent; border: 0; color: var(--text);
  font: 500 13px var(--ui); padding: 1px 2px;
}

/* Which rules are actually in force, under the picker rather than behind a
 * button: the whole value of this window is that somebody can see what they
 * are being judged by without opening anything. */
#prop .propstamp {
  padding: 0 var(--s4) var(--s3); color: var(--faint); font-size: 11.5px;
  border-bottom: 1px solid var(--line-soft); line-height: 1.9;
}
#prop .propstamp a {
  color: var(--dim); cursor: pointer; margin-inline-start: 6px;
  border-bottom: 1px dotted var(--panel-3);
}
#prop .propstamp .was { margin-inline-start: 8px; opacity: .75; }

#prop .propidle { padding: var(--s4); }
#prop .propidle p { margin: 0 0 var(--s2); }
#prop .propidle .sub { color: var(--dim); font-size: 12.5px; margin: 0; }

#prop .propverdict {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--up) 14%, transparent),
    color-mix(in srgb, var(--up) 4%, transparent));
  border-bottom: 1px solid var(--line-soft);
}
#prop .propverdict.out {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--down) 16%, transparent),
    color-mix(in srgb, var(--down) 5%, transparent));
}
#prop .propverdict .dot {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 9px; background: var(--up);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--up) 18%, transparent);
}
#prop .propverdict.out .dot {
  background: var(--down);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--down) 18%, transparent);
}
#prop .propverdict b { font-size: 14.5px; }
#prop .propverdict .sub { color: var(--dim); font-size: 12.5px; }
#prop .propverdict .money { font-weight: 700; font-size: 15px; color: var(--up); }
#prop .propverdict.out .money { color: var(--down); }

#prop .propbars { padding: var(--s2) var(--s4) var(--s3); }
#prop .propbar {
  display: grid; grid-template-columns: 100px 1fr auto;
  align-items: center; gap: var(--s3); padding: 9px 0;
}
#prop .propbar + .propbar { border-top: 1px solid var(--line-soft); }
#prop .propbar .lab { color: var(--dim); font-size: 13px; }
#prop .propbar .track {
  height: 9px; border-radius: 5px; background: var(--bg);
  box-shadow: var(--well); position: relative; overflow: hidden;
}
/* Filled from the reading edge in both languages, so "more of it gone" always
 * grows in the direction the eye starts from. */
#prop .propbar .fill { position: absolute; top: 0; bottom: 0; inset-inline-start: 0; border-radius: 5px; }
#prop .propbar .fill.good { background: linear-gradient(to left, var(--up), color-mix(in srgb, var(--up) 70%, #000)); }
#prop .propbar .fill.warn { background: linear-gradient(to left, var(--gold), color-mix(in srgb, var(--gold) 70%, #000)); }
#prop .propbar .fill.bad  { background: linear-gradient(to left, var(--down), color-mix(in srgb, var(--down) 70%, #000)); }
#prop .propbar .num { font: 700 13px var(--ui); min-width: 160px; text-align: end; }
#prop .propbar .num s {
  display: block; text-decoration: none; font-weight: 400;
  font-size: 11.5px; color: var(--faint);
}

#prop .propchips {
  display: flex; gap: var(--s2); flex-wrap: wrap; padding: 0 var(--s4) var(--s4);
}
#prop .propchip {
  display: flex; align-items: center; gap: 6px; background: var(--bg);
  border: 1px solid var(--panel-3); border-radius: 999px;
  padding: 5px 11px; font-size: 12.5px; color: var(--dim);
}
#prop .propchip b { color: var(--text); font-weight: 500; }
#prop .propchip .tick { color: var(--up); font-size: 12px; }
#prop .propchip.soon { border-color: color-mix(in srgb, var(--gold) 55%, var(--panel-3)); }
#prop .propchip.soon .tick { color: var(--gold); }
/* A rule that is OFF, said rather than left out: silence reads as "we did not
 * check it", which is the one thing this window must never imply. */
#prop .propchip.off { color: var(--faint); border-style: dashed; }
#prop .propchip.off .tick { color: var(--faint); }

#prop .propform {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3);
  padding: var(--s4); border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel-2) 40%, var(--panel));
}
#prop .propform label { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
#prop .propform label.wide { grid-column: 1 / -1; }
#prop .propform label.check { flex-direction: row; align-items: center; gap: var(--s2); }
/* A combination that is allowed but does nothing. Gold, not red: the numbers
   belong to whoever is writing the rules and this refuses nothing, it only
   says what the number will do. Empty until there is something to say, and
   `:empty` keeps the gap out of the grid meanwhile. */
#prop .propform .propwarn {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--gold-ink);
  font-size: 11.5px;
  line-height: 1.6;
}
#prop .propform .propwarn:empty { display: none; }
#prop .propform span { color: var(--dim); }
/* A figure is written left to right in both languages. That is this form's
   own business; the box is not. */
#prop .propform input[type="number"], #prop .propform select {
  direction: ltr; text-align: start;
}
#prop .propform select { direction: inherit; }
#prop .propformgo { grid-column: 1 / -1; display: flex; gap: var(--s2); justify-content: flex-end; }

#prop .btn {
  border: 1px solid var(--panel-3); background: var(--bg); color: var(--text);
  border-radius: 8px; padding: 8px 14px; font: 500 13px var(--ui); cursor: pointer;
}
#prop .btn:hover { background: var(--hover); }
#prop .btn.go {
  background: var(--lift); background-color: var(--accent);
  border-color: var(--accent-2); color: var(--ink); box-shadow: var(--sheen);
}
/* In force, and only partly checkable. Not the same as a rule the firm does
 * not have, which is what `.off` marks. */
#prop .propchip.unsure { border-style: dashed; }
#prop .propchip.unsure .tick { color: var(--gold); }

/* What happened, once the challenge is over. Sits under the verdict strip,
 * where somebody is already looking. */
#prop .propover {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line-soft);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
}
#prop .propover p { margin: 0; flex: 1 1 100%; font-size: 13px; }
#prop .propover .sub { color: var(--dim); font-size: 12.5px; }
#prop .propover.out { background: color-mix(in srgb, var(--down) 6%, transparent); }
#prop .propover.won { background: color-mix(in srgb, var(--up) 6%, transparent); }

/* The same trading, dealt again. Under everything else, because it is the
 * answer to a different question from "where am I now". */
#prop .propodds {
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel-2) 30%, var(--panel));
  padding: var(--s4);
}
#prop .propodds.idle {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
}
#prop .propodds .sub { color: var(--faint); font-size: 12px; flex: 1; min-width: 240px; }
#prop .oddhead { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s3); }
#prop .oddhead b { font-size: 13.5px; }
#prop .oddhead span { color: var(--faint); font-size: 12px; }
#prop .oddbig { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }
#prop .oddpct { font: 700 40px/1 var(--ui); color: var(--gold); }
#prop .oddpct em { font-style: normal; font-size: 19px; color: var(--dim); margin-inline-start: 2px; }
#prop .oddsub { color: var(--dim); font-size: 12.5px; max-width: 230px; margin-top: var(--s2); }
#prop .oddsplit { flex: 1; min-width: 260px; display: flex; flex-direction: column; gap: 6px; }
#prop .oddrow {
  display: grid; grid-template-columns: 1fr 116px 44px;
  align-items: center; gap: 9px; font-size: 12.5px;
}
#prop .oddrow .k { color: var(--dim); }
#prop .oddrow .ot { height: 7px; border-radius: 4px; background: var(--bg); overflow: hidden; position: relative; }
#prop .oddrow .ot i { position: absolute; top: 0; bottom: 0; inset-inline-start: 0; border-radius: 4px; }
#prop .oddrow .ot i.p { background: var(--up); }
#prop .oddrow .ot i.d { background: var(--down); }
#prop .oddrow .ot i.m { background: var(--gold); }
#prop .oddrow .v { text-align: end; color: var(--text); font-weight: 500; }
#prop .oddnote { color: var(--faint); font-size: 11.5px; margin: var(--s3) 0 0; }
#prop .propodds > .btn { margin-top: var(--s3); }
/* Two halves, two jobs: the reading and the writing. See the note on `draw`. */
#prop .proptabs {
  display: flex; gap: 2px; padding: 0 var(--s4);
  background: var(--panel-2); border-bottom: 1px solid var(--line);
}
#prop .proptab {
  padding: 10px 16px; margin-bottom: -1px;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--dim); font: 500 13px var(--ui); cursor: pointer;
}
#prop .proptab:hover { color: var(--text); }
#prop .proptab.on { color: var(--text); border-bottom-color: var(--accent); }
#prop .propwas { color: var(--faint); font-size: 11.5px; }
/* The form is a page of its own now rather than a drawer under a line, so it
   needs no border of its own to separate it from what is above. */
#prop .propform { border-top: 0; background: none; }

/* "On the chart", back on the order panel where a forex trader's hand is.
 * At the far end of the heading, so the name of the section still reads
 * first. Gone on crypto, which is the one place it was asked to go. */
.sidehead .tg.onchart { margin-inline-start: auto; padding: 2px 0; font-size: 11.5px; }
body.crypto .sidehead .tg.onchart { display: none; }
/* Said only where the picker cannot act yet: the account is carrying trades,
 * so the size on it is a promise rather than a fact. */
#prop .proppending {
  padding: 0 var(--s4) var(--s3);
  color: var(--gold); font-size: 12px;
}

/* The free account's standing facts, under the top bar.
   Quiet on purpose: it is furniture, not a warning, and it is on screen for
   as long as somebody is on the free tier. The one thing that changes colour
   is the row of trade pips as they go out. */
.freebar {
  display: flex; align-items: center; gap: 0;
  padding: 0 var(--s4); min-height: 30px;
  background: var(--panel); border-bottom: 1px solid var(--line);
  font-size: 11.5px; color: var(--dim);
}
.freebar .cell { display: flex; align-items: center; gap: 7px; padding: 0 13px; }
.freebar .cell + .cell { border-inline-start: 1px solid var(--line); }
.freebar .cell:first-child { padding-inline-start: 0; }
.freebar .k { color: var(--faint); font-size: 10px; letter-spacing: .4px; }
.freebar b { font-weight: 600; color: var(--text); }
.freebar b.mono { font-family: var(--mono); direction: ltr; }
.freebar .gap { flex: 1 1 auto; }
.freebar .say { flex: 1 1 auto; padding-inline-start: 9px; }
.freebar .dot {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--gold);
  box-shadow: 0 0 8px 1px color-mix(in srgb, var(--gold) 55%, transparent);
}
.freebar .pips { display: inline-flex; gap: 4px; }
.freebar .pips i {
  width: 7px; height: 7px; border-radius: 50%; display: block;
  background: var(--up);
}
.freebar .pips i.off { background: transparent; border: 1px solid var(--line-strong); }
.freebar .chip.gold {
  border-color: color-mix(in srgb, var(--gold) 50%, transparent);
  color: var(--gold-ink, var(--gold));
}
/* Nothing left today, so the row that says so stops being furniture. */
.freebar.spent .pips i { background: transparent; border: 1px solid var(--down); }
.freebar.spent b { color: var(--down); }

/* The three most people start with, in the free chooser. */
.freeusual { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 10px; }
.freeusual button {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 999px; padding: 5px 12px; cursor: pointer;
  font: 500 11.5px var(--ui); color: var(--dim); box-shadow: var(--sheen);
}
.freeusual button .sy { font-family: var(--mono); direction: ltr;
  display: inline-block; font-weight: 600; }
.freeusual button.on {
  border-color: var(--accent); color: var(--text); background: var(--sel);
}
.setnote.quiet {
  background: none; border: 0; padding: 0 0 6px; color: var(--faint);
}
.setnote.quiet::before { content: none; }

/* ------------------------------------------------------------- folders
 *
 * The card that says where something is kept and lets it be moved. Drawn in
 * three places - the journal's first-run questions, the MetaTrader panel and
 * the indicators panel - and it looks the same in all three on purpose: the
 * answer to "where does this go" should not change shape depending on which
 * window you happen to be standing in.
 *
 * Every colour here is a token, and the text ones are `--text`, not `--ink`.
 * `--ink` is what is legible ON the accent - white in both themes - so a card
 * that reached for it drew the path in white on a pale grey block in the
 * light theme, unreadable, while the dark theme looked perfect. Nothing in
 * the name says which of the two it is; the picture did.
 */
.fcard { position: relative; overflow: hidden; margin: 12px 0;
         padding: 14px; border-radius: 12px;
         background: var(--panel-2); border: 1px solid var(--line);
         box-shadow: var(--elev-1); color: var(--text); }
.fcard::before { content: ''; position: absolute; inset-inline: 0; top: 0;
                 height: 1px; background: var(--sheen); }
/* A foot that glows in the accent when it is somewhere the customer chose,
   and in the warm colour when that somewhere is not there any more. */
.fcard.moved::after, .fcard.gone::after {
  content: ''; position: absolute; inset-inline: 0; bottom: 0; height: 2px;
  background: var(--accent); box-shadow: 0 0 14px var(--accent); }
.fcard.gone::after { background: var(--down); box-shadow: 0 0 14px var(--down); }

.fcard .fhead { display: flex; gap: 11px; align-items: flex-start; }
.fcard .fico { color: var(--accent); display: inline-flex; padding-top: 2px; }
.fcard .fwhat { min-width: 0; }
.fcard .fwhat b { display: block; font-size: 14px; color: var(--text); }
.fcard .fwhat .sub { font-size: 12px; color: var(--dim); line-height: 1.85; }

.fcard .fstate { margin-inline-start: auto; white-space: nowrap;
                 font-size: 11px; padding: 3px 9px; border-radius: 999px;
                 color: var(--dim); border: 1px solid var(--line);
                 background: var(--panel-3); }
.fcard .fstate.on { color: var(--accent); border-color: var(--accent);
                    background: color-mix(in srgb, var(--accent) 14%, transparent); }
.fcard .fstate.gone { color: var(--down-ink); border-color: var(--down);
                      background: color-mix(in srgb, var(--down) 14%, transparent); }

/* The path is the hero, so it gets its own block rather than a line of body
   text. Always left to right and always breakable: a Windows path in an
   RTL paragraph reads back to front, and one that cannot break runs off the
   edge of the card. */
.fcard .fpathbig { margin: 12px 0; padding: 10px 12px; border-radius: 9px;
                   background: var(--panel-3); color: var(--text);
                   border: 1px solid var(--line-soft); font-size: 13px;
                   direction: ltr; text-align: left; overflow-wrap: anywhere; }
.fcard .frow { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.fcard .frow .primary { padding: 7px 13px; border-radius: 9px; font-size: 13px; }
.fcard .frow .primary.waiting { opacity: .6; }
.fcard .fbring { display: flex; gap: 7px; align-items: center;
                 margin: 0 0 11px; font-size: 12px; color: var(--dim); }
.fcard .ffoot { margin: 11px 0 0; font-size: 11.5px; color: var(--dim);
                line-height: 1.9; }
.fcard .ffoot.warn { color: var(--down-ink); }

/* The answer to a control in the account panel, said beside the control.
 *
 * There is one shared line at the foot of that panel and every action used to
 * write into it - measured at 290 pixels below the button that caused it,
 * which on a scrolled panel is off the bottom of the window. A refusal
 * nobody sees and a success nobody sees are the same thing to the person
 * pressing the button, and both read as the program having hung.
 */
.actsaid:empty, .signsaid:empty { display: none; }
/* A sign-in's answer, under its button (account.js saySignIn, F2). */
.signsaid { margin: 8px 0 0; font-size: 12px; line-height: 1.85; }
.signsaid .warn { color: var(--down-ink); }
.actsaid { margin-top: 9px; font-size: 12px; line-height: 1.85;
           color: var(--dim); }
.actsaid .warn { color: var(--down-ink); }
.actsaid .good { color: var(--up-ink); }

/* ==========================================================================
 * Paying on a chain
 *
 * The chooser sits above whichever face is drawn, so switching network never
 * moves the panel under the pointer. The address is the one string here that
 * MUST be readable character by character: it is copied by eye by some people
 * and scanned by others, and a wrong character sends the money somewhere
 * nobody can reach.
 * ====================================================================== */
.paypick { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.paypick-b {
  flex: 1 1 auto; min-height: 30px; padding: 0 12px;
  background: var(--bg); color: var(--dim);
  border: 1px solid var(--line); border-radius: 8px;
  font: 500 12px/1 var(--ui); cursor: pointer; white-space: nowrap;
}
.paypick-b:hover { color: var(--text); border-color: var(--line-strong); }
.paypick-b.on {
  background: var(--panel-3); color: var(--text); font-weight: 600;
  border-color: var(--line-strong);
}
/* Broken to the width it has rather than clipped: half an address is worse
   than a small one, because half of it still looks like an address. */
.paycode.addr {
  font-size: 13px; line-height: 1.6; word-break: break-all;
  user-select: all;
}
/* The window that says a subscription landed (option 1 of five, picked
   2026-09-16): a tick in its own light, the date, a receipt, one button. */
.paidwin .pad { gap: 12px; text-align: center; }
.paidwin h2 { font-size: 20px; font-weight: 700; margin: 0; line-height: 1.4; }
.paidwin p { margin: 0; line-height: 1.8; }
.paidmark { width: 64px; height: 64px; border-radius: 50%; margin: 6px auto 0;
  background: radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--up) 34%, transparent), transparent 72%);
  display: grid; place-items: center; }
.paidmark i { width: 40px; height: 40px; border-radius: 50%; background: var(--up); color: #fff;
  display: grid; place-items: center; font-style: normal; font-size: 22px; font-weight: 700;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--up) 18%, transparent), 0 8px 22px -8px var(--up); }
.paidrcpt { border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); text-align: start; }
.paidrcpt div { display: flex; justify-content: space-between; gap: 12px; padding: 9px 12px; font-size: 13.5px; }
.paidrcpt div + div { border-top: 1px solid var(--line-soft); }
.paidrcpt span:first-child { color: var(--dim); flex: 0 0 auto; }
.paidrcpt b { font-weight: 600; text-align: end; }
.paidwin .primary { padding: 11px 16px; border-radius: 8px; font-size: 14.5px; }
.paidways { display: flex; align-items: center; gap: 10px; text-align: start;
  padding: 10px 12px; border-radius: 8px; font-size: 13px; color: var(--dim);
  background: color-mix(in srgb, var(--gold) 12%, var(--panel-2)); border: 1px solid color-mix(in srgb, var(--gold) 35%, var(--line)); }
.paidways span { flex: 1; line-height: 1.6; }
.paidways .chip { flex: 0 0 auto; }

/* Pressed to copy. The hand cursor and a lift on hover say so before the
   sentence under it does. */
.paycode.tap { cursor: pointer; transition: background .12s, border-style .12s;
  /* The page is `user-select: none`; the road without a clipboard selects
     the box's text and asks for one press, and there was nothing to
     select on the card and the amount (the adversary, 2026-09-17). */
  user-select: all; }
.paycode.tap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.paycode.tap:hover { background: color-mix(in srgb, var(--accent) 10%, var(--bg)); border-style: solid; }
.paycode.tap:active { transform: translateY(1px); }
.payqr {
  display: flex; justify-content: center; margin: 12px 0 4px;
  background: #fff; border-radius: 10px; padding: 10px;
  width: fit-content; margin-inline: auto;
}
.payqr svg { display: block; width: 148px; height: 148px; }

/* ---- the web version ----
   `html.web` is set in index.html when the page is served by the web app
   (window.RAHYAB_WEB). What is hidden here is what only means something on
   the desktop: the updater, folders on the person's disk, other programs on
   their computer, downloading history, the MetaTrader export (a bulk copy of
   the archive, which the web version must not hand out), and Google sign-in
   until it arrives as a redirect. `!important` because several of these are
   shown by the code with `classList.remove('hidden')` or `style.display`,
   and on the web nothing is to bring them back. */
html.web #btnUpdate,
html.web #update,
html.web #verCheck,
html.web #verSay,
html.web [data-foldercard],
html.web #indReload,
html.web #cardShow,
html.web #cardTg,
html.web #cardNoTg,
html.web [data-shotfolder],
html.web #btnDownloadHere,
html.web #dlPanel,
html.web #getdata,
html.web #stopped,
html.web #lab .tab[data-tab="mt5"],
html.web #lab .labpane[data-tab="mt5"],
html.web #googleBox,
html.web #googleRow,
html.web #googleWait,
html.web #googleName,
html.web .supsay > b,
html.web .desk,
html.web #supHere { display: none !important; }
/* The one sentence that differs rather than disappears: the desktop's copy
   (`.desk`) and the web's (`.webonly`) sit side by side, one shown. */
html:not(.web) .webonly { display: none !important; }

/* ==========================================================================
   A window narrower than the chart's columns (the web on a phone)
   ==========================================================================
   The drawing tools, the order column and the rail are fixed widths, and
   below about 480 pixels they left the chart nothing: 320 wide gave it 0,
   360 gave it 2 (the area-8 review, 2026-09-29, finding 11). The desktop's
   floor is 900 and never gets here. Below 600 the order column moves under
   the chart, full width, and the page scrolls down to it: nothing is taken
   away, and the chart keeps the width of the window less its two strips. */
@media (max-width: 600px) {
  main { flex-wrap: wrap; overflow-y: auto; align-content: flex-start; }
  main > .tools { order: 1; }
  main > #center { order: 2; flex: 1 1 0; min-width: 120px; height: 62vh; min-height: 260px; }
  main > #rail { order: 3; height: 62vh; min-height: 260px; }
  main > #side { order: 4; flex: 1 0 100%; width: 100%; height: auto; min-height: 420px;
    border-inline-start: 0; border-top: 1px solid var(--line); }
}
/* And the windows, at the same widths: a working width, and the page scrolls
 * to the rest. Squeezed to the screen they fell apart - the market picker's
 * title one letter a line at 320, the journal's filters 7 to 22 pixels wide
 * at 500, the Lab's right column 34 wide at 360 (the area-13 adversary, F13).
 * A phone is not what this is made for (WEB-VERSION.md); a window that can
 * be read and scrolled is the least it owes one. The sign-in drawer keeps
 * its own shape at its own edge. */
@media (max-width: 640px) {
  .modal:not(#welcome) { overflow: auto; align-items: flex-start; justify-content: flex-start; }
  .modal:not(#welcome) > .sheet { flex: 0 0 auto; margin: auto; min-width: 300px; }
  .modal:not(#welcome) > .sheet.wide,
  .modal:not(#welcome) > .sheet.huge { min-width: 600px; }
  /* And its header no wider than the screen, on the side the window opens
   * on: at the end of a row wider than the screen the ✕ was off the edge in
   * six windows, and a search box focused there scrolled the window away
   * from it (the round-4 area-13 review, F7). */
  .modal:not(#welcome) > .sheet:is(.wide, .huge) > header { max-width: calc(100vw - 16px); }
  .modal:not(#welcome) > .sheet:is(.wide, .huge) > header > .x { flex-shrink: 0; }
}
