/* ════════════════════════════════════════════════════════════
   journal.css — the trading journal application shell

   Deliberately NOT built on style.css. The rest of this site is a
   marketing site: a wide header, a footer full of links, a hero.
   The journal is an application someone opens on a phone, standing
   up, thirty seconds after closing a position. It shares a domain
   with the marketing site and nothing else, and mixing the two
   stylesheets would mean every future journal screen fighting a
   layout built for a landing page.

   ── The tokens are the ones that were designed and approved ──
   Colour values below are lifted unchanged from the screen model.
   The rule they encode is the design thesis of the whole
   application: COLOUR MEANS RULE ADHERENCE, NEVER PROFIT. A losing
   trade taken exactly to plan is green. A winning trade taken on a
   whim is red. --good and --bad refer to behaviour; there is no
   token for a P&L sign, because P&L is rendered neutral on purpose.

   ── Dark by default, light by choice ─────────────────────────
   Two palettes, selected by data-theme on <html>, which PHP writes
   from the reader's saved choice before the page is sent. The
   default is dark: this is opened at 2am more often than at noon,
   the screen model was designed dark-first, and the rest of the site
   is served dark, so a journal that opened light would be the only
   page on the domain that did.

   The device's own preference is not consulted — see
   Domains\Journal\JournalTheme. Anyone who wants it has it in one
   press of the toggle, and then it is remembered.
   ════════════════════════════════════════════════════════════ */

:root {
  --bg:#0B1011; --panel:#141A1C; --panel2:#1A2123; --panel3:#212A2C;
  --ink:#E8EEEC; --ink2:#AFBDBA; --ink3:#7C8C8A;
  --line:#283234; --line2:#1F2729;
  --brand:#4FC2AC; --brand-soft:#11302B; --on-brand:#0B1011;
  --good:#4FBE84; --good-soft:#13301F; --good-line:#2C6B45;
  --bad:#FF6FB1;  --bad-soft:#3A1827;  --bad-line:#8A3A62;   /* a bright pink: red sat too close to the orange of a loss */
  --warn:#D9B04E; --warn-soft:#2B2515;
  /* The two halves of a review. Amber and violet on purpose: green
     and red already mean rule adherence, and the brand green already
     means "this one" — a phase is none of those things, and a reader
     who has learned what green means here must not meet it again
     meaning something else. */
  --before:#D9A441; --before-soft:#2A2214; --before-line:#5E4C22;
  --after:#A892F0;  --after-soft:#221E38;  --after-line:#453A72;
  --sh:0 1px 2px rgba(0,0,0,.5), 0 10px 30px -22px rgba(0,0,0,.9);

  --rail:212px;   /* desktop sidebar */
  --bar:56px;     /* phone tab bar   */

  /* ── What the BROWSER draws, as opposed to what we draw ──────
     The date and time picker is the browser's own window: its
     calendar grid, its month arrows, its scrollbars. None of it can
     be styled, and without this line it is drawn in the OPERATING
     SYSTEM's scheme — so a white calendar popped out of a dark form
     and looked like a different application had opened.
     This is the one declaration that themes it, and it does the
     same for scrollbars, the focus ring and the time spinners. */
  color-scheme: dark;
}

/* The device's preference is deliberately NOT consulted.
   PHP writes data-theme on <html> from the reader's saved choice,
   defaulting to dark — see Domains\Journal\JournalTheme for why.
   A @media (prefers-color-scheme) block used to sit here; with the
   attribute always present it could never match, and dead code that
   looks like a rule is worse than no rule, because the next person
   to change the palette edits both and only one of them counts. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg:#EEF0EF; --panel:#FFFFFF; --panel2:#F5F7F6; --panel3:#EAEEEC;
  --ink:#0F1618; --ink2:#42504F; --ink3:#6E7D7B;
  --line:#D9DFDC; --line2:#E8ECEA;
  --brand:#0A5E51; --brand-soft:#DDEBE7; --on-brand:#FFFFFF;
  --good:#1C7A4A; --good-soft:#DDEEE2; --good-line:#8CC0A3;
  --bad:#B01E6A;  --bad-soft:#FAE0EC;  --bad-line:#E09BBE;
  --warn:#8A6208; --warn-soft:#F6EEDB;
  --before:#8A6208; --before-soft:#FAF1DC; --before-line:#E0CB9A;
  --after:#5B42B5;  --after-soft:#EDEAFA;  --after-line:#C6BCEC;
  --sh:0 1px 2px rgba(15,22,24,.05), 0 10px 30px -22px rgba(15,22,24,.3);
}

/* ── Which colours mean what — Settings → Colours ─────────────
   "classic" (the default, and what a page without the attribute gets):
   green and red are profit and loss, as most traders expect, and the
   plan — every place that was green/red for rules, verdicts and the
   matrix — is blue and orange. "neutral" is the other way round: green
   and red for the plan, money in blue and orange (journal-dash.css),
   so a profitable trade is never mistaken for a good one.
   Only the tokens change; nothing below this block knows which pairing
   is on. The blue and orange are the dashboard's own pair, the one that
   stays apart under every kind of colour vision; green and red do not,
   which is why a figure is never told by colour alone (it has its
   sign, its side of zero, its words). */
:root:not([data-colors="neutral"]) {
  --good:#4DA3FF; --good-soft:#12263F; --good-line:#2B5A94;
  --bad:#FFB627;  --bad-soft:#33270A;  --bad-line:#8A6A12;   /* a bright amber: orange sat too close to the red of a loss */
  --gain:#4FBE84; --loss:#EE6B5F; --dir-long:#4FBE84; --dir-short:#EE6B5F;
}
/* Long and short follow the money pair of the colour setting (--dir-*): green and red, or — in "neutral" — blue and orange. */
:root[data-colors="neutral"] { --dir-long: #3987e5; --dir-short: #d95926; }
:root[data-theme="light"][data-colors="neutral"] { --dir-long: #2a78d6; --dir-short: #eb6834; }
:root[data-theme="light"]:not([data-colors="neutral"]) {
  --good:#1F63B8; --good-soft:#DCE8F7; --good-line:#8DB1E0;
  --bad:#9A6500;  --bad-soft:#FBEFCF;  --bad-line:#E0BE6B;
  --gain:#1C7A4A; --loss:#BF3328; --dir-long:#1C7A4A; --dir-short:#BF3328;
}
/* A figure that is a profit or a loss: coloured by its sign — except in "neutral", where it stays plain. */
:root:not([data-colors="neutral"]) .jr-gain, :root:not([data-colors="neutral"]) .jr-fact.jr-gain .v { color: var(--gain); }
:root:not([data-colors="neutral"]) .jr-loss, :root:not([data-colors="neutral"]) .jr-fact.jr-loss .v { color: var(--loss); }

/* The sample under the choice in Settings: both pairs, in the colours of the pairing being shown. */
.jr-colors-demo { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 2px; font-size: 12.5px; font-weight: 600; }
.jr-colors-demo span { padding: 5px 10px; border-radius: 999px; border: 1px solid var(--line); background: var(--panel2); }
.jr-colors-demo .d-gain { color: var(--gain, #3987e5); } .jr-colors-demo .d-loss { color: var(--loss, #d95926); }
.jr-colors-demo .d-ok { color: var(--good); background: var(--good-soft); border-color: var(--good-line); }
.jr-colors-demo .d-no { color: var(--bad);  background: var(--bad-soft);  border-color: var(--bad-line); }
:root[data-colors="neutral"] .jr-colors-demo .d-gain { color: #3987e5; } :root[data-colors="neutral"] .jr-colors-demo .d-loss { color: #d95926; }
:root[data-theme="light"][data-colors="neutral"] .jr-colors-demo .d-gain { color: #2a78d6; } :root[data-theme="light"][data-colors="neutral"] .jr-colors-demo .d-loss { color: #eb6834; }
.jr-seg-wide { flex-wrap: wrap; }

/* ── base ────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* The `hidden` attribute must actually hide.
   ────────────────────────────────────────────────────────────
   The browser's own stylesheet says [hidden] { display: none },
   and ANY author rule that sets display beats it — author styles
   outrank the user-agent sheet entirely, whatever the specificity.
   So the moment a class that sets `display: flex` was put on an
   element the JavaScript hides with `hidden`, the element kept
   rendering.

   It shipped: the "what you picked" line under the instrument field
   is a flex row, and it drew an empty grey pill under every search
   before anything had been chosen. Spotted on a real phone, on the
   real site.

   !important because this rule has to win against a class rule that
   is trying to set display, which is the entire situation it exists
   for. An element that wants to be hidden and styled cannot express
   that any other way. */
[hidden] { display: none !important; }

/* Overscroll off, and the page colour on the root as well as the body: pulling the page down at
   the top used to slide it away from the top bar and rail, leaving a blank band above them in the
   canvas colour. */
html { -webkit-text-size-adjust: 100%; background: var(--bg); overscroll-behavior-y: none; }

body.jr {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  /* The tab bar is fixed to the bottom on a phone, so the last
     element of every screen needs somewhere to end. safe-area-inset
     keeps it clear of the home indicator on a notched iPhone, where
     a plain 56px would put the last row under the gesture bar. */
  padding-bottom: calc(var(--bar) + env(safe-area-inset-bottom, 0px));
  -webkit-font-smoothing: antialiased;
}

/* Numbers are read in columns and compared down the page, so they
   are monospaced and tabular everywhere. A price that shifts left
   and right as digits change is a price you have to read twice. */
.mono, .num { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
              font-variant-numeric: tabular-nums; }

a { color: var(--brand); }

/* Visible focus, always. This gets used one-handed on a phone and
   with a keyboard at a desk, and the default outline disappears
   against --panel. */
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 6px; }

/* ── shell ───────────────────────────────────────────────── */

.jr-shell { min-height: 100vh; }

.jr-main {
  max-width: 760px;
  margin: 0 auto;
  /* 16px gutter on a phone, never edge-to-edge text. */
  padding: 18px 16px 32px;
}

/* ── top bar ─────────────────────────────────────────────── */

.jr-top {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border-bottom: 1px solid var(--line2);
  backdrop-filter: blur(10px);
}
/* color-mix is recent. Without it the bar would be transparent and
   content would scroll visibly under the title, so the opaque
   fallback comes first and is overridden above where supported. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .jr-top { background: var(--bg); }
}

.jr-brand { display: flex; align-items: center; gap: 9px; font-weight: 700; letter-spacing: -.01em; white-space: nowrap; flex: 0 0 auto; }
.jr-brand i {
  display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: 8px;
  background: var(--brand); color: var(--on-brand);
  font-style: normal; font-weight: 700; font-size: 14px;
}
.jr-brand i svg { display: block; }
.jr-top .sp { margin-left: auto; }

/* Go to a trade by its number: a small field in the bar. The # is drawn, not typed, so 36 and #36 both work. */
.jr-go { display: flex; align-items: center; flex: 0 1 auto; min-width: 0; height: 30px; padding: 0 9px; gap: 3px;
  background: var(--panel2); border: 1px solid var(--line); border-radius: 8px; }
.jr-go:focus-within { border-color: var(--brand); }
.jr-go .hash { color: var(--ink3); font-size: 13px; font-weight: 600; }
.jr-go input { width: 78px; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 13px; padding: 0; }
.jr-go input::placeholder { color: var(--ink3); }
/* A phone's bar has no room for a field: it is a "#" button. Tapping it (the input lies over it, invisible, so the
   keyboard opens on the tap) lifts the field over the whole bar; leaving it puts the bar back. */
@media (max-width: 560px) {
  /* The bar was already full with the Check-in button showing; the field takes 30px, which comes from the gaps. */
  .jr-top { gap: 8px; }
  .jr-top .sp { display: none; }
  .jr-go { margin-left: auto; position: relative; width: 30px; padding: 0; justify-content: center; flex: 0 0 auto; }
  .jr-go input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; font-size: 16px; }
  .jr-go:focus-within { position: absolute; left: 10px; right: 10px; top: 50%; transform: translateY(-50%); z-index: 5;
    width: auto; height: 38px; padding: 0 12px; justify-content: flex-start; background: var(--panel); border-color: var(--brand); }
  .jr-go:focus-within input { position: static; opacity: 1; flex: 1; height: auto; }
}

/* The same control as the marketing nav, sized for a top bar that
   also has to fit a brand and an email on a 390px screen. Label
   hidden below 380px — the icon and the title attribute still say
   what it does, and a wrapped top bar is worse than a terse one. */
.jr-theme {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 12px; font-weight: 600;
  color: var(--ink3); background: none; border: 0;
  padding: 8px; margin: -8px 0 -8px 4px; border-radius: 8px;
  cursor: pointer; white-space: nowrap;
}
.jr-theme:hover { color: var(--ink); background: var(--panel2); }
.jr-theme .mk { font-size: 15px; line-height: 1; }
@media (max-width: 379px) { .jr-theme [data-theme-label] { display: none; } }
.jr-top .who { font-size: 12px; color: var(--ink3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The way to settings, icon-only in both directions. It has no text
   label because the gear is one of the few icons that genuinely needs
   none, and because the bar it sits in already has a brand, an email
   and a theme control to fit on a 390px screen.

   44px of touch target, from a 15px glyph plus padding: below that a
   thumb misses it and hits the theme toggle beside it instead. */
.jr-gear {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px; margin: -8px -4px -8px 0;
  border-radius: 8px;
  font-size: 15px; line-height: 1; color: var(--ink3);
  text-decoration: none;
}
.jr-gear:hover { color: var(--ink); background: var(--panel2); }
.jr-gear[aria-current] { color: var(--brand); background: var(--panel2); }

/* ── panels ──────────────────────────────────────────────── */

.jr-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--sh);
  padding: 18px;
  margin-bottom: 14px;
}
.jr-card h2 { font-size: 16px; letter-spacing: -.01em; margin-bottom: 6px; }
.jr-card p  { color: var(--ink2); font-size: 14px; }
.jr-card p + p { margin-top: 10px; }

.jr-eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink3); margin-bottom: 10px;
}

/* The eyebrow with something at the far end of it — the way back out
   of a trade. A flex row rather than an absolute corner: the eyebrow
   is a different length on every screen, and a positioned link lands
   on top of it at the one width nobody tested. */
.jr-cardtop { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.jr-cardtop .jr-eyebrow { margin-bottom: 10px; white-space: nowrap; }
.jr-closes { white-space: nowrap; }
.jr-inline-form { display: inline; margin: 0; }
@media (max-width: 600px) {
  /* The eyebrow and the way back share the first line; the one action is a full-width
     button under them, so nothing wraps into the title. */
  .jr-cardtop { flex-wrap: wrap; row-gap: 2px; margin-bottom: 4px; }
  .jr-cardtop > .jr-cardacts { display: contents; }
  .jr-cardtop .jr-eyebrow { order: 1; margin-bottom: 4px; }
  .jr-cardtop .jr-cardacts .jr-back { order: 2; margin-left: auto; }
  .jr-cardtop .jr-cardacts .jr-inline-form, .jr-cardtop .jr-cardacts > .jr-btn, .jr-cardtop .jr-cardacts > .jr-closes { order: 3; flex: 1 1 100%; margin-bottom: 6px; }
  .jr-cardtop .jr-cardacts .jr-inline-form .jr-btn { width: 100%; min-height: 40px; }
  .jr-cardtop .jr-cardacts > .jr-btn { text-align: center; display: inline-flex; align-items: center; justify-content: center; min-height: 40px; }
  .jr-cardtop .jr-cardacts .jr-inline-form .jr-link-btn { display: block; width: 100%; text-align: left; padding: 6px 0; }
}
.jr-back {
  flex: none;
  font-size: 13px; color: var(--ink2); text-decoration: none;
  padding: 4px 2px;          /* a thumb's worth of target, no box */
}
.jr-back:hover { color: var(--brand); text-decoration: underline; }

/* An empty screen states what it is for and what fills it. A blank
   panel and a broken panel look identical, and the difference is
   the only thing the reader wants to know. */
.jr-empty { text-align: center; padding: 34px 18px; color: var(--ink3); }
.jr-empty .mk { font-size: 26px; color: var(--line); margin-bottom: 10px; }
.jr-empty strong { display: block; color: var(--ink2); font-weight: 600; margin-bottom: 4px; }

/* ── buttons ─────────────────────────────────────────────── */

.jr-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  /* 44px tall: the minimum a thumb hits reliably. This is an app
     used one-handed while something is still running. */
  min-height: 44px; padding: 0 18px;
  border-radius: 11px; border: 1px solid var(--line);
  background: var(--panel2); color: var(--ink);
  font: inherit; font-weight: 600; font-size: 14px;
  cursor: pointer; text-decoration: none; white-space: nowrap;
}
.jr-btn:hover { border-color: var(--ink3); }
.jr-btn.pri { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.jr-btn.pri:hover { filter: brightness(1.06); }

/* ── nav ─────────────────────────────────────────────────── */
/*
   One markup, two shapes. On a phone it is a fixed bottom bar,
   because that is where a thumb is. From 860px up it becomes a left
   rail, because a mouse is already at the edge of the window and
   vertical space is what a trade list wants.
*/
.jr-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex;
  height: calc(var(--bar) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--panel);
  border-top: 1px solid var(--line);
}
.jr-nav a {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  color: var(--ink3); text-decoration: none;
  font-size: 10px; font-weight: 600; letter-spacing: .01em;
}
.jr-nav a .ic { font-size: 17px; line-height: 1; position: relative; }
.jr-nav a.on { color: var(--brand); }
/* Disabled tabs are shown, not hidden. A nav that grows between
   releases teaches people to re-scan it every time; one that is
   complete and greyed teaches them where things will be. */
.jr-nav a[aria-disabled="true"] { opacity: .38; pointer-events: none; }

@media (min-width: 860px) {
  body.jr { padding-bottom: 0; }

  .jr-nav {
    top: 0; right: auto; bottom: 0;
    width: var(--rail); height: 100vh; padding: 14px 10px;
    flex-direction: column; gap: 2px;
    border-top: 0; border-right: 1px solid var(--line);
  }
  .jr-nav a {
    flex: 0 0 auto; flex-direction: row; justify-content: flex-start; gap: 11px;
    height: 40px; padding: 0 12px; border-radius: 10px; font-size: 14px;
  }
  .jr-nav a .ic { font-size: 15px; width: 18px; text-align: center; }
  .jr-nav a.on { background: var(--brand-soft); }
  .jr-nav a:not(.on):hover { background: var(--panel2); }

  .jr-shell { margin-left: var(--rail); }
  .jr-top   { padding-left: 24px; padding-right: 24px; }
  .jr-main  { padding: 26px 24px 48px; }
}

/* The rail carries the product name at desktop width; the top bar
   carries it on a phone. Showing both would say "Journal" twice on
   one screen. */
.jr-nav .jr-brand { display: none; }
@media (min-width: 860px) {
  .jr-nav .jr-brand { display: flex; margin: 2px 6px 16px; }
  .jr-top  .jr-brand { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ════════════════════════════════════════════════════════════
   Forms, lists and readouts — the Log screen and everything it
   taught the rest of the application.

   The governing constraint is the same one the whole slice is
   measured by: one hand, a phone, thirty seconds, in the minute
   after entering a trade. Every size below follows from that —
   inputs are 48px so a thumb hits them, the font is 16px because
   anything smaller makes iOS zoom the page on focus, and the
   numeric fields are monospaced because they are read in a column
   and compared down the page.
   ════════════════════════════════════════════════════════════ */

.jr-label {
  display: block;
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
  color: var(--ink2); margin: 16px 0 6px;
}
.jr-label .opt { font-weight: 400; color: var(--ink3); letter-spacing: 0; margin-left: 8px; }
.jr-card > .jr-label:first-of-type { margin-top: 0; }

.jr-input {
  display: block; width: 100%;
  min-height: 48px; padding: 11px 13px;
  background: var(--panel2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 11px;
  /* 16px exactly. Below it, iOS zooms the viewport on focus and the
     form jumps sideways mid-entry — on the one screen that has to be
     fast. */
  font: inherit; font-size: 16px;
}
.jr-input:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand); }

/* ── the date and time field ─────────────────────────────────
   The popup belongs to the browser and follows color-scheme above.
   What is left is the field itself, which by default renders its
   segments in the platform's own spacing and its calendar button as
   a small grey glyph that reads as disabled.

   Digits get tabular figures so the field does not twitch sideways
   as the minutes change, and the trigger gets a real tap target
   rather than the 12px the platform gives it. */
.jr-input[type="datetime-local"],
.jr-input[type="date"] {
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
  /* Safari ignores min-height on these and collapses them to the
     text, which left the only short field on the form. */
  -webkit-appearance: none; appearance: none;
}
.jr-input[type="datetime-local"]::-webkit-calendar-picker-indicator,
.jr-input[type="date"]::-webkit-calendar-picker-indicator {
  /* The glyph is a fixed dark bitmap. invert() is what turns it into
     the pale one the dark palette needs; the light theme puts it
     back below. */
  filter: invert(1) opacity(.55);
  cursor: pointer;
  padding: 6px; margin-right: -2px;
  border-radius: 6px;
}
.jr-input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover,
.jr-input[type="date"]::-webkit-calendar-picker-indicator:hover {
  filter: invert(1) opacity(1);
  background: var(--panel3);
}
:root[data-theme="light"] .jr-input[type="datetime-local"]::-webkit-calendar-picker-indicator,
:root[data-theme="light"] .jr-input[type="date"]::-webkit-calendar-picker-indicator {
  filter: opacity(.5);
}
:root[data-theme="light"] .jr-input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover,
:root[data-theme="light"] .jr-input[type="date"]::-webkit-calendar-picker-indicator:hover {
  filter: opacity(1);
}
/* An empty field shows dd/mm/yyyy --:-- --, which is the browser's
   placeholder and should read like one rather than like a value. */
.jr-input[type="datetime-local"]:not(:focus)::-webkit-datetime-edit-text,
.jr-input[type="datetime-local"]:invalid::-webkit-datetime-edit {
  color: var(--ink3);
}

/* Focusing a field must not park it under the sticky header.
   The browser scrolls a focused input to the top of the viewport,
   which put Entry — the first field anyone taps — behind the bar
   with its label completely hidden. scroll-margin-top reserves the
   bar's height plus a little air, so the field lands just below it.
   Found by focusing each input in turn and measuring; it is
   invisible in a screenshot because a screenshot does not tap. */
.jr-input, .jr-seg-opt { scroll-margin-top: 68px; }
.jr-input::placeholder { color: var(--ink3); }
.jr-input.bad { border-color: var(--bad); }

.jr-textarea { min-height: 104px; resize: vertical; line-height: 1.55; }

.jr-err { color: var(--bad); font-size: 13px; margin-top: 6px; }

/* Two columns from 380px. Entry/size and stop/target are read as
   pairs, and pairing them halves the vertical travel on a phone. */
.jr-grid { display: grid; grid-template-columns: 1fr; gap: 0 12px; }
@media (min-width: 380px) { .jr-grid { grid-template-columns: 1fr 1fr; } }

/* ── direction ───────────────────────────────────────────────
   A radio group wearing two large buttons. Real radios underneath,
   so it is keyboard-operable and announces correctly; the input is
   hidden with opacity rather than display:none, which would take it
   out of the tab order entirely. */
.jr-seg { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.jr-seg-opt { position: relative; }
.jr-seg-opt input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.jr-seg-opt span {
  display: flex; align-items: center; justify-content: center;
  min-height: 48px; border-radius: 11px;
  background: var(--panel2); border: 1px solid var(--line);
  font-weight: 600; color: var(--ink2);
}
/* Long green, short red.
   Both were the brand teal, which made the two choices look
   interchangeable — you had to read the word to know which was
   selected. This is the ONE place in the application where colour
   means direction rather than rule adherence, and it is safe here
   precisely because direction is not an outcome: a red Short says
   "you are short", never "this went badly". */
.jr-seg-opt input:checked + span.long {
  background: var(--good-soft); border-color: var(--good-line); color: var(--good);
}
.jr-seg-opt input:checked + span.short {
  background: var(--bad-soft); border-color: var(--bad-line); color: var(--bad);
}
/* A selected segment with no direction to express — the theme pair.
   Without this the two options look identical when one is chosen,
   because the rules above only paint .long and .short. Brand teal,
   which is what "selected" means everywhere else in this stylesheet. */
.jr-seg-opt input:checked + span {
  background: var(--brand-soft); border-color: var(--brand); color: var(--brand);
}
.jr-seg-opt input:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ── a list of mutually exclusive choices, each with a reason ─
   Not a <select>: these three options differ in what they MEAN for
   the data, not just in their labels, and a dropdown hides the
   explanation behind the one thing you have to open to read it.
   Stacked rows, each carrying its own consequence in small text. */
.jr-radios { display: grid; gap: 8px; }
.jr-radio { position: relative; display: block; cursor: pointer; }
.jr-radio input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.jr-radio > span {
  display: block; padding: 12px 13px;
  background: var(--panel2); border: 1px solid var(--line); border-radius: 11px;
}
.jr-radio b  { display: block; font-size: 14px; font-weight: 600; color: var(--ink2); }
.jr-radio em { display: block; margin-top: 3px; font-style: normal; font-size: 12px; color: var(--ink3); line-height: 1.6; }
.jr-radio input:checked + span            { border-color: var(--brand); background: var(--brand-soft); }
.jr-radio input:checked + span b          { color: var(--brand); }
.jr-radio input:focus-visible + span      { outline: 2px solid var(--brand); outline-offset: 2px; }

/* A unit welded to its field, so "6" cannot be read as six minutes
   and "0.02" cannot be read as two percent. The suffix is decorative
   and outside the input, because a unit typed INTO the field is a
   value the parser then has to strip back out. */
.jr-suffix { position: relative; display: block; }
.jr-suffix .jr-input { width: 100%; padding-right: 62px; }
.jr-suffix > span {
  position: absolute; right: 13px; top: 50%; transform: translateY(-50%);
  font-size: 13px; color: var(--ink3); pointer-events: none;
}

/* A button that reads as a link, for an offer inside a sentence —
   "this device says Europe/Paris. Use that". A real <button>, because
   it changes a field rather than going anywhere. */
.jr-link {
  font: inherit; font-size: inherit; font-weight: 600;
  color: var(--brand); background: none; border: 0; padding: 0;
  text-decoration: underline; cursor: pointer;
}

/* ── symbol quick-pick ───────────────────────────────────────
   Filled from the trader's own history. A new account shows none. */
.jr-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.jr-chip {
  font: inherit; font-size: 13px; font-weight: 600;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  padding: 7px 11px; border-radius: 9px;
  background: var(--panel3); color: var(--ink2);
  border: 1px solid var(--line); cursor: pointer;
}
.jr-chip:hover { border-color: var(--brand); color: var(--brand); }

/* ── running figures ─────────────────────────────────────────
   Risk is the number that decides whether this trade is sane, so it
   sits inside the form rather than after it — visible without
   scrolling away from the fields feeding it. */
.jr-readout {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  margin-top: 16px; background: var(--line2);
  border: 1px solid var(--line); border-radius: 11px; overflow: hidden;
}
@media (min-width: 420px) { .jr-readout { grid-template-columns: repeat(4, 1fr); } }
.jr-readout > div { background: var(--panel2); padding: 10px 12px; }
.jr-readout .k { display: block; font-size: 11px; color: var(--ink3); }
.jr-readout .v { display: block; font-size: 15px; font-weight: 600; margin-top: 2px; }

/* A label that follows a field rather than opening a card needs its own air. */
.jr-label + .jr-input { margin-top: 2px; }
.jr-textarea + .jr-label, .jr-input + .jr-label { margin-top: 18px; }

.jr-note { font-size: 12px; color: var(--ink3); line-height: 1.7; margin-top: 10px; }
.jr-body { color: var(--ink); line-height: 1.7; white-space: pre-wrap; }

.jr-submit { width: 100%; min-height: 52px; font-size: 16px; margin-bottom: 8px; }

/* ── trade list ──────────────────────────────────────────────
   A whole-row link. The tap target is the row, not the symbol —
   aiming at a word on a phone is how you miss. */
.jr-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 4px; text-decoration: none; color: inherit;
  border-bottom: 1px solid var(--line2);
}
.jr-row:last-child { border-bottom: 0; }
.jr-row:hover { background: var(--panel2); }
.jr-dir {
  display: grid; place-items: center; flex: 0 0 30px;
  width: 30px; height: 30px; border-radius: 9px;
  font-size: 13px; font-weight: 700;
}
/* Direction, NOT outcome. Nothing in this application colours by
   profit — long and short are facts, and these two greens and reds
   are the only place a colour means something other than rule
   adherence, which is why they are muted rather than the real
   --good / --bad tokens. */
.jr-dir.long  { background: color-mix(in srgb, var(--dir-long, #4FBE84) 18%, transparent);  color: var(--dir-long, #4FBE84); }
.jr-dir.short { background: color-mix(in srgb, var(--dir-short, #EE6B5F) 18%, transparent); color: var(--dir-short, #EE6B5F); }
.jr-row-main { flex: 1; min-width: 0; }
.jr-row-sym  { display: block; font-weight: 600; font-size: 15px; }
.jr-row-sub  { display: block; font-size: 11px; color: var(--ink3); margin-top: 1px; white-space: nowrap;
               overflow: hidden; text-overflow: ellipsis; }
.jr-row-sub .jr-venue-mark { width: 14px; height: 14px; margin-right: 5px; vertical-align: -3px; }
/* A phone: the mark says the exchange, the name would only push the
   date off the line; the tag sits on the symbol's line, small. */
.jr-when-short { display: none; }
@media (max-width: 600px) {
  .jr-row { gap: 8px; padding: 10px 2px; }
  .jr-row-venue, .jr-when-long { display: none; }
  .jr-row-sub { font-size: 12px; }
  .jr-row-sub .jr-venue-mark { width: 17px; height: 17px; margin-right: 6px; vertical-align: -4px; }
  .jr-when-short { display: inline; }
  .jr-row-sym { font-size: 14px; display: flex; align-items: center; gap: 6px; min-width: 0; }
  .jr-row-sym .jr-sym-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .jr-row-sym .jr-src { margin-left: 0; flex: none; }
  /* The figure keeps its width; it was shrinking and printing over
     the ticker. The ticker is the thing that can lose letters. */
  .jr-c.risk { font-size: 12.5px; flex: 0 0 auto; white-space: nowrap; margin-left: 6px; }
  .jr-c.state { margin-left: 2px; }
}
/* The narrowest phones: the origin tag is its glyph alone. */
@media (max-width: 400px) {
  .jr-row-sym .jr-src { padding: 0 4px; font-size: 0; gap: 0; }
  .jr-row-sym .jr-src::before { font-size: 10px; }
}
.jr-row-end  { text-align: right; flex: 0 0 auto; font-size: 14px; }

/* ── open, at a glance ─────────────────────────────────────
   It used to be the word "open" in grey, under a number, beside the
   word "closed" in the same grey — so a list of twenty trades read
   as one block. These are the rows with money at risk right now.

   The brand colour, which is the one colour here allowed to mean
   "this one" rather than "this was good". Nothing in this list is
   coloured by profit. */
.jr-live {
  display: inline-block; padding: 2px 7px; border-radius: 999px;
  background: var(--brand-soft); color: var(--brand);
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
}
.jr-done { font-size: 11px; color: var(--ink3); }
/* A tint and a rail down the left, so the block of open ones at the
   top of the list is one shape rather than twenty separate rows. */
.jr-row.live {
  background: color-mix(in srgb, var(--brand) 5%, transparent);
  box-shadow: inset 2px 0 0 var(--brand);
}

/* The desktop columns, and the heading over them. A phone has room
   for the ticker, the direction, one number and the state — the rest
   of the columns are hidden and the two stacked lines above carry
   the exchange and the time instead.

   The state is NOT one of the hidden ones. It was the thing that
   could not be seen in the list, which is where this started. */
.jr-c, .jr-head { display: none; }
.jr-c.risk  { display: block; margin-left: auto; text-align: right;
              font-size: 13.5px; font-family: var(--mono, ui-monospace, monospace); }
.jr-c.state { display: block; flex: 0 0 auto; }

/* ── trade facts ─────────────────────────────────────────── */
.jr-facts {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  margin-top: 14px; background: var(--line2);
  border: 1px solid var(--line); border-radius: 11px; overflow: hidden;
}
@media (min-width: 480px) { .jr-facts { grid-template-columns: repeat(4, 1fr); } }
.jr-fact { background: var(--panel2); padding: 10px 12px; }
/* ── the one cell that is allowed a colour ─────────────────
   Rule adherence is the only thing colour means in this journal, and
   this is the cell that carries it: green for followed, red for
   broken, whichever way the money went. A loss taken exactly to plan
   is green here and that is the entire point of the screen. */
.jr-fact.kept   { background: var(--good-soft); }
.jr-fact.kept   .v { color: var(--good); }
.jr-fact.broken { background: var(--bad-soft); }
.jr-fact.broken .v { color: var(--bad); }
.jr-fact.kept .k, .jr-fact.broken .k { color: inherit; opacity: .7; }

.jr-fact .k { display: block; font-size: 11px; color: var(--ink3); }
.jr-fact .v { display: block; font-size: 15px; font-weight: 600; margin-top: 2px; }

/* ════════════════════════════════════════════════════════════
   A position, step by step.

   Not a list of fills: a sequence of decisions. Adding to a position
   and taking a third of it off are different things from each other
   and both different from opening it, and the order they happened in
   is the content — "let the last half ride" only means anything
   against what was still on.

   ── Why each row is its own grid ─────────────────────────────

   It was one grid with display:contents on the <li>, so that the
   columns would line up down the page. Two things went wrong with
   that and both were visible rather than theoretical: a border on
   each cell drew a line in segments with gaps at every gutter, and
   the narrow layout — which moves two cells onto a second line —
   placed them explicitly while the rest auto-flowed, so the money
   from one step landed on the line of the next.

   A row that is its own grid cannot do either. The columns still
   line up because every row uses the same track list with fixed
   leading widths, and a row can put its own border under itself.
   ════════════════════════════════════════════════════════════ */
.jr-fills { margin-top: 12px; }

.jr-steps { list-style: none; margin: 4px 0 10px; padding: 0; max-width: 720px; }

/* ── Fixed tracks, because every row is its own grid ──────
   Each row lays itself out, so `auto` columns would size to that
   row's own content and nothing would line up down the page — which
   on a column of numbers reads as broken rather than as ragged. The
   widths are the longest thing each column realistically holds; the
   gutters give a long one somewhere to go. */
.jr-steps li {
  display: grid;
  /* time · verb · size · "at" · price · what was left · what it made */
  grid-template-columns: 44px 84px 68px 16px 92px 1fr auto;
  gap: 0 8px;
  align-items: baseline;
  padding: 7px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--line2);
}
.jr-steps li:last-child { border-bottom: 0; }

.jr-steps .t { color: var(--ink3); font-variant-numeric: tabular-nums; }
.jr-steps .v { color: var(--ink2); white-space: nowrap; }
/* Right against the "at", so a long size grows left into the gutter
   rather than shunting the price out of its column. */
.jr-steps .q { font-weight: 600; white-space: nowrap; text-align: right; }
.jr-steps .at { color: var(--ink3); }
.jr-steps .p { color: var(--ink); white-space: nowrap; }

/* What was on afterwards — the column this list exists for. */
.jr-steps .pos { color: var(--ink3); font-size: 12px; white-space: nowrap; }
.jr-steps .pos em { font-style: normal; color: var(--ink2); font-weight: 600; }

/* And what the piece made. Right-aligned so the figures line up, and
   NOT coloured: colour in this journal is rule adherence and nothing
   else, and a green number here would teach that a profitable piece
   is a well-managed one. */
.jr-steps .made {
  text-align: right; color: var(--ink2); font-size: 12px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* The step that takes the position flat closes the sequence, and
   reads as the end of it rather than as one more row. */
.jr-steps li.flat .v { color: var(--ink); font-weight: 600; }

/* ── on a phone, two lines per step ────────────────────────
   Seven columns of a 358px screen is four characters each. What you
   did goes on the first line and where it left you on the second,
   under it — which is the shape the information already has. */
@media (max-width: 620px) {
  .jr-steps li {
    grid-template-columns: 44px 72px 1fr auto;
    gap: 2px 8px;
    align-items: start;
  }
  .jr-steps .at { display: none; }
  .jr-steps .q  { text-align: left; }
  .jr-steps .p  { text-align: right; }
  .jr-steps .pos  { grid-column: 2 / 4; }
  .jr-steps .made { grid-column: 4 / 5; }
}

/* The way out, and the one action an open trade has, on the same
   line as the eyebrow. */
.jr-cardacts { display: flex; align-items: center; gap: 14px; }
.jr-btn.sm { min-height: 36px; padding: 0 14px; font-size: 13px; border-radius: 9px; }

/* ── the During log, and the ways into it ──────────────────
   One list in the order things happened, then everything that adds
   to it. The list reuses the story's timeline — same dots, same
   indent, same quiet entries — because it is the same thing, told
   while it is still happening rather than afterwards. */
.jr-during-log { margin: 4px 0 0; }
.jr-during-log .jr-shot-list { margin-top: 6px; }

/* A label the summary above it already says, kept for the screen
   reader that is inside the form rather than above it. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* The one line that says the record and the bars disagree. Not an
   error — a measurement, with the fix one panel below. */
.jr-drift { margin-top: 10px; }
.jr-drift strong { color: var(--ink); }

/* ── what you did, as four buttons ─────────────────────────
   Not a dropdown. A select shows one of its options until you open
   it, so a row offering four things read as offering one — and the
   two that were added last were the two nobody could see. Four short
   words take one line and answer the question by being on screen. */
.jr-step-seg {
  grid-column: 1 / -1;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}
.jr-step-seg .jr-seg-opt span {
  min-height: 38px; border-radius: 9px; font-size: 13px;
}
/* The one chosen, in the brand. No colour by direction here: this row
   is about what you DID, and a red Stop would read as a verdict. */
.jr-step-seg .jr-seg-opt input:checked + span {
  background: var(--brand-soft); border-color: var(--brand); color: var(--brand);
}

/* A level move takes no size: a stop is a price, not an amount. */
.jr-step-row.no-size { grid-template-columns: minmax(0, 1fr) auto; }
@media (min-width: 720px) {
  .jr-step-row.no-size { grid-template-columns: minmax(0, 1fr) auto; }
}

/* ── the ways in, at the foot of the band ──────────────────
   Three lines, not a column. The position is the one with fields so
   it keeps a line of its own; saying something and showing something
   are a button each and share one; the note is a box that grows as
   you type rather than one that starts tall. Then the trade ends,
   under all of it — closing is what you do after the last thing you
   wrote, not something to scroll back up for. */
.jr-adds {
  margin: 14px 0 4px;
  padding-top: 14px;
  border-top: 1px solid var(--line2);
}
.jr-adds > * + * { margin-top: 10px; }

/* The two one-press ones, side by side. Both render a wrapper of
   their own, so the wrappers are what line up. */
.jr-adds-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.jr-adds-row > .jr-voice,
.jr-adds-row > .jr-shots { display: inline-flex; align-items: center; gap: 8px; margin: 0; }
.jr-adds-row .v-head { margin: 0; }
.jr-adds-row .jr-btn,
.jr-adds-row label.jr-btn { min-height: 38px; padding: 0 14px; font-size: 13px; margin: 0; }
/* What the recorder has to say goes after the buttons and wraps to
   its own line when it is long — it changes length as it talks. */
.jr-adds-row .v-say { flex: 1 1 100%; }

/* The note: a two-row box and its button on the same footing as the
   rest, rather than a three-row textarea with a primary button under
   it taking the width of the card. */
.jr-note-add .jr-label { margin-top: 0; }
.jr-note-add .jr-textarea { min-height: 62px; }
.jr-note-add .jr-btn {
  min-height: 38px; padding: 0 16px; font-size: 13px;
  margin-top: 8px; float: right;
}
.jr-note-add::after { content: ''; display: block; clear: both; }

/* And the end of the trade, under everything that adds to it. */
.jr-adds-end {
  display: flex; justify-content: flex-end;
  margin-top: 16px; padding-top: 14px;
  border-top: 1px solid var(--line2);
}

/* ── the live recorder, inside During ──────────────────────
   Three fields on one line: which way, at what, how much. The time is
   not asked for because it is now — which is the whole reason this is
   here rather than on a review screen. */
.jr-step-form { margin-top: 12px; }
/* Two by two on a phone, where four controls across 358px would be
   four characters each: which way it went takes the top line because
   it is the thing that decides what the row means, and the button
   takes the bottom. On anything wider it is one line — it sits at the
   foot of the During band now, which is the width of the screen, and
   a stack of four full-width controls there is a form pretending to
   be more than it is. */
.jr-step-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 6px;
  align-items: center;
}
.jr-step-row > select,
.jr-step-row > .jr-btn { grid-column: 1 / -1; }

@media (min-width: 720px) {
  .jr-step-row {
    grid-template-columns: minmax(0, 150px) minmax(0, 1fr) minmax(0, 1fr) auto;
  }
  .jr-step-row > select,
  .jr-step-row > .jr-btn { grid-column: auto; }
}
.jr-step-row .jr-input { min-height: 40px; padding: 8px 10px; font-size: 13px; }
.jr-step-row .jr-btn { min-height: 40px; padding: 0 14px; font-size: 13px; }

/* The one for a piece you noticed ten minutes late. Folded, because
   the common case is that it happened just now. */
.jr-step-when > summary {
  cursor: pointer; font-size: 12px; color: var(--ink3);
  padding: 8px 2px 4px; list-style: none;
}
.jr-step-when > summary::-webkit-details-marker { display: none; }
.jr-step-when > summary::before { content: '+ '; }
.jr-step-when[open] > summary::before { content: '– '; }
.jr-step-when .jr-input { min-height: 40px; padding: 8px 10px; font-size: 13px; }

/* The running list in the During card is tighter than the one on the
   reviewed trade: it shares a card with notes, a recorder and a
   picture strip, and it is a running total rather than the subject. */
.jr-steps.tight { font-size: 12px; margin-bottom: 4px; }
.jr-steps.tight li > span { padding: 5px 0; }

/* ── the editor, folded away ───────────────────────────────
   Most trades are one fill in and one fill out, and for those this
   is noise. Closed it is one quiet line that says the feature is
   here; opened it is already filled in with what the trade holds. */
.jr-fill-edit > summary {
  cursor: pointer; font-size: 13px; color: var(--ink3);
  padding: 8px 2px; list-style: none;
}
.jr-fill-edit > summary::-webkit-details-marker { display: none; }
.jr-fill-edit > summary::before { content: '+ '; color: var(--ink3); }
.jr-fill-edit[open] > summary::before { content: '– '; }
.jr-fill-edit > summary:hover { color: var(--brand); }
.jr-fill-edit .jr-note { margin: 2px 0 10px; }

/* ── three columns, and the heading row is part of the grid ──
   Separate <label>s above each field would wrap differently from the
   fields on a phone and stop lining up with them, which on a grid of
   numbers reads as the wrong number under the wrong heading. */
/* Four columns: time, which way it went, price, size. */
.jr-fill-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 6px;
  align-items: center;
  max-width: 760px;
}
/* A hidden field must not be laid out as a column of its own — it has
   no box, but the grid would still give it a track. */
.jr-fill-grid input[type="hidden"] { display: none; }
.jr-fill-head {
  font-size: 11px; color: var(--ink3); letter-spacing: .04em;
  text-transform: uppercase;
}
/* Shorter than the 48px touch target the rest of the forms use: a row
   of three is three times the height of one field, and a form of four
   rows at full height is a screen and a half on a phone. Still 40,
   which is a thumb. */
.jr-fill-grid .jr-input { min-height: 40px; padding: 8px 10px; font-size: 13px; }

/* ── on a phone the date gets its own line ─────────────────
   A third of 358px is 132, and a datetime-local renders
   "29/09/2026, 10:37" inside it — the browser does not wrap or
   shrink that, it clips it, and a field showing "29/09/20" is a field
   nobody can check. The two numbers that matter fit side by side; the
   date goes above them, where it has the width.

   The headings go with it, because a heading over a full-width field
   and two half-width ones no longer lines up with anything. The
   placeholders carry the labelling at that size. */
@media (max-width: 620px) {
  .jr-fill-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    row-gap: 4px;
  }
  .jr-fill-head { display: none; }
  .jr-fill-grid input[type="datetime-local"] { grid-column: 1 / -1; }
  /* Which way it went spans both, above the two numbers: it is the
     thing that changes what the row MEANS, so it reads first. */
  .jr-fill-grid select[name="step_side[]"] { grid-column: 1 / -1; }
  /* Space under each step, since four fields stacked two by two with
     no separation is one long column of boxes. On BOTH of the pair:
     the grid centres each item in its row, so a margin on one of two
     side-by-side fields lifts it ten pixels above the other. */
  .jr-fill-grid input[name="step_price[]"],
  .jr-fill-grid input[name="step_qty[]"] { margin-bottom: 12px; }
}

/* Shorter buttons than the rest of the app's 44px, for the same
   reason the fields are: this is a form inside a fold inside a card,
   and full-height controls make it read as the main event on a screen
   where it is a detail. 38px is still a thumb. */
.jr-fill-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.jr-fill-acts .jr-btn { min-height: 38px; padding: 0 14px; font-size: 13px; }

/* ── destructive, and kept quiet ─────────────────────────────
   Collapsed by default and at the bottom of the screen. Deleting a
   trade is a real need and a rare one; a red button beside "All
   trades" is a red button a thumb finds by accident. */
/* ── the two rare things, on one line ──────────────────────
   Adding something a week later and deleting a trade logged by
   mistake are both one short sentence behind a fold, and neither is
   what anybody came to this page for. Side by side they read as a
   footer; stacked they read as a list of things to consider.

   Opening either one takes the whole width back, because what is
   inside them is a form. */
.jr-quiet { display: flex; flex-wrap: wrap; gap: 8px 28px; align-items: flex-start; }
.jr-quiet > details { flex: 0 1 auto; }
.jr-quiet > details[open] { flex: 1 1 100%; }

.jr-danger { margin-top: 4px; }
.jr-danger > summary {
  cursor: pointer; font-size: 13px; color: var(--ink3);
  padding: 10px 4px; list-style: none; display: flex; align-items: center;
}
.jr-danger > summary::-webkit-details-marker { display: none; }
/* a drawn chevron: the ⌄ / ⌃ characters are missing from some fonts and showed as a stray "^" */
.jr-danger > summary::before {
  content: ''; flex: none; width: 6px; height: 6px; margin: -3px 10px 0 2px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .15s ease;
}
.jr-danger[open] > summary::before { transform: rotate(-135deg); margin-top: 3px; }
.jr-danger > summary:hover { color: var(--ink2); }
/* Open, it is a panel of its own: the explanation, and the button at the end of its row — not a loose
   button under loose text. */
.jr-danger[open] {
  padding: 4px 16px 16px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--sh);
}
.jr-danger[open] > summary { padding-left: 0; padding-right: 0; }
.jr-danger:not(.jr-later) > .jr-note { max-width: 62ch; margin: 0 0 8px; }
.jr-danger:not(.jr-later) > form { display: flex; justify-content: flex-end; margin-top: 6px; }
.jr-danger:not(.jr-later) > form .jr-btn-danger { margin-top: 0; }
.jr-btn-danger { color: var(--bad); border-color: var(--bad-line); margin-top: 6px; }
.jr-btn-danger:hover { background: var(--bad-soft); border-color: var(--bad); }

/* ── the little "i" ──────────────────────────────────────────
   An explanation that is there the first time and out of the way
   every time after. It used to be a permanent paragraph, which is
   fine on day one and clutter by day three. */
.jr-info {
  display: inline-grid; place-items: center;
  width: 16px; height: 16px; margin-left: 5px;
  border: 1px solid var(--line); border-radius: 50%;
  font-size: 10px; font-weight: 700; color: var(--ink3);
  cursor: help; vertical-align: middle;
}
.jr-info:hover, .jr-info:focus-visible { color: var(--brand); border-color: var(--brand); }
.jr-info[aria-expanded="true"] { color: var(--on-brand); background: var(--brand); border-color: var(--brand); }

/* What it opens. A panel in the page rather than a title attribute:
   the native tooltip needs a mouse to hover and a second of
   patience, so on a phone — where this form is actually used — it
   could not be read at all. */
.jr-tip {
  margin: 8px 0 2px; padding: 11px 13px;
  background: var(--panel2); border: 1px solid var(--line);
  border-left: 3px solid var(--brand); border-radius: 9px;
  font-size: 13px; line-height: 1.65; color: var(--ink2);
}

/* ── the standing rules, on the home page ────────────────────
   Set as a block of statements rather than as a bulleted list: a
   bullet makes each line an item in an inventory, and these are
   meant to be read as sentences somebody wrote about themselves.
   The rule is the left edge — one accent line down the whole set,
   which groups them without decorating each one. */
.jr-creed-list { list-style: none; margin: 4px 0 0; padding: 0 0 0 14px; border-left: 2px solid var(--brand); }
.jr-creed-list li {
  font-size: 15px; line-height: 1.6; color: var(--ink);
  padding: 5px 0;
}
/* A blank line the writer typed. Kept, because it is how goals get
   separated from rules without the journal having an opinion about
   which is which. */
.jr-creed-list li.gap { height: 10px; padding: 0; }
.jr-creed .jr-note { margin-top: 12px; }
.jr-creed .jr-note a { color: var(--ink3); }
.jr-creed .jr-note a:hover { color: var(--brand); }

/* ── the chart ───────────────────────────────────────────────
   A fixed height rather than an aspect ratio: on a phone a 16:9 box
   is 240px of candles and on a desktop it is 600px of mostly empty
   price scale. A chart is read at a comfortable height, and that
   height barely changes with the width. */
.jr-chart {
  height: 320px; width: 100%;
  margin: 4px 0 10px;
  border: 1px solid var(--line); border-radius: 10px;
  overflow: hidden; position: relative;
}
@media (min-width: 720px) { .jr-chart { height: 420px; } }

/* The timeframe row. Only the intervals the stored window can
   actually be aggregated into are ever rendered, so every button
   here produces a real chart. */
.jr-tf { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.jr-tf-btn {
  font: inherit; font-size: 12px; line-height: 1;
  padding: 7px 12px; min-height: 34px; min-width: 44px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel2); color: var(--ink2); cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.jr-tf-btn:hover { color: var(--ink); }
.jr-tf-btn.on {
  background: var(--brand); border-color: var(--brand); color: var(--on-brand);
  font-weight: 700;
}

/* A control that is deliberately not a button. Used for the
   testing affordance on the chart card: available, findable, and
   visibly not one of the things the screen is for. */
/* ── talking instead of typing ─────────────────────────────
   A record button, then a list of players with whatever the
   transcriber made of each. The transcript sits BESIDE the player
   rather than inside the written note: machine words never go into
   your sentence. */
.jr-voice { margin-top: 12px; }
.jr-voice .v-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.jr-voice .v-say { font-size: 12px; color: var(--ink3); font-family: var(--mono, monospace); }
.jr-voice .jr-btn.rec {
  background: var(--bad); border-color: var(--bad); color: #fff;
  /* No text selection or long-press menu while a finger is holding
     it down — both fire on exactly the gesture this button uses. */
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  touch-action: manipulation;
}
.jr-voice .jr-btn[data-voice-rec] {
  user-select: none; -webkit-user-select: none; touch-action: manipulation;
}
.jr-voice .v-detail {
  margin: 6px 0 0; font-family: var(--mono, ui-monospace, monospace);
  font-size: 11px; color: var(--ink3); word-break: break-word;
}
.jr-voice-list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 10px; }
/* `display: grid` beats the hidden attribute, so an empty list still
   took its own top margin — ten pixels of nothing under every
   recorder, which is what made the Record button sit higher than the
   two buttons beside it. */
.jr-voice-list[hidden] { display: none; }
.jr-voice-list li { border-top: 1px solid var(--line2); padding-top: 10px; }
.jr-voice-list li:first-child { border-top: 0; padding-top: 0; }
/* ── a player, wherever it lands ───────────────────────────
   These were scoped to .jr-voice-list, which is the list under the
   Record button. The During band keeps its recordings in the TIMELINE
   now, at the minute they were made — a different list with a
   different class — so none of this applied to them: no gap, no
   sizing, and "0:08", "Delete" and "Listening…" ran together into one
   word on a phone.

   Scoped to the pieces themselves instead. A player is a player
   wherever the page puts it. */
.v-row {
  display: flex; align-items: center;
  gap: 4px 12px; flex-wrap: wrap;
}
.v-row audio { height: 34px; max-width: 100%; flex: 1 1 240px; }

/* The length, the controls and whatever the transcriber is saying all
   sit on the line UNDER the player on a narrow screen, with room
   between them — they are four separate things and they were reading
   as one. */
.v-len {
  font-family: var(--mono, ui-monospace, monospace); font-size: 11.5px;
  color: var(--ink3); white-space: nowrap;
}
.v-state { font-size: 12px; color: var(--ink3); }
.v-row .jr-link-btn { font-size: 12px; }

@media (max-width: 620px) {
  .v-row audio { flex: 1 1 100%; }
}

.v-text {
  margin: 7px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--ink2);
  border-left: 2px solid var(--line); padding-left: 10px;
}

/* ── pictures kept with a phase ────────────────────────────
   A strip of thumbnails that stays a strip: three or four
   screenshots of the same moment are a row to glance along, not four
   full-width images to scroll past to reach the next card. Tapping
   one opens it full size in its own tab, where the browser's own
   viewer does the zooming — which it does better than anything
   written here would. */
.jr-shots { margin-top: 12px; }
.jr-shot-list {
  list-style: none; margin: 0 0 10px; padding: 0;
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
}
.jr-shot-list li { position: relative; }
.jr-shot-list a { display: block; }
.jr-shot-list img {
  display: block; width: 100%; height: 78px; object-fit: cover;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--panel2);
}
/* The way to remove one sits under its own thumbnail rather than on
   top of it: a delete control floating over a picture is pressed by
   a thumb that was aiming to look at the picture. */
.jr-shot-drop { margin: 2px 0 0; }
.jr-shot-drop .jr-link-btn { font-size: 11.5px; color: var(--ink3); }

.jr-shot-add { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* The real input is kept reachable by keyboard and screen readers —
   display:none would take it off both — and the label beside it is
   what is actually seen and pressed. */
.jr-shot-input {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.jr-shot-input:focus-visible + .jr-shot-go,
.jr-shot-add label:focus-within { outline: 2px solid var(--brand); outline-offset: 2px; }
label.jr-btn.sm { cursor: pointer; }

/* The plain file field on the close screen, where there is no strip
   yet because the trade has not been closed. */
.jr-input.jr-file { padding: 10px 12px; font-size: 13px; line-height: 1.4; }
.jr-input.jr-file::file-selector-button {
  margin-right: 10px; padding: 6px 10px;
  background: var(--panel2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px; cursor: pointer;
}

/* ── the trade screen, three columns where there is room ───
   A stack of cards on a 1900px monitor is a column of text down the
   middle with a field of grey either side.

   The shape is the trade: the facts across the top, then the three
   phases — before, during, after — in a row, read left to right,
   because they are one story and comparing them is the whole act of
   reviewing. The review furniture that follows (result, chart,
   timeline, verdict) takes the full width; none of it is a column of
   prose. While the trade is open the third column holds Close
   instead of After, which does not exist yet. */
@media (min-width: 1080px) {
  .jr-main.jr-trade {
    /* ── The container has to grow with the columns ───────
       .jr-main is 760px wide, which is a reading measure for ONE
       column of text. Splitting it without touching it gave 360px
       columns — narrower than a phone, with the audio players
       wrapping onto three lines each. The width is set by what a
       column has to hold, not by what the stack used to be. */
    max-width: 1240px;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 18px;
    align-items: start;
    /* A full-width card between narrow ones leaves a hole beside the
       one above it. Dense backfills that hole with the next card that
       fits, which is what somebody laying this out by hand would
       do. */
    grid-auto-flow: dense;
  }
  /* Anything that is better wide says so. Everything else takes a
     column, in the order it was written, which is the order it
     happened. */
  .jr-main.jr-trade > .jr-card.wide,
  .jr-main.jr-trade > .jr-card:has(.jr-chart),
  .jr-main.jr-trade > .jr-card:has(.jr-timeline),
  /* The two quiet things at the bottom are full width as well: a
     third of a screen is not enough for a form, and they were being
     laid out as if they were cards in the row. */
  .jr-main.jr-trade > details,
  .jr-main.jr-trade > .jr-review-end,
  .jr-main.jr-trade > .jr-quiet { grid-column: 1 / -1; }
}

/* Three columns of 395 is tight for an audio player with a scrubber
   in it; three of 500 is not. The container grows once the screen can
   pay for it, rather than being pinned to a width chosen for two. */
@media (min-width: 1600px) {
  .jr-main.jr-trade { max-width: 1560px; }

  /* And the two-column screens grow with it. 1240 was chosen when
     this was a grid whose columns had to stay a readable measure;
     two columns of 700 are not too wide for a panel of fields, and a
     1900px monitor showing 1240 of content is still mostly grey. */
}

/* ── every other screen, on a screen with room ─────────────
   760px is a reading measure for one column of prose, and almost
   nothing here is prose: settings is seven independent panels, the
   log is a form of short fields, the trade list is a table. On a
   1900px monitor all of them were a ribbon down the middle with a
   field of grey either side.

   The panels pair up; the list does not — a row of a table is not
   improved by being half as wide, and the card holding it simply
   gets the width instead. */
@media (min-width: 1080px) {
  .jr-main { max-width: 1240px; }

  /* The cards of a .jr-cols screen are laid out in columns by journal-masonry.js
     (below), not as a grid: a grid lines them up in ROWS, and a short card beside
     a tall one left a hole that nothing could move up into. */

  /* ── the trade list, as a table ─────────────────────────
     Not two columns of cards: a row of a table is not improved by
     being half as wide. It gets the width as extra COLUMNS — the
     exchange, when it opened, how long it was held, the risk, the
     planned reward and the result — while staying one line tall,
     because the point of a list is to be scanned.

     The widths are fixed so every row lines up with the heading; the
     ticker takes whatever is left. */
  .jr-list .jr-row {
    display: grid;
    /* Proportional, not "the ticker takes all that is left": on a
       wide screen that put a hand's width of nothing between the
       trade and its exchange. The spare width is shared out. */
    grid-template-columns:
      30px 22px minmax(150px, 1.4fr) minmax(104px, .9fr) minmax(136px, 1.1fr)
      minmax(60px, .6fr) minmax(70px, .7fr) minmax(56px, .5fr) minmax(64px, .6fr) 76px;
    gap: 10px;
    align-items: center;
    padding: 9px 8px;          /* one line, and a short one */
  }
  .jr-list .jr-row-sub { display: none; }    /* it has columns now */
  .jr-list .jr-row-sym { font-size: 14px; overflow: hidden; text-overflow: ellipsis; }

  .jr-list .jr-c {
    display: block; min-width: 0;
    font-size: 12.5px; color: var(--ink2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .jr-list .jr-c.num   { text-align: right; font-size: 13px; color: var(--ink); }
  .jr-list .jr-c.state { text-align: right; }

  .jr-list .jr-head {
    display: grid; padding-top: 2px; padding-bottom: 8px;
    border-bottom: 1px solid var(--line);
  }
  .jr-list .jr-head:hover { background: none; }
  .jr-list .jr-head .jr-row-sym,
  .jr-list .jr-head .jr-c {
    font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
    text-transform: uppercase; color: var(--ink3);
  }
}

/* The thesis, once it is sealed: a record rather than a field. */
.jr-card.sealed { background: var(--panel2, var(--panel)); }
.jr-card.sealed .jr-body { color: var(--ink2); }

/* ── the trade as a sequence ───────────────────────────────
   A dot, a rail, and one line of header per entry: when it happened,
   what it was, how long it ran. Those were three stacked rows, which
   on a trade talked through in a dozen voice notes was most of the
   screen — and two of the three repeated the same thing down the
   whole column. */
.jr-timeline { list-style: none; margin: 0; padding: 0; }
/* `> li`, not `li`: an entry can contain a list of its own — the
   strip of screenshots — and `.jr-timeline li` was laying each
   thumbnail out as a timeline entry, which put it in the 16px column
   the dot lives in. Two pictures came out 16 pixels wide. */
.jr-timeline > li {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  column-gap: 10px;
  padding: 0 0 6px;
  position: relative;
  border-radius: 10px;
  transition: background .12s ease;
}
.jr-timeline > li:last-child { padding-bottom: 0; }

.jr-timeline .dot {
  grid-column: 1; grid-row: 1;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--ink3); justify-self: center; margin-top: 6px;
  box-shadow: 0 0 0 3px var(--panel);
  z-index: 1;
}
/* The open and the exit are the two facts the sequence hangs on, so
   their dots are solid rather than tinted. Neither is coloured by
   the money: a loss taken exactly to plan is a correct trade, and
   the verdict cell two cards up is where that is said. */
.jr-timeline > li.open .dot,
.jr-timeline > li.exit .dot { background: var(--ink2); width: 10px; height: 10px; }

/* A level move is not a fill: nothing changed hands, a line on the
   chart changed place. Hollow, so the two read as different kinds of
   decision at a glance down the rail — which is the whole reason they
   share a timeline. Still no colour: a stop dragged out is a fact,
   and the verdict cell is where this journal makes judgements. */
.jr-timeline > li.level .dot {
  background: var(--panel); border: 2px solid var(--ink3);
  width: 10px; height: 10px;
}

/* The rail runs between one dot and the next, behind them. */
.jr-timeline > li::before {
  content: ''; position: absolute; left: 7px; top: 12px; bottom: -4px;
  width: 1px; background: var(--line2);
}
.jr-timeline > li:last-child::before { display: none; }

.jr-timeline .b { grid-column: 2; min-width: 0; }

/* ── what · detail, on one line ────────────────────────────── */
.jr-timeline .h {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  min-height: 20px;
}
.jr-timeline .t {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 11px; color: var(--ink3); white-space: nowrap;
}

/* ── the clock, as a marker between groups ─────────────────
   Printed on the entry it belonged to, and only every few minutes,
   the time read as MISSING from the entries without one. On a row
   of its own, with a hairline running off it, it reads as what it
   is: everything under it happened within a few minutes of this. */
.jr-timeline > li.when {
  padding: 10px 0 5px;
  min-height: 0;
}
.jr-timeline > li.when:first-child { padding-top: 0; }
.jr-timeline > li.when::before { top: 0; }
.jr-timeline > li.when .t {
  grid-column: 2;
  display: flex; align-items: center; gap: 10px;
  line-height: 14px;
}
.jr-timeline > li.when .t::after {
  content: ''; flex: 1; height: 1px; background: var(--line2);
}
.jr-timeline .h strong { font-size: 14px; font-weight: 600; line-height: 1.4; }
.jr-timeline .h em {
  font-style: normal; font-size: 12px; color: var(--ink3);
}
/* An entry whose label would have been "Said out loud" for the
   twelfth time. The player and the words are the entry. */
.jr-timeline > li.quiet .h { min-height: 0; margin-bottom: 2px; }

/* ── the story's own content ───────────────────────────────
   The timeline is the screen now: the thesis in full, the notes
   where they were written, the recordings playable where they were
   said, the screenshots where they were taken. Entries have bodies,
   and a body needs room to be read without costing four rows. */
.jr-timeline .say {
  margin: 3px 0 0; font-size: 15px; line-height: 1.5; color: var(--ink);
  border-left: 2px solid var(--line); padding-left: 10px;
}
/* 28px, not the browser's 54: a scrubber for twenty seconds of
   talking does not need to be the tallest thing in the entry. */
.jr-timeline audio {
  display: block; width: 100%; max-width: 320px; height: 28px; margin: 2px 0 4px;
}
.jr-timeline .jr-shot-list { margin-top: 6px; }
.jr-timeline .jr-shot-list img { height: 64px; }

/* Hovering an entry asks the chart where price was. Saying so with a
   tint is the difference between a page that responds and a page
   that appears to have twitched. */
.jr-main:not(.live) .jr-timeline > li[data-at]:hover { background: var(--panel2); cursor: pointer; }
.jr-main:not(.live) .jr-timeline > li[data-at]:hover .dot { box-shadow: 0 0 0 3px var(--panel2); }

/* The entry the chart is currently HELD at. Brand, not green or red:
   it means "this one", which is the only other thing colour is
   allowed to say here. */
.jr-timeline > li.held {
  background: var(--brand-soft);
  box-shadow: inset 2px 0 0 var(--brand);
}
.jr-timeline > li.held .dot { background: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }

/* ── the three regions of a trade ──────────────────────────
   The sequence stays unbroken — it is one story and reading it in
   order is the point — but Before, During and After are three kinds
   of knowledge: a commitment made under uncertainty, a live note,
   and hindsight. The whole reason this journal keeps them apart is
   to stop the last one rewriting the first, and a flat list of rows
   loses that. */
.jr-phase { border-left: 2px solid var(--line); padding-left: 14px; margin: 0 0 16px; }
/* A phone: the bands lose their side padding and the rail its gutter,
   so the words get the width. */
@media (max-width: 600px) {
  .jr-phase { padding-left: 8px; }
  .jr-phase.before, .jr-phase.after { padding: 10px 10px; }
  .jr-timeline > li { column-gap: 8px; grid-template-columns: 14px minmax(0, 1fr); }
  .jr-timeline .h { gap: 6px; }
  .jr-timeline .h strong { font-size: 13.5px; }
  .jr-timeline .say { padding-left: 8px; font-size: 14.5px; }
  .jr-timeline audio { max-width: 100%; }
}
.jr-phase:last-of-type { margin-bottom: 0; }

/* Before and After carry the same weight, because they are the two
   halves of a review: what you committed to, and what came of it.
   During is the one that is optional — a trade talked through has
   more to read, a trade taken and left alone has nothing in the
   middle and simply shows no region there. */
.jr-phase.before,
.jr-phase.after {
  border-radius: 12px;
  padding: 13px 15px;
  border-left-width: 3px;
  border-left-style: solid;
}
.jr-phase.before { background: var(--before-soft); border-left-color: var(--before); }
.jr-phase.after  { background: var(--after-soft);  border-left-color: var(--after); }

.jr-phase.before .jr-phase-head,
.jr-phase.after  .jr-phase-head { color: var(--ink); }
.jr-phase.before .jr-phase-head::before,
.jr-phase.after  .jr-phase-head::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%; align-self: center;
}
.jr-phase.before .jr-phase-head::before { background: var(--before); }
.jr-phase.after  .jr-phase-head::before { background: var(--after); }

/* The quote rule down the side of what was written takes the band's
   colour, so a paragraph belongs to its half at a glance. */
.jr-phase.before .say { border-left-color: var(--before-line); }
.jr-phase.after  .say { border-left-color: var(--after-line); }
.jr-phase.before .say,
.jr-phase.after  .say { font-size: 15px; color: var(--ink); }

/* The rail between dots, inside a tinted band. */
.jr-phase.before .jr-timeline > li::before { background: var(--before-line); }
.jr-phase.after  .jr-timeline > li::before { background: var(--after-line); }

/* The ring around a dot hides the rail behind it, so it has to be
   the colour the dot is actually sitting on. */
.jr-phase.before .dot { box-shadow: 0 0 0 3px var(--before-soft); }
.jr-phase.after  .dot { box-shadow: 0 0 0 3px var(--after-soft); }

/* And the hover tint has to sit on the band, not on the card. */
.jr-main:not(.live) .jr-phase.before .jr-timeline > li[data-at]:hover { background: rgba(217,164,65,.10); }
.jr-main:not(.live) .jr-phase.after  .jr-timeline > li[data-at]:hover { background: rgba(168,146,240,.12); }

.jr-phase-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 0 0 12px;
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink2);
}
/* What the region is FOR, which is the half that matters and the
   half nobody would guess from the word alone. */
.jr-phase-head span {
  font-size: 12px; font-weight: 400; letter-spacing: 0;
  text-transform: none; color: var(--ink3);
}

/* The one part of a closed trade that still takes something. */
.jr-add { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }

/* ── the three ways to add something, side by side ─────────
   They are three answers to one question — write it, say it, show it
   — and stacked they read as three separate offers. The recorder and
   the picture form bring their own wrappers, so the row is laid out
   on whatever they happen to be. */
.jr-later-acts {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px;
}
.jr-later-acts .jr-voice,
.jr-later-acts .jr-shots { margin-top: 0; }
.jr-later-acts .jr-voice .v-head,
.jr-later-acts .jr-shot-add { margin: 0; }
/* The three sit on one line, so they are one height: a button, a
   label dressed as a button and a button inside a flex row all
   measure differently left to themselves. */
.jr-later-acts .jr-btn,
.jr-later-acts label.jr-btn {
  display: inline-flex; align-items: center; min-height: 38px; margin: 0;
}
/* What the recorder has to say goes UNDER the row rather than
   between two buttons: it changes length as it talks — "Recording…
   0:07", "That was too short to keep" — and the buttons either side
   of it moved every time it did. */
.jr-later-acts .jr-voice { display: contents; }
.jr-later-acts .jr-voice .v-head { display: contents; }
.jr-later-acts .v-say { flex-basis: 100%; order: 9; margin: 0; }
.jr-later-acts .jr-voice-list { flex-basis: 100%; order: 10; }

/* ── a screenshot, full size, over the page ────────────────
   Not a new tab: the whole value of a screenshot is being read
   against the trade it belongs to, and a tab of its own is the trade
   gone. Fixed, dark, and it takes the whole viewport including the
   phone's safe areas. */
.jr-view {
  display: none; position: fixed; inset: 0; z-index: 90;
  background: rgba(4, 8, 9, .88);
  align-items: center; justify-content: center;
  padding: max(16px, env(safe-area-inset-top)) 16px max(16px, env(safe-area-inset-bottom));
  overscroll-behavior: contain;
}
.jr-view.on { display: flex; }
.jr-view img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 10px;
  box-shadow: 0 20px 60px -20px rgba(0, 0, 0, .9);
}
/* 44px of target, out of the way of the picture, and legible on
   whatever colour happens to be underneath them. */
.jr-view button {
  position: absolute; display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  background: rgba(20, 26, 28, .85); color: #E8EEEC;
  border: 1px solid rgba(232, 238, 236, .25); border-radius: 50%;
  font-size: 22px; line-height: 1; cursor: pointer;
}
.jr-view button:hover { background: rgba(20, 26, 28, 1); }
.jr-view .x { top: max(12px, env(safe-area-inset-top)); right: 12px; }
.jr-view .p { left: 12px; }
.jr-view .n { right: 12px; }
.jr-view.one .p, .jr-view.one .n { display: none; }

/* ── the replay ────────────────────────────────────────────
   Two places. Above the chart, with the timeframes: Recenter and the P&L tag, which are about the view. Under
   it, in one row: the player (step back, play, step on, speed, stop) and the slider, because they are one
   control, the same replay by button and by hand. */
.jr-replay-set { display: flex; flex-wrap: wrap; gap: 4px; margin-left: auto; }
.jr-replay-set .jr-tf-btn.on, .jr-player .jr-tf-btn.on {
  background: var(--brand-soft); color: var(--brand); border-color: var(--brand);
}
.jr-scrub { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin: 8px 0 2px; }
.jr-player { display: flex; gap: 4px; flex: none; }
.jr-player .jr-tf-btn { white-space: nowrap; }
.jr-player .jr-step  { min-width: 36px; padding: 7px 10px; font-size: 15px; }
.jr-player .jr-speed { min-width: 44px; font-variant-numeric: tabular-nums; }
.jr-player .jr-replay { min-width: 92px; }
.jr-scrub-track { display: flex; align-items: center; gap: 10px; flex: 1 1 200px; min-width: 0; }
.jr-scrub input[type=range] { flex: 1; min-width: 0; height: 28px; margin: 0; accent-color: var(--brand); cursor: pointer; touch-action: pan-y; }
.jr-scrub-at { flex: none; min-width: 84px; text-align: right; font: 600 12px/1 var(--mono, ui-monospace, monospace); color: var(--ink3); font-variant-numeric: tabular-nums; }

/* On a phone the timeframes already fill the row, so Recenter and the tag drop below them; the player takes
   one full row under the chart (the buttons share it), and the slider the row below that. */
@media (max-width: 560px) {
  /* All seven timeframes on ONE row: they share the width instead of wrapping the last one under the rest. */
  .jr-tf { gap: 4px; }
  .jr-tf > .jr-tf-btn { flex: 1 1 0; min-width: 0; padding: 7px 0; text-align: center; white-space: nowrap; }
  .jr-replay-set { margin-left: 0; width: 100%; gap: 6px; }
  .jr-replay-set .jr-tf-btn { white-space: nowrap; flex: 1 1 0; min-width: 0; padding: 7px 8px; }
  .jr-player { width: 100%; gap: 6px; }
  .jr-player .jr-tf-btn { flex: none; min-width: 0; padding: 8px 8px; }
  .jr-player .jr-step { flex: 0 0 44px; }
  .jr-player .jr-replay { flex: 1 1 96px; min-width: 92px; }
  .jr-player .jr-speed { flex: 0 0 50px; }
  .jr-player .jr-stop { flex: 0 0 auto; }
  .jr-scrub-track { flex: 1 1 100%; }
  .jr-scrub-at { min-width: 70px; font-size: 11px; }
}

/* ── a setting that is a choice, not a number ──────────────
   The box and its explanation on one row, with the label doing the
   clicking: a 14px checkbox is not a touch target, and the sentence
   beside it is the part that explains what the box is for. */
.jr-check {
  display: flex; align-items: flex-start; gap: 12px;
  margin-top: 18px; padding: 12px 14px;
  background: var(--panel2); border: 1px solid var(--line);
  border-radius: 12px; cursor: pointer;
}
.jr-check input { flex: none; width: 18px; height: 18px; margin-top: 2px; accent-color: var(--brand); }
.jr-check span   { font-size: 13px; line-height: 1.55; color: var(--ink3); }
.jr-check strong { display: block; font-size: 14px; color: var(--ink); margin-bottom: 3px; }

/* The phase small print: an i on its own line, right where the
   sentence used to be, so the card does not change height when it is
   opened. */
.jr-meta { margin: 6px 0 0; }

/* ── during: the notes written while a trade ran ───────────
   Time above, words below — the same shape as the timeline, for the
   same reason: a fixed column of monospace date is wide enough to
   clip "Fri 2 Oct, 09:22" at any width worth having, and a clipped
   timestamp beside a sentence reads as a broken sentence. */
.jr-notes { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 2px; }
.jr-notes li {
  padding: 9px 0; border-bottom: 1px solid var(--line2);
}
.jr-notes li:last-child { border-bottom: 0; }
.jr-notes .when {
  display: block;
  font-family: var(--mono, ui-monospace, monospace); font-size: 11px;
  color: var(--ink3); white-space: nowrap; margin-bottom: 2px;
}
.jr-notes .what { display: block; font-size: 14px; line-height: 1.55; }


/* The pan line: what the chart just fetched while you dragged, and
   the fact that it is not being kept. Sits under the chart, quiet,
   and takes itself away again. */
.jr-pan {
  position: absolute; left: 10px; top: 8px; z-index: 6; margin: 0; max-width: calc(100% - 20px);
  padding: 4px 10px; font-size: 12px; line-height: 1.4; color: var(--ink2); pointer-events: none;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
  font-family: var(--mono, ui-monospace, monospace);
}
.jr-pan[hidden] { display: none; }

/* ── where the bars come from ─────────────────────────────
   One block, two couriers. Folded into a <details> when a chart is
   already drawn, because then it is a second opinion rather than
   the way out — and an open picker under a working chart reads as
   a question somebody is asking. */
.jr-source { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line2); }
.jr-source > summary {
  cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink2);
  list-style: none; display: flex; align-items: center; gap: 7px;
}
.jr-source > summary::-webkit-details-marker { display: none; }
.jr-source > summary::before {
  content: '+'; font-family: var(--mono, monospace); font-size: 14px; line-height: 1;
  color: var(--ink3); width: 12px; text-align: center;
}
.jr-source[open] > summary::before { content: '−'; }
.jr-source > summary:hover { color: var(--ink); }
.jr-source .jr-input { max-width: 320px; }
.jr-source-btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.jr-source-btns .jr-btn[disabled] { opacity: .45; cursor: not-allowed; }
/* The attempt log: one line per route tried, and it has to stay
   readable when a venue answers with a sentence. */
#jrFetchOut { margin-top: 10px; line-height: 1.6; }

.jr-forget { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line2); }
.jr-link-btn {
  font: inherit; font-size: 12px; line-height: 1.5;
  background: none; border: 0; padding: 0;
  color: var(--ink3); text-decoration: underline;
  text-underline-offset: 3px; cursor: pointer;
}
.jr-link-btn:hover { color: var(--ink2); }

/* ── the standing rules, as a gate ───────────────────────────
   Covers the application until it is answered. Fixed rather than
   absolute so it cannot be scrolled past, and it carries its own
   safe-area padding because it is the one element on the page that
   is not inside the shell's. */
.jr-gate {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  padding: calc(env(safe-area-inset-top, 0px) + 20px) 16px
           calc(env(safe-area-inset-bottom, 0px) + 20px);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  overflow-y: auto;
}
.jr-gate-box {
  width: 100%; max-width: 520px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: var(--sh);
  padding: 24px 22px 20px;
}
/* The one way out. Full width and last, so the eye passes the rules
   on the way to it. */
.jr-gate-go { width: 100%; min-height: 50px; margin-top: 20px; }
.jr-gate .jr-note { text-align: center; margin-top: 12px; }
.jr-gate .jr-creed-list li { font-size: 16px; }

/* ── saved ───────────────────────────────────────────────────
   Shown in place of the form the instant the server confirms, so
   there is no second page load before anything happens. */
.jr-saved { text-align: center; padding: 26px 18px; }
.jr-saved .mk { font-size: 30px; color: var(--good); }
.jr-saved h2 { margin: 8px 0 2px; }
.jr-saved .figs { display: flex; justify-content: center; gap: 18px; flex-wrap: wrap; margin: 14px 0 20px; }
.jr-saved .figs span { font-size: 13px; color: var(--ink2); }
.jr-saved .figs b { display: block; font-size: 17px; color: var(--ink);
                    font-family: 'JetBrains Mono', ui-monospace, monospace; }
.jr-saved .acts { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.jr-submit[aria-busy="true"] { opacity: .65; pointer-events: none; }

/* ── the line at the top of a form that just took a POST ─────
   Not a card: a card is a section of the page and this is a reply to
   something the reader just did. Coloured border on the leading edge
   only, so it reads as an annotation rather than as new content. */
.jr-flash {
  margin-bottom: 14px; padding: 12px 14px;
  border-radius: 11px; border: 1px solid;
  font-size: 14px; line-height: 1.6;
}
.jr-flash.good { color: var(--good); background: var(--good-soft); border-color: var(--good-line); }
.jr-flash.bad  { color: var(--bad);  background: var(--bad-soft);  border-color: var(--bad-line); }

/* ── the instrument picker ───────────────────────────────────
   A combobox, not a select. The field stays free text — the list
   assists and never gates — so this is styled as a field with
   something under it rather than as a control of its own. */
.jr-picker { position: relative; }

/* IN THE FLOW, not floating over the form, and that was a measured
   decision rather than a stylistic one.

   Floated, the list covered the Direction buttons directly beneath
   it. A thumb aimed at "Long" hit the list instead: the tap was
   swallowed, nothing was selected, and the reader had to tap twice —
   and if that first tap landed on a result row rather than on the
   list's padding, it silently changed the instrument they had just
   finished typing. Measured with a real touch tap, not assumed.

   In the flow, the form grows while the list is open and nothing is
   ever covered. The content that moves is all BELOW the field being
   typed into, so the reader's eye does not have to follow it. */
.jr-results {
  max-height: 46vh; overflow-y: auto; overscroll-behavior: contain;
  margin: 6px 0 0; padding: 4px; list-style: none;
  background: var(--panel2); border: 1px solid var(--line); border-radius: 12px;
}

/* 44px of touch target. A row: the asset's mark, then the two lines
   of text, which are a hierarchy — the ticker is what you are looking
   for, the venue and description are what tell you which of the four
   identical tickers this one is. flex-start rather than the default:
   centred, the marks would sit at a different indent on every line
   depending on how long the ticker next to them was. */
.jr-result {
  display: flex; flex-direction: row; align-items: center;
  justify-content: flex-start; gap: 10px;
  min-height: 44px;
  padding: 7px 10px; border-radius: 9px; cursor: pointer;
}
.jr-result-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.jr-result-text b,
.jr-result-text span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr-result b    { font-size: 14px; color: var(--ink); font-weight: 600; }
.jr-result span { font-size: 12px; color: var(--ink3); }
.jr-result.on   { background: var(--brand-soft); }
.jr-result.on b { color: var(--brand); }
.jr-result:hover { background: var(--panel2); }

/* What was chosen, under the field. The ticker alone is ambiguous
   across venues and this is the line that resolves it. */
.jr-picked {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin-top: 8px; font-size: 12px; color: var(--ink3);
}
.jr-venue {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  padding: 3px 7px; border-radius: 6px;
  background: var(--panel3); color: var(--ink2);
}
/* A price that came from the venue rather than from the trader.
   A left edge, not a fill: it must read as "this is a suggestion"
   without looking like the field is in an error state, and it
   disappears the moment the number is touched. */
.jr-input.jr-prefilled { border-left: 3px solid var(--brand); }

/* Announced, not shown. The result count has to reach a screen
   reader, and printing it would be noise for everyone else. */
.jr-sr {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── the asset's mark ────────────────────────────────────────
   A logo where one ships, a monogram where none does — and the two
   are deliberately the same circle at the same size.

   The shipped set is 483 crypto marks and it is permanently
   incomplete: it predates SUI, ARB, OP and TIA, and it has nothing
   for CME:NQ or for a barrel of oil, which this journal is meant to
   hold eventually. So the monogram is the primary treatment and the
   logo is the enhancement. A list of eight monograms and four logos
   has to read as one kind of thing rather than as a set with holes
   in it, and matching their geometry exactly is what does that. */
.jr-mark {
  flex: 0 0 26px;
  display: inline-grid; place-items: center;
  width: 26px; height: 26px; border-radius: 50%;
  font-size: 10px; font-weight: 700; letter-spacing: .02em;
  background: var(--panel3); color: var(--ink2);
  /* Neutral, always. Colour in this application means rule
     adherence, and a monogram tinted per asset would quietly start a
     second colour language next to the only one that is allowed to
     mean anything. A logo carries its own brand colour, which is
     identity rather than a claim about a trade — the same carve-out
     the long/short pills get. */
  overflow: hidden;
}
img.jr-mark { background: none; }

/* The heading on a trade puts the mark in line with the ticker. */
.jr-card h2 .jr-mark { vertical-align: middle; margin-right: 4px; }

/* A row in the trade list gains the mark before its direction pill. */
.jr-row .jr-mark { margin-right: 2px; }

/* ══════════════════════════════════════════════════════════
   The matrix

   Ported from the approved screen model, unchanged in shape and
   colour. Two rules it must keep:

   1. COLOUR ENCODES RULE ADHERENCE, NEVER PROFIT. Followed-and-lost
      is GREEN. That is the whole point of the screen: a loss taken
      exactly to plan is a correct trade, and nothing else in this
      category of product gets that right. Painting the loss column
      red would turn the matrix back into a P&L tracker with extra
      squares.

   2. The row headers read down the side rather than wrapping, so the
      grid stays square on a phone — which is where trades are
      actually reviewed.
   ══════════════════════════════════════════════════════════ */
.jr-mx {
  display: grid;
  grid-template-columns: auto 1fr 1fr;
  gap: 7px;
  align-items: stretch;
  margin: 18px 0 4px;
}
.jr-mx .colh,
.jr-mx .rowh {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px; letter-spacing: .11em; text-transform: uppercase;
  color: var(--ink3);
  display: flex; align-items: center; justify-content: center;
  padding: 3px;
}
.jr-mx .rowh { writing-mode: vertical-rl; transform: rotate(180deg); padding: 8px 3px; }

.jr-cell {
  border-radius: 9px; padding: 15px 16px; border: 1px solid;
  min-height: 112px;
  display: flex; flex-direction: column; justify-content: space-between;
  position: relative; overflow: hidden;
}
.jr-cell.good { background: var(--good-soft); border-color: var(--good-line); }
.jr-cell.bad  { background: var(--bad-soft);  border-color: var(--bad-line); }

.jr-cell .ttl { font-size: 13px; font-weight: 700; line-height: 1.28; }
.jr-cell.good .ttl { color: var(--good); }
.jr-cell.bad  .ttl { color: var(--bad); }

.jr-cell .big {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 31px; font-weight: 700; line-height: 1;
  letter-spacing: -.03em; color: var(--ink);
}
.jr-cell .pct { font-size: 12px; color: var(--ink2); font-weight: 600; }

/* The count of trades the four boxes do NOT cover. Quiet, and
   directly under the grid, because a matrix that does not say what
   it left out is a matrix that overstates itself. */
.jr-mx-gap {
  margin-top: 12px; padding: 11px 13px;
  background: var(--panel2); border: 1px solid var(--line);
  border-radius: 9px; font-size: 12.5px; line-height: 1.65; color: var(--ink3);
}
.jr-mx-gap strong { color: var(--ink2); }

/* ══════════════════════════════════════════════════════════
   plans — the rules a trade is measured against
   ══════════════════════════════════════════════════════════ */

/* The Plans screen is one centred column: two short cards left-aligned on a wide
   screen looked like a page that had not finished loading. */
.jr-main.jr-plans { max-width: 720px; }
.jr-plans > .jr-card { margin-bottom: 16px; }

.jr-plan-head {
  display: flex; align-items: center; gap: 8px;
  margin: 22px 0 0; font-size: 13px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink2);
}
.jr-plan-head span {
  background: var(--line2); color: var(--ink2); border-radius: 999px;
  padding: 1px 8px; font-size: 12px; letter-spacing: 0;
}

/* Each plan is a button-sized card, not a line of text: a name, how many rules it has,
   and an arrow that says "this opens". */
.jr-plan-list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; }

.jr-plan-list a {
  display: flex; align-items: center; gap: 12px;
  min-height: 56px; padding: 12px 14px;
  background: color-mix(in srgb, var(--brand) 7%, var(--card, var(--bg)));
  border: 1.5px solid color-mix(in srgb, var(--brand) 38%, var(--line2));
  border-radius: 12px;
  color: var(--ink); text-decoration: none;
  transition: border-color .12s, background .12s, transform .12s;
}
.jr-plan-list a:hover, .jr-plan-list a:focus-visible {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 14%, var(--card, var(--bg)));
}
.jr-plan-list a:active { transform: scale(.992); }
.jr-plan-list a strong { font-size: 16px; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.jr-plan-meta {
  flex: 0 0 auto; font-size: 12.5px; color: var(--ink2);
  background: var(--line2); border-radius: 999px; padding: 2px 10px;
}
.jr-plan-open {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  font-size: 13px; font-weight: 700; color: var(--brand);
}
.jr-plan-open b { font-size: 20px; line-height: 1; }
@media (max-width: 480px) { .jr-plan-open { font-size: 0; } .jr-plan-open b { font-size: 22px; } }

/* A retired plan is still part of how you traded last year, so it is
   listed — but dimmer and without the brand tint, which is the whole difference. */
.jr-plan-list > li.off a { background: transparent; border-color: var(--line2); border-style: dashed; }
.jr-plan-list > li.off a strong { color: var(--ink3); font-weight: 600; }
.jr-plan-list > li.off .jr-plan-open { color: var(--ink3); }

.jr-plan-new { display: flex; gap: 8px; margin-top: 14px; }
.jr-plan-new .jr-input { flex: 1 1 auto; min-width: 0; }
/* "New plan" came out as two lines once the card was half the screen:
   the input takes the slack and the button takes the words it has. */
.jr-plan-new .jr-btn { flex: 0 0 auto; white-space: nowrap; }

.jr-plan-acts {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 14px;
}

/* ── one list of rules ────────────────────────────────────── */

.jr-rules { list-style: none; margin: 12px 0 0; padding: 0; }

.jr-rules > li {
  display: grid;
  /* mark · the rule · who answers it · order · remove */
  grid-template-columns: 18px 1fr auto auto auto;
  gap: 0 10px;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--line2);
  font-size: 13.5px;
}
.jr-rules > li:last-child { border-bottom: 0; }

/* ── Why the mark is not a colour ─────────────────────────
   Colour in this journal means rule adherence, and this screen is
   the rules themselves — nothing here has been followed or broken
   yet. So the two kinds are told apart by a glyph and a word: a
   hollow ring for one you answer, the brand's lozenge for one the
   journal answers. */
.jr-rule-mark { color: var(--ink3); font-size: 11px; line-height: 1.5; }
.jr-rules > li.measured .jr-rule-mark { color: var(--brand); }

.jr-rule-text { color: var(--ink); line-height: 1.5; }
.jr-rule-who {
  color: var(--ink3); font-size: 11.5px; white-space: nowrap;
  text-transform: lowercase;
}
.jr-rules > li.measured .jr-rule-who { color: var(--brand); }

.jr-rule-drop { display: inline; }
.jr-rule-empty { margin: 12px 0 0; }

/* ── the order the list is read in ─────────────────────────
   A checklist is read top to bottom while a position is being sized,
   so the order is part of what it says. Two arrows rather than a
   drag: a drag is the one gesture that cannot be done one-handed on
   a phone with a trade already running.

   The arrow at the end of the list is printed and dimmed rather than
   dropped, so the two rows do not shuffle sideways as you move
   something through them. */
.jr-rule-move { display: inline-flex; gap: 2px; white-space: nowrap; }
.jr-rule-move form { display: inline; }

.jr-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; min-height: 26px;
  font-size: 13px; line-height: 1; color: var(--ink3);
}
button.jr-arrow:hover { color: var(--brand); }
.jr-arrow.off { opacity: .22; }

/* Said under every list, because the card above has a Save button
   and this one does not — which reads as a card you forgot to save.
   It is not: a list of rules is a list, and adding to it IS the
   change. */
.jr-rule-kept { margin: 10px 0 0; font-size: 11.5px; }

/* ── adding one ───────────────────────────────────────────── */

.jr-add-rule { margin-top: 14px; }

.jr-add-rule > summary {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel2); color: var(--ink);
  font-size: 13.5px; font-weight: 600; cursor: pointer;
  list-style: none;
}
.jr-add-rule > summary::-webkit-details-marker { display: none; }
.jr-add-rule > summary::before { content: '+'; color: var(--brand); font-weight: 700; }
.jr-add-rule > summary:hover { border-color: var(--brand); }
.jr-add-rule[open] > summary { margin-bottom: 12px; }

.jr-rule-own-row { display: flex; gap: 8px; }
.jr-rule-own-row .jr-input { flex: 1 1 auto; min-width: 0; }

.jr-rule-auto {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
}

.jr-offer { list-style: none; margin: 10px 0 0; padding: 0; }

.jr-offer > li {
  padding: 8px 0; border-bottom: 1px solid var(--line2);
}
.jr-offer > li:last-child { border-bottom: 0; }

.jr-offer form {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13.5px;
}
.jr-offer .jr-rule-text { flex: 1 1 240px; line-height: 2.1; }

/* Wide enough for "07:00-16:00" and no wider: a number field that
   fills the row reads as the important part of a sentence it is only
   the limit of. */
.jr-rule-n {
  /* Inline, inside the sentence it is a word of. */
  display: inline-block; vertical-align: baseline;
  width: 72px; min-height: 34px; padding: 0 8px; margin: 0 2px;
  font-size: 13px;
}
.jr-rule-n[size] { width: 112px; }
.jr-rule-unit { color: var(--ink3); font-size: 11.5px; white-space: nowrap; }

.jr-offer > li.have {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  font-size: 13.5px; opacity: .55;
}
.jr-offer .jr-note { margin: 4px 0 0; font-size: 11.5px; }

/* ── on a phone ───────────────────────────────────────────
   The rule and who answers it stack, because "measured" beside a
   two-line sentence on a 358px screen leaves the sentence four
   characters wide. Remove goes to the end of the first line, where
   a thumb already is. */
@media (max-width: 760px) {
  .jr-rules > li {
    grid-template-columns: 18px 1fr auto;
  }
  /* The rule keeps the first line to itself; who answers it and the
     two controls share the second. Three columns of a 358px screen
     left the sentence four characters wide. */
  .jr-rule-who  { grid-column: 2 / 3; grid-row: 2; }
  .jr-rule-move { grid-column: 3 / 4; grid-row: 2; justify-self: end; }
  .jr-rule-drop { grid-column: 3 / 4; grid-row: 1; justify-self: end; }
  .jr-plan-new { flex-wrap: wrap; }
  .jr-plan-new .jr-input { flex-basis: 100%; }
}

/* ── which plan, and its checklist ────────────────────────── */

.jr-plan-pick { list-style: none; margin: 12px 0 0; padding: 0; }

.jr-plan-pick > li {
  border: 1px solid var(--line); border-radius: 11px;
  background: var(--panel2);
  margin-bottom: 8px;
  overflow: hidden;
}

/* Real radio, off screen but focusable — the label is bound to it by
   for=, so the whole row is a hit target and the keyboard still
   reaches it. Not display:none, which takes it out of the tab order
   and out of the accessibility tree. */
.jr-pick-in {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.jr-pick {
  display: block; padding: 12px 14px; cursor: pointer;
  /* 44px of thumb even on the shortest row. */
  min-height: 44px;
}
.jr-pick b { display: block; font-size: 14px; color: var(--ink); }
.jr-pick em {
  display: block; margin-top: 2px;
  font-style: normal; font-size: 12px; line-height: 1.5; color: var(--ink3);
}

.jr-pick-in:checked + .jr-pick {
  background: var(--brand-soft);
  box-shadow: inset 2px 0 0 var(--brand);
}
.jr-pick-in:checked + .jr-pick b { color: var(--brand); }
.jr-pick-in:focus-visible + .jr-pick { outline: 2px solid var(--brand); outline-offset: -2px; }

/* ── The checklist, revealed by its own radio ─────────────
   CSS alone, so choosing a plan costs no request and works before
   any script has loaded. Every plan's list is in the page; the boxes
   are named per plan, so the answers of a plan that was not picked
   cannot be read by mistake. */
.jr-checklist { display: none; }
.jr-pick-in:checked ~ .jr-checklist { display: block; }

.jr-checks {
  list-style: none; margin: 0; padding: 4px 14px 12px;
  border-top: 1px solid var(--line);
}

.jr-checks > li {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 0;
  border-bottom: 1px solid var(--line2);
  font-size: 13.5px;
}
.jr-checks > li:last-child { border-bottom: 0; }

.jr-check-text { flex: 1 1 180px; color: var(--ink); line-height: 1.45; }
.jr-checks > li.measured .jr-check-text { color: var(--ink2); }

/* Two buttons, 96px each: wide enough for the word, narrow enough
   that the rule stays the thing being read. */
.jr-check-seg {
  display: grid; grid-template-columns: repeat(2, 86px); gap: 6px; flex: 0 0 auto;
}
.jr-check-seg .jr-seg-opt span { min-height: 38px; border-radius: 9px; font-size: 13px; }

/* ── Colour here IS rule adherence ───────────────────────
   Which is the one thing colour means in this application, so this
   is the place it belongs: green for a rule you kept, red for one
   you broke, and nothing for a question you have not answered. */
.jr-seg-opt input:checked + span.kept {
  background: var(--good-soft); border-color: var(--good-line); color: var(--good);
}
.jr-seg-opt input:checked + span.broke {
  background: var(--bad-soft); border-color: var(--bad-line); color: var(--bad);
}

/* All of them kept, in one tap. Inserted by script, because a
   control that does nothing without one should not be in the page
   at all. */
.jr-check-all {
  display: flex; justify-content: flex-end; padding: 8px 14px 0;
}

@media (max-width: 620px) {
  .jr-check-seg { grid-template-columns: repeat(2, minmax(0, 1fr)); flex: 1 1 100%; }
}

/* ── the verdict, with its working ────────────────────────── */

/* ── Why this is the one coloured thing here ──────────────
   Colour in this journal means rule adherence and nothing else.
   This IS rule adherence, so it is where the colour belongs — and it
   is deliberately not the P&L beside it: a loss taken exactly to
   plan is a correct trade, and a green number on it would teach the
   opposite. */
.jr-verdict {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 10px 0 4px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel2);
}
.jr-verdict strong { font-size: 15px; }
.jr-verdict span { font-size: 12.5px; color: var(--ink3); line-height: 1.5; }

.jr-verdict.kept  { background: var(--good-soft); border-color: var(--good-line); }
.jr-verdict.kept strong { color: var(--good); }
.jr-verdict.broke { background: var(--bad-soft); border-color: var(--bad-line); }
.jr-verdict.broke strong { color: var(--bad); }
.jr-verdict.open strong { color: var(--ink2); }

.jr-ruling { margin-top: 16px; }

.jr-ruled { list-style: none; margin: 8px 0 0; padding: 0; }

.jr-ruled > li {
  display: grid;
  /* mark · the rule and its answer · the figure that settled it */
  grid-template-columns: 22px minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 2px 12px;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--line2);
  font-size: 13px;
}
.jr-ruled > li:last-child { border-bottom: 0; }

/* ── The mark, as a badge ──────────────────────────────────
   It was a 12px glyph in the rule's colour, which beside a line of
   text is a speck: kept and broken read the same from a foot away.
   A filled disc for broken, a tinted one for kept, and nothing but a
   dash for a rule nobody could answer — the three are told apart by
   shape and weight before colour, so they survive a glance. */
.jr-ruled-mark {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  font-size: 13px; font-weight: 800; line-height: 1; color: var(--ink3);
  align-self: start; margin-top: -1px;
}
.jr-ruled > li.kept  .jr-ruled-mark { background: var(--good-soft); color: var(--good); }
.jr-ruled > li.broke .jr-ruled-mark { background: var(--bad); color: #fff; }
.jr-ruled > li.broke { background: color-mix(in srgb, var(--bad) 6%, transparent); }

.jr-ruled-text { color: var(--ink); line-height: 1.45; }
.jr-ruled-text em {
  display: block; margin-top: 2px;
  font-style: normal; font-size: 11px; color: var(--ink3); text-transform: lowercase;
}
.jr-ruled > li.kept  .jr-ruled-text em { color: var(--good); font-weight: 600; }
.jr-ruled > li.broke .jr-ruled-text em { color: var(--bad);  font-weight: 700; }
.jr-ruled > li.quiet .jr-ruled-text { color: var(--ink2); }

/* The working. Quiet by default — it is there to be checked, not to
   be read every time — and in the mono face, because most of it is
   figures. */
.jr-ruled-fact {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11.5px; line-height: 1.5; color: var(--ink3);
}

.jr-dispute {
  margin-top: 14px; padding: 10px 12px;
  background: var(--warn-soft); border: 1px solid var(--warn);
  border-radius: 9px; color: var(--ink2);
}
.jr-dispute strong { color: var(--warn); }

.jr-dispute-ask { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }

/* ── on a phone, the working goes under the rule ──────────
   Three columns of a 358px screen leaves the rule and the figure
   four words each, and both of them are sentences. */
@media (max-width: 760px) {
  .jr-ruled > li { grid-template-columns: 22px minmax(0, 1fr); }
  .jr-ruled-fact { grid-column: 2 / 3; }
}

/* The way back for a plan that was not picked, or a rule that was not
   answered. Set apart from the ruling above it, because it is the one
   thing on the card that is not a record of what happened. */
.jr-plan-link {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
}
.jr-plan-link .jr-checks { padding: 0; border-top: 0; }
.jr-plan-link .jr-btn { margin-top: 12px; }

/* ══════════════════════════════════════════════════════════
   import — an exchange's own record of the year
   ══════════════════════════════════════════════════════════ */

.jr-import-form { margin-top: 14px; }
.jr-import-form .jr-btn { margin-top: 14px; }

/* ── which column is which ───────────────────────────────── */

.jr-map { list-style: none; margin: 14px 0 0; padding: 0; }

.jr-map > li {
  display: grid; grid-template-columns: 160px minmax(0, 1fr);
  gap: 8px 12px; align-items: center;
  padding: 7px 0; border-bottom: 1px solid var(--line2);
}
.jr-map > li:last-child { border-bottom: 0; }

.jr-map-name { font-size: 13.5px; color: var(--ink); }
.jr-map-name em {
  display: block; font-style: normal; font-size: 11px; color: var(--brand);
  text-transform: lowercase;
}

/* ── the positions a file came to ────────────────────────── */

.jr-drafts { list-style: none; margin: 14px 0 0; padding: 0; }

.jr-drafts > li {
  display: grid;
  /* what it was · the figures · what to do with it */
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 6px 14px;
  align-items: start;
  padding: 11px 0;
  border-bottom: 1px solid var(--line2);
  font-size: 13px;
}
.jr-drafts > li:last-child { border-bottom: 0; }

/* One already imported is listed and greyed rather than hidden: a
   file whose rows quietly disappeared is a file you cannot reconcile
   against the exchange's own count. */
.jr-drafts > li.done { opacity: .5; }

.jr-draft-what strong { font-size: 13.5px; }
.jr-draft-dir { color: var(--ink2); font-size: 12px; text-transform: lowercase; }
.jr-draft-what em {
  display: block; margin-top: 2px;
  font-style: normal; font-size: 11.5px; color: var(--ink3); line-height: 1.5;
}

.jr-draft-figs {
  display: flex; flex-direction: column; gap: 2px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px; color: var(--ink2);
}
/* ── Not coloured ────────────────────────────────────────
   Colour in this journal means rule adherence, and an import has no
   idea whether a rule was followed — it has a list of executions. A
   green number here would be the one thing this application says it
   never does. */
.jr-draft-made { color: var(--ink); }

.jr-draft-opt {
  display: flex; align-items: flex-start; gap: 7px;
  min-height: 26px; cursor: pointer; line-height: 1.45;
}
.jr-draft-opt input { margin-top: 3px; flex: 0 0 auto; }
.jr-draft-opt span { font-size: 12.5px; color: var(--ink2); }
.jr-draft-opt input:checked + span { color: var(--ink); font-weight: 600; }

/* A position the import thinks you already wrote down. Marked on the
   row, because the choice beside it is the one that is not obvious. */
.jr-drafts > li.match { background: var(--panel2); }

@media (max-width: 760px) {
  .jr-drafts > li { grid-template-columns: minmax(0, 1fr) auto; }
  .jr-draft-figs { grid-column: 2 / 3; grid-row: 1; text-align: right; align-items: flex-end; }
  .jr-draft-say  { grid-column: 1 / -1; grid-row: 2; }
  .jr-map > li   { grid-template-columns: 1fr; }
}

/* Both ways into the journal, at the top of the list: typing one and
   bringing a year in. The import link lived at the foot of the list
   and the first question asked about it was where it had gone. */
.jr-list-acts {
  display: flex; gap: 10px; flex-wrap: wrap;
  margin: 12px 0 4px;
}
/* A phone: two rows that line up, not five things wrapping as they
   fall. Log + Import on the first, the exchanges + sync on the
   second, the "synced at" line under them. */
@media (max-width: 600px) {
  .jr-list-acts { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: stretch; }
  .jr-list-acts .jr-act-log, .jr-list-acts .jr-act-imp { display: none; }
  .jr-list-acts .jr-btn { min-height: 42px; padding: 0 14px; justify-content: center; white-space: nowrap; width: 100%; box-sizing: border-box; }
  .jr-list-acts .jr-btn-ex { justify-content: flex-start; min-width: 0; overflow: hidden; gap: 6px; padding: 0 10px; }
  .jr-list-acts .jr-sync-all { min-width: 44px; }
  .jr-list-acts .jr-add { display: block; }
  .jr-list-acts .jr-add > summary { width: 44px; padding: 0; font-size: 22px; line-height: 1; }
  /* Five marks and a count fit; five marks and "exchanges" do not. */
  .jr-list-acts .jr-ex-word { display: none; }
  /* Many exchanges: four marks and "+N" — never a row of marks cut
     off at the edge of the button. */
  .jr-list-acts .jr-ex-marks > :nth-child(n+5) { display: none; }
  .jr-list-acts .jr-ex-more { display: inline; }
  .jr-list-acts .jr-ex-more ~ .jr-ex-count { display: none; }
  .jr-list-acts .jr-sync-brief { grid-column: 1 / -1; font-size: 12px; margin-top: -2px; }
}

/* ── Import: the name box, only for an exchange not on the list ──
   Shown by the list's own state rather than by a script, so it
   cannot be left showing beside a venue that was chosen. */
.jr-venue-other { display: none; }
.jr-import-form:has(#venue option[value=""]:checked) .jr-venue-other { display: block; }

/* Import: select / deselect all, above the waiting list */
.jr-draft-all { display: flex; gap: 18px; margin: 4px 0 2px; }
.jr-draft-all[hidden] { display: none; }
.jr-draft-all .jr-link-btn { min-height: 32px; }

/* ── trade list: what each row is asking for ─────────────────
   Open (brand), waiting for its review (amber), done (quiet). The
   amber is a to-do, not a judgement — it says nothing about whether
   the trade was any good, and it goes the moment the review is
   marked done. */
.jr-due {
  display: inline-block; padding: 2px 7px; border-radius: 999px;
  background: var(--warn-soft); color: var(--warn);
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
}
.jr-row.due { box-shadow: inset 2px 0 0 var(--warn); background: color-mix(in srgb, var(--warn-soft) 75%, transparent); }
.jr-row.due:hover { background: var(--warn-soft); }
/* Open and still without its thesis: the strongest amber on the
   page — the one thing to do right now, while the reason is fresh. */
.jr-row.live.ask { box-shadow: inset 3px 0 0 var(--before); background: color-mix(in srgb, var(--before) 16%, transparent); }
.jr-row.live.ask:hover { background: color-mix(in srgb, var(--before) 24%, transparent); }
.jr-row.live.ask .jr-row-sym, .jr-row.live.ask .jr-c { color: var(--ink); }
.jr-row:not(.live):not(.due) .jr-row-sym,
.jr-row:not(.live):not(.due) .jr-c { color: var(--ink3); }
.jr-imp {
  display: inline-block; margin-left: 8px; padding: 0 6px; border-radius: 5px;
  border: 1px solid var(--line); color: var(--ink3);
  font-family: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 10px; font-weight: 600; line-height: 16px; letter-spacing: .04em;
  vertical-align: 2px; white-space: nowrap;
}
.jr-show { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 10px; }
/* On a phone the filters are one strip that scrolls sideways, which
   is what every phone list does with its chips; wrapped, four of them
   took two ragged rows. */
@media (max-width: 600px) {
  .jr-show {
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; margin-left: -16px; margin-right: -16px; padding: 0 16px;
  }
  .jr-show::-webkit-scrollbar { display: none; }
  .jr-show a { flex: none; }
}
.jr-show a {
  padding: 6px 12px; border-radius: 999px; border: 1px solid var(--line);
  font-size: 13px; color: var(--ink2); text-decoration: none; min-height: 32px;
  display: inline-flex; align-items: center; gap: 6px;
}
.jr-show a b { font-weight: 700; color: var(--ink); }
.jr-show a.on { background: var(--ink); border-color: var(--ink); color: var(--panel); }
.jr-show a.on b { color: var(--panel); }
.jr-show a.jr-show-review:not(.on) b { color: var(--warn); }

/* Stop and Recenter sit with the replay controls. */
.jr-tf .jr-stop   { color: var(--ink); }
.jr-tf .jr-center { white-space: nowrap; }

/* ── Rules: show all, broken, kept, or unanswered ───────────
   The radios sit ahead of the lists in the card, and :has() on the
   card does the filtering — a band left with nothing to show goes
   too, rather than leaving its heading over an empty list. */
.jr-rule-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 4px; }
.jr-rf-in { position: absolute; opacity: 0; pointer-events: none; }
.jr-rf {
  display: inline-flex; align-items: center; gap: 6px; min-height: 32px;
  padding: 5px 12px; border-radius: 999px; border: 1px solid var(--line);
  font-size: 13px; color: var(--ink2); cursor: pointer;
}
.jr-rf b { color: var(--ink); }
.jr-rf-broke b { color: var(--bad); }
.jr-rf-kept b  { color: var(--good); }
.jr-rf-in:checked + .jr-rf { background: var(--ink); border-color: var(--ink); color: var(--panel); }
.jr-rf-in:checked + .jr-rf b { color: var(--panel); }
.jr-rf-in:focus-visible + .jr-rf { outline: 2px solid var(--brand); outline-offset: 2px; }
.jr-rf-in:disabled + .jr-rf { opacity: .4; cursor: default; }

#rules:has(#rf-broke:checked) .jr-ruled > li:not(.broke),
#rules:has(#rf-kept:checked)  .jr-ruled > li:not(.kept),
#rules:has(#rf-quiet:checked) .jr-ruled > li:not(.quiet) { display: none; }
#rules:has(#rf-broke:checked) .jr-ruling:not(:has(li.broke)),
#rules:has(#rf-kept:checked)  .jr-ruling:not(:has(li.kept)),
#rules:has(#rf-quiet:checked) .jr-ruling:not(:has(li.quiet)) { display: none; }

/* ── (i): the explanation behind a title ────────────────────
   Titles say what a thing is in a word or two; why it works the way
   it does is here, on hover with a mouse and on tap on a phone (the
   span takes focus). Pure CSS, so it cannot be left open. */
.jr-i {
  position: relative; display: inline-grid; place-items: center;
  width: 16px; height: 16px; margin-left: 6px; vertical-align: 1px;
  border: 1px solid var(--line); border-radius: 50%;
  font: 700 10px/1 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0; text-transform: none; font-style: normal;
  color: var(--ink3); cursor: help; outline: none;
}
.jr-i:hover, .jr-i:focus { color: var(--brand); border-color: var(--brand); }
.jr-i-pop {
  display: none; position: absolute; z-index: 30; top: calc(100% + 8px); left: -10px;
  /* Never wider than the screen; and pulled back inside it by a
     script in the page's foot when it would run off the right edge
     (every (i) near the right of a phone did). */
  width: max-content; max-width: min(340px, calc(100vw - 16px));
  padding: 10px 12px; border-radius: 9px;
  background: var(--panel2); border: 1px solid var(--line); border-left: 3px solid var(--brand);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  font-size: 13px; font-weight: 400; line-height: 1.55; text-align: left;
  color: var(--ink2); white-space: normal;
}
.jr-i:hover .jr-i-pop, .jr-i:focus .jr-i-pop { display: block; }


/* ── connected exchange ───────────────────────────────────── */
.jr-conn-state { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 4px 0 8px; font-size: 14px; }
.jr-conn-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); }
.jr-conn-state .mono { color: var(--ink3); font-size: 12px; }
.jr-conn-state [data-connect-last] { color: var(--ink3); font-size: 13px; }
.jr-note.bad { color: var(--bad); }
.jr-conn-new > summary { display: inline-flex; list-style: none; cursor: pointer; }
.jr-conn-new > summary::-webkit-details-marker { display: none; }
.jr-conn-new[open] > summary { margin-bottom: 10px; }
.jr-conn-steps { margin: 0 0 12px; padding-left: 20px; font-size: 14px; line-height: 1.6; color: var(--ink2); }
.jr-conn-steps a { color: var(--brand); }

.jr-masked { -webkit-text-security: disc; text-security: disc; }

/* ── the sync, as a quiet line ─────────────────────────────── */
/* :not([hidden]) so that a row the page hides stays hidden whatever else is loaded after this rule. */
.jr-sync:not([hidden]) { display: flex; }
.jr-sync { flex-wrap: wrap; align-items: center; gap: 4px 7px; margin: 0 0 10px; font-size: 12.5px; color: var(--ink3); }
.jr-sync [data-connect-said] { flex: 1 1 auto; min-width: 0; }
/* A refusal is a sentence: its own line under the status, never a column beside it. */
.jr-sync > .jr-sync-bad { flex: 1 1 100%; order: 3; }
.jr-sync > .jr-sync-bad[hidden] { display: none; }
.jr-sync .jr-sync-go { flex: 0 0 auto; margin-left: auto; }
.jr-sync .jr-conn-dot { width: 7px; height: 7px; }
.jr-sync.on .jr-conn-dot { animation: jr-pulse 1s ease-in-out infinite; }
.jr-sync-bad { color: var(--bad); text-decoration: none; }
@keyframes jr-pulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .jr-sync.on .jr-conn-dot { animation: none; } }

/* ── Where a trade came from: Logged / File / Live ───────────
   Told apart by shape before colour — none of them is a verdict, so
   none uses the green and red that mean rule adherence. */
.jr-src {
  display: inline-flex; align-items: center; gap: 4px;
  margin-left: 8px; padding: 0 6px; border-radius: 5px;
  font-family: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 10px; font-weight: 600; line-height: 16px; letter-spacing: .04em;
  vertical-align: 2px; white-space: nowrap;
}
.jr-src.log  { color: var(--ink2); border: 1px solid var(--line); }
.jr-src.log::before  { content: '✎'; font-size: 9px; }
.jr-src.file { color: var(--ink2); border: 1px dashed var(--ink3); }
.jr-src.file::before { content: '⇪'; font-size: 9px; }
/* Synced: neutral like the other two. Green in this list means a
   position that is still OPEN, and an origin tag in the same green
   read as a second "open". */
.jr-src.live { color: var(--ink2); border: 1px solid var(--line); }
.jr-src.live::before { content: '⇄'; font-size: 9px; }

.jr-sync-go {
  margin-left: 4px; padding: 3px 10px; min-height: 26px; border-radius: 999px;
  border: 1px solid var(--line); background: transparent; color: var(--ink2);
  font: inherit; font-size: 12px; cursor: pointer;
}
.jr-sync-go:hover { color: var(--brand); border-color: var(--brand); }
.jr-sync-go:disabled { opacity: .5; cursor: default; }

/* ── Live mode: the thesis first ─────────────────────────────
   An open trade without its thesis says so in the list (the Before
   amber, filled — it is the one thing to do now) and in a line at
   the top of every journal page until it has one. */
.jr-thesis {
  display: inline-block; padding: 2px 7px; border-radius: 999px;
  background: var(--before); color: var(--bg, #fff);
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
}
.jr-banner {
  display: flex; flex-direction: column; gap: 6px;
  max-width: 1200px; margin: 10px auto 0; padding: 0 16px;
}
.jr-banner a {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 14px; border-radius: 12px; text-decoration: none;
  background: var(--before-soft); border: 1px solid var(--before-line); color: var(--ink);
  font-size: 14px;
}
.jr-banner a:hover { border-color: var(--before); }
.jr-banner-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--before); flex: none; }

/* The seal form, inside the Before band */
.jr-seal { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.jr-seal .jr-label { margin-top: 6px; }
.jr-seal-plan .jr-plan-pick { margin-top: 4px; }
.jr-seal-go { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.jr-seal-go[hidden], .jr-seal-empty[hidden] { display: none; }
.jr-seal-empty {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px;
  padding: 10px 12px; border-radius: 10px; border: 1px solid var(--before-line); background: var(--panel, transparent);
}
.jr-seal-empty p { margin: 0; flex: 1 1 220px; }
.jr-seal-first { margin: 10px 0 4px; }

/* ── Exchanges: one tile per exchange ────────────────────────
   The state pill is the one thing read first: Live (brand), Connected
   but only while a page is open (amber — something to switch on),
   Needs attention, Not connected, Coming. */
.jr-ex-grid {
  display: grid; gap: 14px; margin-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  align-items: stretch;   /* the tiles of a row are one size; a row of tiles to connect is not as tall as one with facts in it */
}
.jr-ex {
  border: 1px solid var(--line); border-radius: 14px; padding: 16px;
  background: var(--panel2); display: flex; flex-direction: column; gap: 10px; min-width: 0;
}
.jr-ex.live { border-color: color-mix(in srgb, var(--brand) 55%, var(--line)); }
.jr-ex.soon { opacity: .72; }
.jr-ex-head { display: flex; align-items: center; gap: 12px; }
.jr-ex-head > div { flex: 1; min-width: 0; }
.jr-ex-head h3 { margin: 0; font-size: 16px; }
.jr-ex-head p { margin: 2px 0 0; font-size: 12.5px; color: var(--ink3); }
.jr-ex-logo { width: 40px; height: 40px; flex: none; color: var(--ink); }
.jr-ex-pill {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--line); color: var(--ink2);
}
.jr-ex-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink3); }
.jr-ex-pill.live { color: var(--brand); border-color: color-mix(in srgb, var(--brand) 45%, transparent); }
.jr-ex-pill.live .dot { background: var(--brand); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 25%, transparent); }
.jr-ex-pill.page { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.jr-ex-pill.page .dot { background: var(--warn); }
.jr-ex-pill.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
.jr-ex-pill.bad .dot { background: var(--bad); }
.jr-ex-pill.soon { color: var(--ink3); }
.jr-ex-sum { margin: 0; font-size: 13.5px; color: var(--ink2); }
.jr-ex-sum.bad { color: var(--bad); }
.jr-ex-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; margin: 0; }
.jr-ex-facts div { min-width: 0; }
.jr-ex-facts dt { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink3); }
.jr-ex-facts dd { margin: 2px 0 0; font-size: 14px; color: var(--ink); overflow-wrap: anywhere; }
.jr-ex-facts dd > span { color: var(--ink3); font-size: 12.5px; display: inline-block; /* "22:49 · 1 min ago" wraps as two pieces, never mid-phrase */ }
.jr-ex-acts { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: auto; }
.jr-ex-acts form { display: inline; }
.jr-ex .jr-conn-new summary { display: inline-flex; }

/* The Trades list's third button: the exchange, and whether it is fine */
.jr-btn-ex { display: inline-flex; align-items: center; gap: 8px; }
.jr-btn-ex-mark { flex: none; color: var(--ink); }
.jr-ex-marks { display: inline-flex; align-items: center; gap: 8px; flex: none; }
.jr-ex-more { display: none; font-size: 13px; font-weight: 600; color: var(--ink2); flex: none; }
.jr-ex-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); }
.jr-ex-dot.bad { background: var(--bad); }
.jr-import-alt { margin: 0 0 10px; }
.jr-venue-mark { flex: none; vertical-align: middle; margin-right: 8px; color: var(--ink); }
.jr-c.venue > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 1080px) { .jr-list .jr-c.venue { display: flex; align-items: center; } }
.jr-venue .jr-venue-mark { vertical-align: -3px; margin-right: 5px; }
.jr-ex .jr-form { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.jr-ex .jr-form .jr-label { margin-top: 6px; }
.jr-ex .jr-form button[type=submit] { margin-top: 14px; align-self: flex-start; }
.jr-ex [data-connect-said]:not([hidden]) { margin: 2px 0 0; }

/* The one sync button beside the exchanges: square, and turning while it works */
.jr-sync-all { min-width: 44px; padding-left: 0; padding-right: 0; justify-content: center; font-size: 18px; }
.jr-sync-all span { display: inline-block; line-height: 1; }
.jr-sync-all.on { pointer-events: none; }
.jr-sync-all.on span { animation: jr-turn 1s linear infinite; }
@keyframes jr-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .jr-sync-all.on span { animation: none; } .jr-sync-all.on { opacity: .6; } }
.jr-sync[hidden] { display: none; }
.jr-sync-brief { font-size: 12.5px; color: var(--ink3); align-self: center; display: inline-flex; gap: 6px; flex-wrap: wrap; }
.jr-sync-brief .jr-sync-bad { color: var(--bad); text-decoration: none; }
.jr-banner-venue { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; color: var(--ink2); }
.jr-seal-shots { display: flex; gap: 8px; flex-wrap: wrap; list-style: none; margin: 4px 0 0; padding: 0; }
.jr-seal-shots[hidden] { display: none; }
.jr-seal-shots img { height: 64px; border-radius: 8px; border: 1px solid var(--line); }
.jr-seal-shots li { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.jr-seal-shots .jr-link-btn { font-size: 12px; }

/* The questions a phase asks, as chips: one press puts the heading in. */
.jr-prompts { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.jr-prompt {
  padding: 4px 10px; border-radius: 999px; border: 1px dashed var(--line);
  background: transparent; color: var(--ink2); font: inherit; font-size: 12.5px; cursor: pointer;
}
.jr-prompt:hover { border-style: solid; color: var(--ink); background: var(--panel2); }
.jr-say-edit-acts { display: flex; gap: 12px; align-items: center; margin-top: 6px; }
[data-say-edit][hidden] { display: none; }
.jr-review-end { display: flex; justify-content: flex-end; margin: 14px 0 4px; }
@media (max-width: 640px) { .jr-review-end .jr-btn { width: 100%; justify-content: center; min-height: 48px; } }

/* ── The matrix over time ────────────────────────────────────
   A sparkline in each cell: the cell's share of the trades plotted
   in each bucket, in the cell's own colour — rule adherence, as
   everywhere. A dotted line marks a half. */
.jr-mx-range { display: flex; align-items: center; gap: 6px; margin: 16px 0 -8px; font-size: 12px; color: var(--ink3); }
.jr-mx-range span { margin-right: 4px; }
.jr-mx-r {
  padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line); background: transparent;
  color: var(--ink2); font: inherit; font-size: 12px; cursor: pointer;
}
.jr-mx-r.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.jr-cell .spark { position: absolute; right: 10px; bottom: 10px; width: 120px; height: 36px; overflow: visible; }
.jr-cell.good .spark { color: var(--good); }
.jr-cell.bad  .spark { color: var(--bad); }
.jr-cell .spark .ln  { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.jr-cell .spark .mid { stroke: currentColor; stroke-opacity: .25; stroke-dasharray: 2 3; stroke-width: 1; }
.jr-cell .spark .end { fill: currentColor; stroke: var(--panel); stroke-width: 2; }
.jr-cell .spark .pt  { fill: currentColor; }
.jr-cell .spark-tip {
  position: absolute; right: 10px; bottom: 50px; padding: 3px 8px; border-radius: 6px;
  background: var(--ink); color: var(--bg); font-size: 11px; white-space: nowrap; pointer-events: none;
}
.jr-cell .spark-tip[hidden] { display: none; }
@media (max-width: 420px) { .jr-cell .spark { width: 80px; height: 28px; } }

/* ── the background job's own record ─────────────────────── */
.jr-bg-runs { margin-top: 16px; }
.jr-bg-runs > summary { cursor: pointer; font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 8px; }
.jr-bg-runs .jr-bg-count { font-weight: 400; color: var(--ink3); font-size: 12px; margin-left: auto; }
.jr-bg-log {
  margin: 12px 0 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel2); font-family: var(--mono, ui-monospace, monospace); font-size: 11.5px;
  line-height: 1.6; color: var(--ink2); white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow: auto;
}

/* A pasted private key: a block, small, left alone by the masking. */
.jr-pem { font-size: 11.5px; line-height: 1.4; min-height: 110px; resize: vertical; white-space: pre; overflow-x: auto; }

/* An exchange's name links to its perpetuals page: plain until hovered, with a small arrow-out mark. */
.jr-ex-link { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 5px; }
.jr-ex-link:hover, .jr-ex-link:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.jr-ex-ext { opacity: .55; flex: none; }
.jr-ex-link:hover .jr-ex-ext { opacity: 1; }

/* ── Review, Explore and Analysis ────────────────────────────
   Wide, because a table of twelve columns is not a phone-width
   thing. Colour keeps its one meaning: green and red are followed
   and broke. The shading on the Review queue is amber, and it is
   how long something has waited, never how it went. */

.jr-main.jr-x { max-width: 1240px; }
.jr-x .jr-card { margin-bottom: 16px; }
.jr-x-lead { font-size: 14px; color: var(--ink2); margin: 2px 0 14px; line-height: 1.6; }
.jr-x-tools { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.jr-x-h { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink3); margin: 22px 0 6px; font-weight: 600; }

.jr-x-tabs { display: flex; gap: 4px; margin: 0 0 16px; border-bottom: 1px solid var(--line2); }
.jr-x-tabs a {
  padding: 8px 14px; font-size: 13px; color: var(--ink3); text-decoration: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.jr-x-tabs a:hover { color: var(--ink); }
.jr-x-tabs a.on { color: var(--ink); border-bottom-color: var(--ink2); }

.jr-x-search { display: grid; grid-template-columns: 1fr auto; gap: 8px; }
.jr-x-filters { display: grid; gap: 8px; margin-bottom: 6px; }
.jr-x-filter { display: grid; grid-template-columns: minmax(120px, 1fr) minmax(110px, .7fr) minmax(120px, 1.2fr); gap: 8px; }
.jr-x-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.jr-x-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.jr-x-acts { display: flex; gap: 10px; margin-top: 16px; align-items: center; flex-wrap: wrap; }
@media (max-width: 640px) {
  .jr-x-filter { grid-template-columns: 1fr 1fr; }
  .jr-x-filter [data-f-value] { grid-column: 1 / -1; }
  .jr-x-row { grid-template-columns: 1fr; gap: 0; }
}

.jr-x-cols { margin-top: 14px; font-size: 13px; color: var(--ink2); }
.jr-x-cols summary { cursor: pointer; color: var(--ink3); }
.jr-x-cols summary .n { font-size: 11px; background: var(--panel3); border-radius: 8px; padding: 1px 7px; margin-left: 4px; }
.jr-x-colgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px 14px; margin-top: 10px; }
.jr-x-colgrid label { display: flex; gap: 6px; align-items: center; font-size: 12px; }

.jr-x-asked { margin: 22px 0 8px; padding: 12px 14px; background: var(--panel2); border: 1px solid var(--line2); border-radius: 11px; }
.jr-x-asked .said { margin: 0; font-size: 14px; color: var(--ink); }
.jr-x-sql { margin-top: 8px; font-size: 12px; color: var(--ink3); }
.jr-x-sql summary { cursor: pointer; }
.jr-x-sql pre, .jr-x-step pre {
  margin: 8px 0 0; padding: 10px 12px; background: var(--bg); border: 1px solid var(--line2); border-radius: 8px;
  font-size: 11.5px; line-height: 1.6; color: var(--ink2); white-space: pre-wrap; word-break: break-word;
}

.jr-x-scroll { overflow-x: auto; margin: 6px -4px 0; padding: 0 4px; }
.jr-x-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.jr-x-table th {
  text-align: left; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; font-weight: 600;
  color: var(--ink3); padding: 8px 10px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.jr-x-table th a { color: inherit; text-decoration: none; }
.jr-x-table th a:hover { color: var(--ink); }
.jr-x-table td { padding: 8px 10px; border-bottom: 1px solid var(--line2); vertical-align: top; color: var(--ink2); }
.jr-x-table td a { color: var(--ink); text-decoration: none; }
.jr-x-table td a:hover { text-decoration: underline; text-underline-offset: 3px; }
.jr-x-table .num { text-align: right; white-space: nowrap; }
.jr-x-table .dim { color: var(--ink3); }
.jr-x-table tbody tr:hover td { background: var(--panel2); }
.jr-x-table tr.jr-x-found td { padding-top: 0; font-size: 12px; color: var(--ink3); border-bottom: 1px solid var(--line); }
.jr-x-found .where { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; margin-right: 4px; }
.jr-x-found mark { background: var(--warn-soft); color: var(--ink); border-radius: 3px; padding: 0 2px; }

.jr-x-chip { display: inline-block; font-size: 11px; padding: 1px 8px; border-radius: 9px; font-weight: 600; }
.jr-x-chip.followed { background: var(--good-soft); color: var(--good); }
.jr-x-chip.broke { background: var(--bad-soft); color: var(--bad); }
.jr-x-bar { display: inline-block; width: 54px; height: 6px; border-radius: 3px; background: var(--bad-soft); vertical-align: middle; overflow: hidden; }
.jr-x-bar i { display: block; height: 100%; background: var(--good); }
.jr-x-bar.wide { width: 100%; max-width: 260px; height: 8px; }

.jr-x-keep { display: flex; gap: 8px; margin-top: 18px; max-width: 420px; }
.jr-x-keep .jr-input { flex: 1; }

.jr-x-saved { display: grid; gap: 2px; }
.jr-x-kept { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--line2); }
.jr-x-kept a { color: var(--ink); text-decoration: none; font-size: 14px; min-width: 0; }
.jr-x-kept a .kind { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink3); margin: 0 8px; }
.jr-x-kept a .what { display: block; font-size: 12px; color: var(--ink3); margin-top: 2px; }

.jr-x-answer { margin: 20px 0 6px; padding: 14px 16px; background: var(--panel2); border: 1px solid var(--line); border-radius: 11px; font-size: 15px; line-height: 1.7; color: var(--ink); }
.jr-x-step { margin: 6px 0; font-size: 13px; color: var(--ink2); }
.jr-x-step summary { cursor: pointer; }
.jr-x-step summary .n { display: inline-block; min-width: 20px; text-align: center; background: var(--panel3); border-radius: 8px; font-size: 11px; margin-right: 6px; }

.jr-x-key { padding: 10px 0 14px; border-bottom: 1px solid var(--line2); }
.jr-x-key:last-child { border-bottom: 0; }
.jr-x-keyform { display: flex; gap: 8px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.jr-x-keyform .jr-input { flex: 1; min-width: 200px; }

/* Review: oldest first, shaded by how long it has waited. */
.jr-rv { display: grid; gap: 6px; margin-top: 8px; }
.jr-rv-row { display: flex; align-items: center; gap: 10px; border: 1px solid var(--line2); border-radius: 11px; background: var(--panel2); padding-right: 10px; }
.jr-rv-link { display: grid; grid-template-columns: auto minmax(90px, 140px) 1fr auto auto; gap: 12px; align-items: center; flex: 1; min-width: 0; padding: 11px 12px; color: inherit; text-decoration: none; }
a.jr-rv-row { display: grid; grid-template-columns: auto minmax(90px, 140px) 1fr auto auto; gap: 12px; align-items: center; padding: 11px 12px; color: inherit; text-decoration: none; }
.jr-rv-main { font-size: 14px; font-weight: 600; color: var(--ink); }
.jr-rv-when { font-size: 12px; color: var(--ink3); }
.jr-rv-gaps { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.jr-rv-go { font-size: 12px; color: var(--ink2); }
.jr-x-gap { font-size: 11px; color: var(--ink3); border: 1px solid var(--line); border-radius: 9px; padding: 1px 8px; }
.jr-rv-row.aging { box-shadow: inset 3px 0 0 var(--warn-soft); }
.jr-rv-row.slow { box-shadow: inset 3px 0 0 var(--warn); background: color-mix(in srgb, var(--warn-soft) 55%, var(--panel2)); }
.jr-rv-row.late { box-shadow: inset 3px 0 0 var(--bad); background: color-mix(in srgb, var(--bad-soft) 60%, var(--panel2)); }
.jr-rv-row.ask { box-shadow: inset 3px 0 0 var(--warn); background: var(--warn-soft); }
.jr-rv-row.done { opacity: .8; }
.jr-rv-done { margin: 0; }
@media (max-width: 720px) {
  /* A phone: a row is a few thin lines, the button at the top right — not a tall card. */
  .jr-rv-row { position: relative; padding: 0; }
  .jr-rv-link, a.jr-rv-row { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; padding: 8px 118px 8px 10px; }
  .jr-rv-done { position: absolute; top: 8px; right: 8px; }
  .jr-rv-done .jr-btn, .jr-rv-done .jr-link-btn { min-height: 34px; padding: 4px 10px; font-size: 12px; }
  .jr-rv-main { font-size: 14px; }
  .jr-rv-when { flex: 1 1 100%; font-size: 12px; }
  .jr-rv-verdict, .jr-rv-gaps { display: contents; }
  .jr-rv-row .jr-x-chip, .jr-rv-row .jr-x-gap { font-size: 11px; padding: 1px 7px; }
  .jr-rv-row.done .jr-rv-link { padding-right: 70px; }
}

/* Analysis */
.jr-an-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.jr-an-head h2 { margin: 0; font-size: 20px; }
.jr-an-head h2 a { color: var(--ink); text-decoration: none; }
.jr-an-line { font-size: 15px; line-height: 1.65; color: var(--ink); margin: 10px 0 16px; max-width: 70ch; }
.jr-an-halves { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.jr-an-half { background: var(--panel2); border: 1px solid var(--line2); border-radius: 11px; padding: 14px 16px; }
.jr-an-half h3 { margin: 0 0 6px; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink3); }
.jr-an-big { font-size: 30px; font-weight: 600; color: var(--ink); line-height: 1.2; }
@media (max-width: 640px) { .jr-an-halves { grid-template-columns: 1fr; } }
.jr-an-curve { margin-top: 16px; }
.jr-an-svg { display: block; width: 100%; height: 120px; margin-top: 6px; background: var(--panel2); border: 1px solid var(--line2); border-radius: 11px; }
.jr-an-svg .zero { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.jr-an-svg .all { fill: none; stroke: var(--ink2); stroke-width: 2; vector-effect: non-scaling-stroke; }
.jr-an-svg .fol { fill: none; stroke: var(--good); stroke-width: 2; vector-effect: non-scaling-stroke; }
.jr-an .k { display: inline-block; width: 14px; height: 3px; border-radius: 2px; vertical-align: middle; margin: 0 4px; }
.jr-an .k.all { background: var(--ink2); }
.jr-an .k.fol { background: var(--good); }
.jr-an-rules { list-style: none; margin: 0; padding: 0; font-size: 14px; color: var(--ink2); }
.jr-an-rules li { padding: 5px 0; border-bottom: 1px solid var(--line2); }
.jr-an-rules .n { display: inline-block; min-width: 34px; color: var(--bad); font-weight: 600; }
.jr-an-buckets { display: grid; gap: 6px; max-width: 520px; }
.jr-an-bucket { display: grid; grid-template-columns: 120px 1fr 90px; gap: 10px; align-items: center; font-size: 13px; color: var(--ink2); }
.jr-an-bucket .jr-x-bar { width: 100%; }
.jr-an-bucket .val small { color: var(--ink3); }

/* ── the AI behind Ask, one row each ───────────────────────── */
/* the providers as tiles, several to a row on a wide screen — like the exchanges */
.jr-ai-grid { display: grid; gap: 12px; margin-top: 10px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr)); grid-auto-rows: 1fr; align-items: stretch; }
.jr-ai-grid > .jr-ai { margin-top: 0; min-width: 0; }
.jr-ai { display: flex; flex-direction: column; gap: 12px; padding: 14px; margin-top: 10px; border: 1px solid var(--line2); border-radius: 12px; }
.jr-ai.on { border-color: var(--accent, #0f5f50); background: color-mix(in srgb, var(--accent, #0f5f50) 7%, transparent);
            border-width: 2px; padding: 13px; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #0f5f50) 14%, transparent); }
.jr-ai.ready { background: var(--panel); }
.jr-ai.off { border-style: dashed; background: var(--panel2); }
img.jr-ai-logo { background: #fff; padding: 6px; border: 1px solid rgba(127,127,127,.25); box-sizing: border-box; }
.jr-ai.off .jr-ai-logo { filter: grayscale(1); opacity: .55; }
.jr-ai.off .jr-ai-name { color: var(--ink2); }
.jr-ai-tag.ready { background: transparent; color: var(--good); border: 1px solid var(--good-line, var(--good)); }
.jr-ai-tag.off { background: var(--panel3); color: var(--ink3); }
.jr-ai-body { flex: 1; min-width: 0; }
.jr-ai-name { font-weight: 600; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.jr-ai-tag { font-size: 12px; font-weight: 500; padding: 2px 8px; border-radius: 999px; background: var(--accent, #0f5f50); color: #fff; }
.jr-ai-logo { flex: none; width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; font-weight: 700; font-size: 18px; color: #fff; background: #5b6b66; object-fit: contain; }
.jr-ai-gemini { background: #3c6fd8; } .jr-ai-groq { background: #d9531e; } .jr-ai-openai { background: #12805c; } .jr-ai-claude { background: #b8643c; }
.jr-ai-openrouter { background: #6b4fd1; } .jr-ai-mistral { background: #e0922a; }

/* ── Ask as a conversation ─────────────────────────────────── */
.jr-chat-turn { margin: 18px 0 8px; padding-bottom: 14px; border-bottom: 1px solid var(--line2); }
.jr-chat-turn:last-of-type { border-bottom: 0; }
.jr-chat-q { display: flex; justify-content: flex-end; }
.jr-chat-q .bubble { max-width: 88%; padding: 9px 14px; border-radius: 16px 16px 4px 16px; background: color-mix(in srgb, var(--brand) 16%, var(--panel)); border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--line)); color: var(--ink); font-size: 15px; line-height: 1.5; overflow-wrap: anywhere; }
.jr-chat-a { margin-top: 12px; max-width: 100%; border-left: 3px solid var(--line); padding-left: 12px; }
.jr-chat-turn .jr-x-answer { margin: 0; background: var(--panel2); border: 1px solid var(--line); }
/* a question is tinted with the brand colour, an answer is the plain panel: told apart at a glance */
.jr-chat-a.jr-chat-live { border-left-color: var(--brand); }
.jr-chat-ran { margin: 8px 0 0; font-size: 13px; color: var(--ink2); }
.jr-chat-ran > summary { cursor: pointer; }
.jr-chat-save { margin: 10px 0 2px; }
/* The question box rides at the bottom whatever the scroll, so a
   follow-up is always one tap away. On a phone it sits just above
   the tab bar and is kept slim: one line, no label, and the
   secondary controls appear only while it is being typed in. */
.jr-chat-form {
  margin-top: 18px;
  position: sticky; bottom: calc(var(--bar) + env(safe-area-inset-bottom, 0px)); z-index: 20;
  padding: 8px 0 10px; background: color-mix(in srgb, var(--bg) 94%, transparent);
  border-top: 1px solid var(--line);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
@media (min-width: 860px) { .jr-chat-form { bottom: 0; } }
@media (max-width: 859px) {
  .jr-chat-form { margin-left: -4px; margin-right: -4px; padding-left: 4px; padding-right: 4px; }
  .jr-chat-form > .jr-label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .jr-chat-form .jr-x-acts { display: none; margin-top: 6px; }
  .jr-chat-form:focus-within .jr-x-acts { display: flex; }
  .jr-chat-box .jr-input { min-height: 42px; padding-top: 9px; padding-bottom: 9px; }
  .jr-chat-box .jr-btn { height: 42px; }
}
.jr-chat-box { display: flex; gap: 8px; align-items: flex-end; }
.jr-chat-box .jr-input { flex: 1; min-width: 0; resize: none; max-height: 18vh; }
.jr-chat-box .jr-btn { flex: none; height: 44px; }
@media (max-width: 560px) { .jr-chat-q .bubble { max-width: 94%; } }

/* the answer, as the page it was meant to be */
.jr-x-answer.md > :first-child { margin-top: 0; }
.jr-x-answer.md > :last-child { margin-bottom: 0; }
.jr-x-answer.md p { margin: 0 0 10px; }
.jr-x-answer.md h3, .jr-x-answer.md h4, .jr-x-answer.md h5, .jr-x-answer.md h6 { margin: 16px 0 6px; line-height: 1.3; color: var(--ink); }
.jr-x-answer.md h3 { font-size: 17px; } .jr-x-answer.md h4 { font-size: 16px; } .jr-x-answer.md h5, .jr-x-answer.md h6 { font-size: 15px; }
.jr-x-answer.md ul, .jr-x-answer.md ol { margin: 0 0 10px; padding-left: 22px; }
.jr-x-answer.md li { margin: 2px 0; }
.jr-x-answer.md strong { font-weight: 700; color: var(--ink); }
.jr-x-answer.md em { font-style: italic; color: var(--ink2); }
.jr-x-answer.md li::marker { color: var(--ink3); }
.jr-x-answer.md code { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .9em; padding: 1px 5px; border-radius: 5px; background: var(--panel3); }
.jr-x-answer.md .md-code { margin: 0 0 10px; padding: 10px 12px; border-radius: 8px; background: var(--panel3); overflow-x: auto; }
.jr-x-answer.md .md-code code { padding: 0; background: none; }
.jr-x-answer.md blockquote { margin: 0 0 10px; padding: 2px 12px; border-left: 3px solid var(--line); color: var(--ink2); }
.jr-x-answer.md hr { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }
.jr-x-answer.md a { color: var(--accent, var(--ink)); text-decoration: underline; }
.jr-x-answer.md .md-table { margin: 0 0 12px; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.jr-x-answer.md table { border-collapse: collapse; font-size: 14px; min-width: 100%; }
.jr-x-answer.md th, .jr-x-answer.md td { padding: 6px 10px; border-bottom: 1px solid var(--line2); text-align: left; white-space: nowrap; }
.jr-x-answer.md th { color: var(--ink2); font-weight: 600; font-size: 12px; letter-spacing: .03em; }

/* what it is doing while it works */
.jr-chat-live { padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); }
.jr-chat-live .live-head { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--ink); }
.jr-chat-live .live-step { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.jr-chat-live .live-clock { flex: none; font-variant-numeric: tabular-nums; color: var(--ink2); font-size: 13px; }
.jr-chat-live .spin { flex: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line); border-top-color: var(--ink2); animation: jr-turn .9s linear infinite; }
.jr-chat-live .live-log { margin: 10px 0 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--ink3); display: grid; gap: 3px; }
.jr-chat-live .live-log li { overflow-wrap: anywhere; }
.jr-chat-live .live-log li time { display: inline-block; min-width: 38px; font-variant-numeric: tabular-nums; color: var(--ink3); }
.jr-chat-live .jr-note { margin: 10px 0 0; }
.jr-chat-live.failed .spin { display: none; }
@media (prefers-reduced-motion: reduce) { .jr-chat-live .spin { animation: none; } }
.jr-xchart { margin-top: 12px; }

/* ── tables and columns on the SQL tab: a grid to tap, not a wall of text ── */
.jr-x-cols > .jr-note { margin: 8px 0 6px; }
.jr-x-find { margin: 4px 0 10px; max-width: 320px; }
.jr-x-tbl { margin: 8px 0; border: 1px solid var(--line2); border-radius: 10px; padding: 8px 10px; }
.jr-x-tbl > summary { cursor: pointer; color: var(--ink); }
.jr-x-tbl > summary .jr-note { margin-left: 6px; }
.jr-x-pick { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 6px; margin-top: 10px; }
.jr-x-col { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; text-align: left; cursor: pointer;
            padding: 6px 9px; border: 1px solid var(--line2); border-radius: 8px; background: var(--panel2); color: var(--ink); font: inherit; font-size: 12px; min-height: 34px; }
.jr-x-col:hover, .jr-x-col:focus-visible { border-color: var(--accent, #0f5f50); }
.jr-x-col .n { overflow-wrap: anywhere; }
.jr-x-col .t { flex: none; font-size: 10px; color: var(--ink3); text-transform: uppercase; letter-spacing: .04em; }
.jr-x-col[hidden], .jr-x-tbl[hidden] { display: none; }
@media (max-width: 640px) { .jr-x-pick { grid-template-columns: 1fr 1fr; } }

/* ── a plan's management card, with the account's rules above ─
   The account rules are shown read-only, set apart from the plan's
   own list so it is clear which ones a plan can change. The promote
   button takes a row of its own under the rule it moves, so it never
   squeezes the sentence on a phone. */
.jr-rule-inherited { margin: 4px 0 14px; padding-bottom: 6px; border-bottom: 1px dashed var(--line2); }
.jr-rules > li.inherited .jr-rule-text { color: var(--ink2, var(--ink)); }
.jr-rule-promote { margin: 14px 0 4px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); }

/* ── saved conversations beside Ask ────────────────────────── */
.jr-ask-layout { display: block; }
.jr-convos { margin: 0 0 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); padding: 8px 12px; }
.jr-convos > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink2); padding: 4px 0; }
.jr-convos > summary .n { font-weight: 400; color: var(--ink3); }
.jr-convo-new { margin: 6px 0 8px; }
.jr-convo-new .jr-btn { width: 100%; }
.jr-convos ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; }
.jr-convos li { display: flex; align-items: flex-start; gap: 4px; border-radius: 8px; min-width: 0; }
.jr-convos li.open { background: var(--panel3); }
/* A title is read, not guessed at: up to three lines, then an ellipsis; the full text is the tooltip. */
.jr-convos li .t { flex: 1; min-width: 0; padding: 9px 8px; font-size: 14px; line-height: 1.35; color: var(--ink); text-decoration: none; display: flex; gap: 8px; align-items: flex-start; }
.jr-convos li .t .tt { min-width: 0; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow-wrap: anywhere; }
.jr-convos li.open .t { font-weight: 600; }
.jr-convos li .ed, .jr-convos li .x { margin-top: 3px; }
.jr-convos li .tt .ab { display: block; font-size: 11px; font-weight: 600; letter-spacing: .02em; color: var(--ink3); margin-bottom: 1px; }
/* which trade a chat is about, and when each question was asked */
.jr-ask-about { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 10px 0 14px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); color: var(--ink); text-decoration: none; font-size: 14px; }
a.jr-ask-about:hover { border-color: var(--brand); }
.jr-ask-about .k { flex: 1 0 100%; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink3); }
.jr-ask-about .who { display: inline-flex; align-items: center; gap: 7px; }
.jr-ask-about .who .jr-dir { flex: none; width: 24px; height: 24px; font-size: 12px; border-radius: 7px; }
.jr-ask-about .st { font-size: 12px; font-weight: 600; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--line); color: var(--ink2); }
.jr-ask-about .st.is-open { color: var(--brand); border-color: var(--brand); }
.jr-ask-about .go { margin-left: auto; font-size: 13px; color: var(--ink2); }
.jr-ask-about.gone { color: var(--ink3); }
.jr-chat-when { margin: 18px 0 6px; text-align: center; font-size: 11px; color: var(--ink3); letter-spacing: .03em; }
.jr-convos li .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* What a conversation is doing, like the Claude app: working, a new answer, a failed one. */
.jr-convos li .st { flex: none; width: 10px; height: 10px; margin-top: 4px; border-radius: 50%; box-sizing: border-box; }
.jr-convos li .st[hidden] { display: none; }
.jr-convos li.is-working .st { border: 2px solid var(--line); border-top-color: var(--ink2); animation: jr-turn .9s linear infinite; width: 12px; height: 12px; margin-top: 3px; }
.jr-convos li.is-unread .st { background: var(--plan, #3b82f6); box-shadow: 0 0 0 3px color-mix(in srgb, var(--plan, #3b82f6) 22%, transparent); }
.jr-convos li.is-unread .t { font-weight: 600; }
.jr-convos li.is-failed .st { background: var(--bad); box-shadow: 0 0 0 3px var(--bad-soft); }
@media (prefers-reduced-motion: reduce) { .jr-convos li.is-working .st { animation: none; border-top-color: var(--line); background: var(--ink3); } }
.jr-ask-stop { display: inline; margin-left: 6px; }
.jr-ask-stop .jr-link-btn { font-size: inherit; }
.jr-convos li form { margin: 0; flex: none; }
.jr-convos li .x { border: 0; background: none; color: var(--ink3); font-size: 18px; line-height: 1; width: 34px; height: 34px; border-radius: 8px; cursor: pointer; }
.jr-convos li .x:hover, .jr-convos li .x:focus-visible { color: var(--bad); background: var(--bad-soft); }
.jr-convos li .ed { flex: none; width: 34px; height: 34px; display: grid; place-items: center; font-size: 15px; color: var(--ink3); text-decoration: none; border-radius: 8px; }
.jr-convos li .ed:hover, .jr-convos li .ed:focus-visible { color: var(--ink); background: var(--panel3); }
.jr-convos li.renaming { display: block; padding: 6px 0; }
.jr-convos li .rn { display: flex; flex-wrap: wrap; gap: 6px; }
.jr-convos li .rn .jr-input { flex: 1 1 100%; min-width: 0; }
@media (min-width: 900px) {
  .jr-ask-layout.with-list { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 24px; align-items: start; }
  .jr-ask-layout .jr-convos { margin: 0; position: sticky; top: 12px; }
  .jr-ask-layout .jr-convos > summary { pointer-events: none; list-style: none; }
  .jr-ask-layout .jr-convos > summary::-webkit-details-marker { display: none; }
}
@media (min-width: 1500px) { .jr-ask-layout.with-list { grid-template-columns: minmax(320px, 1fr) minmax(0, 860px) minmax(320px, 1fr); } }


/* ════════════════════════════════════════════════════════════
   Cards in columns — journal-masonry.js
   Each card goes at the foot of the shortest column, in reading
   order, so nothing waits for a taller neighbour. The script sets
   how many columns the width pays for (one on a phone, two on a
   laptop, five or six on a 4K monitor) and writes it on the host
   as data-cols; with one column nothing is moved at all.
   ════════════════════════════════════════════════════════════ */
.jr-mrow {
  display: grid; grid-template-columns: repeat(var(--n, 1), minmax(0, 1fr));
  gap: 14px 18px; align-items: start; margin-bottom: 14px;
}
.jr-mcol { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
/* Placed, the columns are made the same height and the cards share out what is left over, so every column
   ends on the same line — no ragged bottom edge. (While the script is placing cards the rows are NOT
   stretched: it measures each column's own height to decide where the next card goes.) */
.jr-masoned > .jr-mrow { align-items: stretch; }
.jr-masoned .jr-mcol > .jr-card, .jr-masoned .jr-mcol > .jd-p { flex: 1 0 auto; }
.jr-mcol > .jr-card, .jr-mcol > .jd-p { margin-bottom: 0; }
.jr-mcol > * { min-width: 0; }

/* A screen with room uses it: the screens made of cards grow with the window instead of
   stopping at a width chosen for two columns. */
@media (min-width: 860px) {
  .jr-main.jr-cols, .jr-main.jr-home { max-width: 3600px; }
}

/* ── The home page: a flow of cards under the goal ───────── */
.jr-home { display: flex; flex-direction: column; gap: 14px; }
.jr-home > .jr-card, .jr-home > .jr-wide, .jr-home > .jr-mason { margin-bottom: 0; }
/* One column: the goal, then the matrix and the open trades, THEN the dashboard's filters and figures. */
.jr-home:has(> .jr-mason[data-cols="1"]) > #jd-a { order: 10; }
.jr-home > .jr-mason { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.jr-mason.jd { margin-bottom: 0; }
.jr-mason.jr-masoned > .jr-mrow { margin-bottom: 0; }
/* One column (a phone, a narrow window): the cards are the page's own flex items, so the matrix and
   the open trades can sit ABOVE the dashboard's filters and figures, and each chart has its place
   after them. Wider, each card keeps the place the masonry gave it. */
.jr-mason[data-cols="1"] { display: contents; }
.jr-mason[data-cols="1"] > .jr-o1 { order: 1; }
.jr-mason[data-cols="1"] > .jr-o2 { order: 2; }
.jr-mason[data-cols="1"] > .jd-p { order: calc(var(--o, 0) + 20); }
.jr-mason[data-cols="1"] > .jd-foot { order: 99; }
.jr-mason[data-cols="1"] > .jr-card { margin-bottom: 0; }

@media (min-width: 1600px) { .jr-main.jr-x { max-width: 1480px; } }
@media (min-width: 2000px) { .jr-main { max-width: 1800px; } .jr-main.jr-x { max-width: 1800px; } .jr-main.jr-trade { max-width: 1900px; } }
@media (min-width: 2500px) { .jr-main { max-width: 2200px; } .jr-main.jr-x { max-width: 2200px; } .jr-main.jr-trade { max-width: 2200px; } }

/* The charts of one answer: a dashboard of panels, not a column of full-width ones. */
.jr-xcharts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, max(300px, calc((100% - 24px) / 3))), 1fr)); gap: 12px; margin-top: 12px; align-items: start; }
.jr-xcharts[data-n="1"] { grid-template-columns: minmax(0, 820px); justify-content: center; }
.jr-xcharts > .jr-xchart { margin: 0; min-width: 0; }

/* The AI picker beside the Ask box: a small select, not a form field's worth of space. */
.jr-ai-pick { display: inline-flex; align-items: center; gap: 8px; }
.jr-ai-pick select { width: auto; min-height: 36px; padding: 4px 28px 4px 10px; font-size: 13.5px; }

/* ── Settings → Your data: the export ───────────────────── */
.jr-export .jr-check { display: flex; align-items: center; gap: 8px; margin: 12px 0 4px; min-height: 36px; }
.jr-export-bar { height: 10px; border-radius: 999px; background: var(--line2); overflow: hidden; margin: 14px 0 6px; }
.jr-export-bar > span { display: block; height: 100%; width: 0; background: var(--brand); transition: width .25s; }
.jr-export a.jr-btn { display: inline-flex; align-items: center; text-decoration: none; }

/* Ask: a candlestick chart is wide, and a trade's open alerts sit above the conversation. */
.jr-xcharts[data-n="1"]:has(.jc-candles) { grid-template-columns: minmax(0, 1200px); }
.jr-xcharts[data-n="1"] > .jr-xchart { width: 100%; }
.jr-xcharts[data-n="1"] .jc-candles { margin-left: auto; margin-right: auto; }
.jc-candles h4 { text-wrap: balance; }

/* Three or more charts of one answer are ONE canvas: a single panel, tiles divided by hairlines, equal height, no card in a card. */
.jr-xcharts[data-canvas] { gap: 1px; padding: 1px; background: var(--line2, #e8ecea); border: 1px solid var(--line, #d9dfdc); border-radius: 16px; overflow: hidden; align-items: stretch; box-shadow: var(--sh, none); }
.jr-xcharts[data-canvas] > .jr-xchart.jc { margin: 0; border: 0; border-radius: 0; box-shadow: none; background: var(--panel, #fff); min-width: 0; }
.jr-alerts { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); font-size: 13px; }
.jr-alerts ul { list-style: none; margin: 8px 0 6px; padding: 0; display: grid; gap: 6px; }
.jr-alerts li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.jr-alerts li form { margin: 0 0 0 auto; }
.jr-banner-alert { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.jr-banner-alert .jr-banner-x { margin: 0 0 0 auto; }

/* Price alerts in the browser: the pop-up that opens Ask, and the device's notification buttons. */
.jr-alert-toast { position: fixed; right: 16px; bottom: 76px; z-index: 60; width: min(380px, calc(100vw - 32px)); padding: 14px 16px; border: 1px solid var(--line); border-left: 4px solid #e0a030; border-radius: 12px; background: var(--panel); color: var(--ink); box-shadow: 0 10px 30px rgba(0, 0, 0, .28); font-size: 14px; }
.jr-alert-toast-b { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.jr-alert-toast-b .jr-btn { text-decoration: none; display: inline-flex; align-items: center; }
.jr-alert-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.jr-alert-tools[hidden] { display: none; }
.jr-alert-tools .jr-btn { min-height: 34px; padding: 4px 12px; font-size: 13px; }
.jr-alerts-slim { padding: 8px 12px; }
.jr-alerts-slim .jr-alert-tools { margin-top: 0; }
.jr-alert-ask { font-weight: 650; text-decoration: underline; }
@media (min-width: 900px) { .jr-alert-toast { bottom: 24px; } }


/* ── the daily check-in ────────────────────────────────────
   Named, one-tap choices in a row (a slider can be left in the middle, a name has to be picked), a line, and
   nothing else. Three across on any width: each is a thumb-sized target. */
.jr-checkin .ci-block + .ci-block { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line2); }
.jr-checkin .ci-day { margin: 0 0 2px; font-size: 14px; color: var(--ink2); }
.jr-checkin .ci-day b { color: var(--ink); }
.jr-checkin .ci-q { margin: 0 0 10px; font-size: 15px; font-weight: 600; }
.jr-checkin fieldset { border: 0; margin: 0 0 12px; padding: 0; min-width: 0; }
.jr-checkin legend { padding: 0; margin: 0 0 6px; font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink3); }
.jr-checkin .ci-opts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.jr-checkin .ci-chip { position: relative; display: block; margin: 0; }
.jr-checkin .ci-chip input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.jr-checkin .ci-chip span,
.jr-checkin .ci-chip.btn {
  display: flex; align-items: center; justify-content: center; min-height: 46px; padding: 6px 8px; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 600; text-align: center; cursor: pointer;
}
.jr-checkin .ci-chip.btn { width: 100%; }
.jr-checkin .ci-chip:hover span, .jr-checkin .ci-chip.btn:hover { border-color: var(--brand); }
.jr-checkin .ci-chip input:checked + span { background: var(--brand); border-color: var(--brand); color: #fff; }
.jr-checkin .ci-chip input:focus-visible + span, .jr-checkin .ci-chip.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.jr-checkin .ci-skip { display: block; margin: 8px auto 0; font-size: 13px; color: var(--ink3); }
.jr-checkin .ci-line { display: grid; gap: 6px; margin: 0 0 12px; font-size: 13px; color: var(--ink2); }
.jr-checkin .ci-line em { font-style: normal; color: var(--ink3); }
.jr-checkin .ci-line .jr-input { width: 100%; box-sizing: border-box; font-size: 16px; }
.jr-checkin .ci-go { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.jr-checkin .ci-go .jr-btn { min-height: 44px; }
.jr-checkin .ci-done { margin: 0 0 6px; font-size: 14px; display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; }
.jr-checkin .ci-done .tick { color: var(--brand); font-weight: 700; }
.jr-checkin .ci-tag { padding: 2px 10px; border: 1px solid var(--line); border-radius: 999px; font-size: 12px; color: var(--ink2); }
.jr-checkin .ci-note { margin: 0 0 6px; font-size: 14px; color: var(--ink2); font-style: italic; }
.jr-checkin .ci-edit { margin-top: 8px; }
.jr-checkin .ci-edit > summary { cursor: pointer; font-size: 13px; color: var(--ink3); padding: 6px 0; }

/* ════════════════════════════════════════════════════════════
   Ask, as a chat app (the Ask page only: .jr-askpage)

   A slim bar on top (menu, the conversation's name, who answers, a
   new chat), answers as plain text, the question as a rounded pill at
   the bottom. The saved conversations and the alert controls live in
   a menu that slides in on a phone and is the left column on a desk.
   ════════════════════════════════════════════════════════════ */
.jr-ask-bar { display: flex; align-items: center; gap: 6px; padding: 4px 0 10px; }
.jr-ask-ico { flex: none; position: relative; width: 40px; height: 40px; display: grid; place-items: center; border: 0; border-radius: 50%; background: none; color: var(--ink); cursor: pointer; padding: 0; }
.jr-ask-ico:hover, .jr-ask-ico:focus-visible { background: var(--panel3); }
.jr-ask-ico[disabled] { color: var(--ink3); opacity: .45; cursor: default; background: none; }
.jr-ask-ico.has-new::after { content: ''; position: absolute; top: 8px; right: 8px; width: 9px; height: 9px; border-radius: 50%; background: var(--plan, #3b82f6); box-shadow: 0 0 0 2px var(--bg); }
.jr-ask-title { flex: 1; min-width: 0; font-size: 16px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr-ask-model { flex: none; display: inline-flex; align-items: center; max-width: 42%; font-size: 13px; font-weight: 600; color: var(--ink2); border: 1px solid var(--line); border-radius: 999px; background: var(--panel); }
.jr-ask-model.solo { padding: 6px 12px; }
.jr-ask-model select { appearance: none; -webkit-appearance: none; border: 0; background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238a9794' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 11px center; color: inherit; font: inherit; padding: 0 30px 0 13px; min-height: 38px; border-radius: 999px; max-width: 100%; text-overflow: ellipsis; }
.jr-ask-model .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.jr-ask-new { margin: 0; flex: none; }
.jr-ask-side-head { display: none; }
.jr-ask-scrim { display: none; }

/* the conversation */
.jr-askpage .jr-chat-turn { border-bottom: 0; margin: 10px 0 6px; padding-bottom: 6px; }
.jr-askpage .jr-chat-q .bubble { background: var(--panel3); border: 0; border-radius: 20px 20px 6px 20px; padding: 10px 16px; color: var(--ink); }
.jr-askpage .jr-chat-a { border-left: 0; padding-left: 0; margin-top: 16px; }
.jr-askpage .jr-chat-turn .jr-x-answer { background: none; border: 0; padding: 0; font-size: 16px; line-height: 1.62; }
.jr-askpage .jr-chat-ran { font-size: 12.5px; color: var(--ink3); margin-top: 12px; }
.jr-askpage .jr-chat-when { margin: 22px 0 4px; }
.jr-ask-empty { text-align: center; padding: 5vh 4px 2vh; }
.jr-ask-empty h2 { margin: 0 0 8px; font-size: 24px; line-height: 1.25; color: var(--ink); }
.jr-ask-empty p { margin: 0 auto 22px; max-width: 440px; font-size: 14px; line-height: 1.5; color: var(--ink3); }
.jr-ask-chips { display: grid; gap: 8px; max-width: 540px; margin: 0 auto; }
.jr-ask-chips a { display: block; text-align: left; padding: 12px 15px; border: 1px solid var(--line); border-radius: 14px; background: var(--panel); color: var(--ink); text-decoration: none; font-size: 14px; line-height: 1.35; }
.jr-ask-chips a:hover, .jr-ask-chips a:focus-visible { border-color: var(--brand); }

/* the question: a pill, with a round send button */
.jr-askpage .jr-chat-form { border-top: 0; margin-top: 8px; padding-top: 6px; background: linear-gradient(to top, var(--bg) 72%, color-mix(in srgb, var(--bg) 0%, transparent)); -webkit-backdrop-filter: none; backdrop-filter: none; }
.jr-askpage .jr-chat-box { align-items: flex-end; gap: 6px; padding: 5px 5px 5px 16px; border: 1px solid var(--line); border-radius: 26px; background: var(--panel); box-shadow: 0 2px 12px rgba(0, 0, 0, .06); }
.jr-askpage .jr-chat-box:focus-within { border-color: var(--brand); }
.jr-askpage .jr-chat-box .jr-input { border: 0; background: transparent; box-shadow: none; outline: none; padding: 9px 0; min-height: 40px; font-size: 16px; line-height: 1.4; }
.jr-askpage .jr-chat-box .jr-send { flex: none; width: 40px; height: 40px; min-height: 0; padding: 0; border-radius: 50%; display: grid; place-items: center; }
.jr-send .lbl { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.jr-askpage .jr-chat-form .jr-x-acts { justify-content: center; }

/* a phone: no card around it, and the lists go into the menu */
@media (max-width: 899px) {
  .jr-askpage.jr-main { padding-top: 0; }
  .jr-askpage .jr-card.wide { background: none; border: 0; box-shadow: none; padding: 0; margin: 0; }
  .jr-askpage .jr-eyebrow { display: none; }
  .jr-ask-bar { position: sticky; top: var(--topH, 54px); z-index: 19; margin: 0 -16px; padding: 6px 10px; background: var(--bg); border-bottom: 1px solid var(--line2); }
  .jr-ask-side { position: fixed; z-index: 60; top: 0; bottom: 0; left: 0; width: min(86vw, 340px); padding: 10px 14px calc(var(--bar) + 18px); overflow-y: auto; background: var(--panel); border-right: 1px solid var(--line); box-shadow: 8px 0 28px rgba(0, 0, 0, .25);
                 transform: translateX(-104%); visibility: hidden; transition: transform .22s ease, visibility 0s linear .22s; }
  html.ask-menu .jr-ask-side { transform: none; visibility: visible; transition: transform .22s ease; }
  .jr-ask-side-head { display: flex; align-items: center; justify-content: space-between; padding: 2px 0 8px; font-size: 17px; }
  .jr-ask-side .jr-convos { border: 0; background: none; padding: 0; margin: 0 0 6px; }
  .jr-ask-side .jr-convos > summary { display: none; }
  .jr-ask-side .jr-alerts { margin: 16px 0 0; }
  .jr-ask-scrim { position: fixed; inset: 0; z-index: 55; background: rgba(0, 0, 0, .45); }
  html.ask-menu .jr-ask-scrim { display: block; }
  html.ask-menu body { overflow: hidden; }
  .jr-askpage .jr-chat-form { margin-left: -6px; margin-right: -6px; padding-left: 6px; padding-right: 6px; }
}
@media (min-width: 900px) {
  /* the page is a panel-coloured card here, so the fade under the question box must end in the card's colour, not the page's */
  .jr-askpage .jr-chat-form { background: linear-gradient(to top, var(--panel) 72%, color-mix(in srgb, var(--panel) 0%, transparent)); }
  .jr-ask-ico.menu { display: none; }
  .jr-ask-bar { padding-top: 0; }
  .jr-ask-main { max-width: 860px; }
}
@media (prefers-reduced-motion: reduce) { .jr-ask-side { transition: none; } }
.jr-alerts-how { margin: 8px 0 0; font-size: 12.5px; color: var(--ink3); }
.jr-alerts-how > summary { cursor: pointer; }
.jr-alerts-how .jr-note { margin: 6px 0 0; }
.jr-askpage .jr-chat-form > .jr-label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@media (min-width: 900px) {
  .jr-ask-layout > .jr-ask-side { position: sticky; top: 12px; align-self: start; max-height: calc(100vh - 24px); overflow-y: auto; }
  .jr-ask-layout .jr-ask-side .jr-convos { position: static; margin: 0 0 14px; }
}

/* ════════════════════════════════════════════════════════════
   The daily check-in pop-up, its history, the fine print under
   an Ask reply, alert delivery, and the Ask column centred
   ════════════════════════════════════════════════════════════ */
.jr-ci-gate { align-items: flex-start; }
.jr-ci-gate .jr-gate-box { margin: auto; max-width: 560px; }
.jr-ci-gate .ci-go { flex-direction: column; align-items: stretch; gap: 4px; }
.jr-ci-gate .ci-go .jr-gate-go { margin-top: 18px; }
.jr-ci-gate .ci-alt { display: flex; justify-content: center; gap: 6px 22px; flex-wrap: wrap; }
.jr-ci-gate .ci-alt .jr-link-btn { min-height: 40px; font-size: 14px; color: var(--ink3); }
.jr-ci-gate .ci-rules .jr-creed-list { margin: 0; }
.jr-checkin .ci-opts.four { grid-template-columns: repeat(3, minmax(0, 1fr)) 44px; }
.jr-checkin .ci-chip.none span { color: var(--ink3); }
.jr-checkin .ci-alerts { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; font-size: 14px; color: var(--ink2); }
.jr-checkin .ci-alerts .mono { color: var(--ink); font-weight: 600; }
.jr-checkin .ci-alerts-via { margin: 8px 0 0; font-size: 12.5px; color: var(--ink3); }
.jr-checkin .ci-tag.dim { color: var(--ink3); }
.jr-checkin .ci-tag.h1 { border-color: var(--good, #1f9d6b); color: var(--good, #1f9d6b); }
.jr-checkin .ci-tag.h3 { border-color: var(--bad, #d6455d); color: var(--bad, #d6455d); }

.jr-cih .ci-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 12px; }
.jr-cih .ci-row { padding: 14px 16px; border: 1px solid var(--line); border-radius: 14px; background: var(--panel2); }
.jr-cih .ci-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; }
.jr-cih .ci-trades { font-size: 13px; color: var(--ink3); }
.jr-cih .ci-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; }
.jr-cih .ci-note { margin: 8px 0 0; }
.jr-cih .ci-audio { display: block; width: 100%; margin: 10px 0 0; height: 40px; }
.jr-cih .ci-said { margin: 6px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--ink2); }
.jr-cih .ci-off { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 14px; color: var(--ink2); }
.jr-cih .ci-pager { display: flex; justify-content: space-between; margin: 14px 0 0; font-size: 14px; }

.jr-chat-model { margin: 8px 0 0; font-size: 11.5px; color: var(--ink3); overflow-wrap: anywhere; }
.jr-alert-via { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; width: 100%; margin: 10px 0 0; font-size: 13px; color: var(--ink2); }
.jr-alert-via .jr-input { width: auto; flex: 1; min-width: 150px; min-height: 38px; font-size: 14px; }

.jr-ask-main { width: 100%; box-sizing: border-box; margin-left: auto; margin-right: auto; }
@media (min-width: 1500px) {
  .jr-ask-layout.with-list > .jr-ask-side { width: 320px; }
}
.jr-ask-fresh { margin: 0 0 8px; padding: 8px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); font-size: 13px; color: var(--ink2); text-align: center; }

/* the "+" on the trade list: a phone only (a desk has both buttons) */
.jr-list-acts details.jr-add { position: relative; margin: 0; padding: 0; border: 0; align-self: stretch; }
.jr-list-acts details.jr-add > summary { height: 100%; }
@media (min-width: 601px) { .jr-list-acts .jr-add { display: none; } }
.jr-add > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-height: 42px; }
.jr-add > summary::-webkit-details-marker { display: none; }
.jr-add-menu { position: absolute; z-index: 30; right: 0; top: calc(100% + 6px); min-width: 190px; padding: 6px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); box-shadow: 0 10px 28px rgba(0, 0, 0, .18); display: grid; gap: 2px; }
.jr-add-menu a { display: block; padding: 11px 12px; border-radius: 8px; color: var(--ink); text-decoration: none; font-size: 15px; white-space: nowrap; }
.jr-add-menu a:hover, .jr-add-menu a:focus-visible { background: var(--panel3); }

/* Settings → Voice: on a wide screen the list of words has the whole column to itself, so it shows far more of them. */
@media (min-width: 1000px) {
  #vocab_terms { min-height: clamp(220px, 46vh, 520px); resize: vertical; }
}

/* ── Trade review: the rules in two drawers (plan rules open, account rules shut) ── */
.jr-rgroup { margin-top: 14px; border: 1px solid var(--line2); border-radius: 12px; background: var(--panel2); }
.jr-rgroup > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  padding: 11px 14px; cursor: pointer; list-style: none; font-weight: 600; font-size: 14.5px;
}
.jr-rgroup > summary::-webkit-details-marker { display: none; }
.jr-rgroup > summary::before { content: '▸'; color: var(--ink3); margin-right: 8px; font-size: 12px; transition: transform .15s; }
.jr-rgroup[open] > summary::before { transform: rotate(90deg); }
.jr-rg-title { flex: 1 1 auto; min-width: 0; }
.jr-rg-tally { display: inline-flex; gap: 10px; align-items: center; font-weight: 400; font-size: 12.5px; color: var(--ink3); }
.jr-rg-tally b.broke { color: var(--bad); font-weight: 600; }
.jr-rgroup.has-broke { border-color: var(--bad-line, var(--bad)); }
.jr-rgroup > .jr-ruling { margin: 0; padding: 0 14px 10px; }
.jr-rgroup > .jr-ruling:first-of-type { margin-top: 0; }
#rules:has(#rf-broke:checked) .jr-rgroup:not(:has(li.broke)),
#rules:has(#rf-kept:checked)  .jr-rgroup:not(:has(li.kept)),
#rules:has(#rf-quiet:checked) .jr-rgroup:not(:has(li.quiet)) { display: none; }
.jr-checkin .ci-opts + .ci-line { margin-top: 12px; }
.jr-cih .ci-review em { font-style: normal; color: var(--ink3); }

/* a trade's own number, small and quiet beside its symbol */
.jr-num { margin-left: 8px; font-size: 11.5px; font-weight: 500; color: var(--ink3); letter-spacing: 0; }

/* ── Settings: emails and alerts, and the weekly review page ── */
.jr-notices { display: flex; flex-direction: column; gap: 14px; margin-top: 10px; }
.jr-nt { border: 1px solid var(--line); border-radius: 14px; padding: 4px 14px 14px; margin: 0; min-width: 0; }
.jr-nt legend { padding: 0 6px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink3); }
.jr-nt .jr-check { margin-top: 8px; }
.jr-nt .jr-check em { display: block; font-style: normal; margin-top: 2px; }
.jr-nt-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 10px; }
.jr-nt-row label { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--ink2); }
.jr-nt-row .jr-input { width: auto; min-width: 110px; }

.jr-wk-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.jr-wk-head h2 { margin: 0; font-size: 20px; }
.jr-wk-pick { display: flex; align-items: center; gap: 8px; }
.jr-wk-pick .jr-input { width: auto; }
.jr-wk-focus { margin: 14px 0; padding: 14px 16px; border-radius: 14px; background: var(--brand-soft, var(--panel2)); border: 1px solid var(--line); }
.jr-wk-focus h3 { margin: 4px 0 6px; font-size: 17px; }
.jr-wk-focus p { margin: 0; color: var(--ink2); line-height: 1.55; font-size: 14px; }
.jr-wk-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 12px 0; }
.jr-wk-cell { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); }
.jr-wk-cell span { font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink3); }
.jr-wk-cell b { font-size: 17px; }
.jr-wk-cell em { font-style: normal; font-size: 12.5px; color: var(--ink3); }
.jr-wk-line { margin: 8px 0; font-size: 14px; }
.jr-wk-sec { margin-top: 14px; }
.jr-wk-rules { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 14px; }
.jr-wk-rules .x { color: var(--loss); font-weight: 700; }
.jr-wk-rules em { font-style: normal; color: var(--ink3); }
.jr-wk-foot { margin-top: 16px; }
@media (min-width: 700px) { .jr-wk-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ── the demo banner: what this is, and the way out ──
   Solid red on purpose and the same in both themes: it is the one thing on the page that says none of this is real. */
.jr-banner-demo { margin-top: 10px; }
.jr-banner-demo .jr-demo-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  padding: 11px 16px; border-radius: 12px; font-size: 14px; color: #fff;
  background: linear-gradient(135deg, #d63a2f, #b3261e); border: 1px solid #ef6a60;
  box-shadow: 0 6px 20px rgba(214, 58, 47, .28);
}
.jr-banner-demo .jr-demo-tag {
  padding: 2px 10px; border-radius: 999px; background: #fff; color: #b3261e;
  font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
}
.jr-banner-demo .jr-demo-say { flex: 1 1 240px; color: #fff; line-height: 1.45; }
.jr-banner-demo a { text-decoration: none; font-weight: 700; white-space: nowrap; }
.jr-banner-demo .jr-demo-cta {
  display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px; border-radius: 10px;
  background: #fff; color: #b3261e; border: 0;
}
.jr-banner-demo .jr-demo-cta:hover { background: #ffe9e6; }
.jr-banner-demo .jr-demo-out, .jr-banner-demo .jr-demo-out:hover { border: 0; color: #fff; font-weight: 600; text-decoration: underline; opacity: .92; background: transparent; border: 0; box-shadow: none; padding: 0 4px; }


/* ════════════════════════════════════════════════════════════
   Settings, as one index and one column of sections
   Left: an index that stays in view. Right: sections of the same
   width, every one a titled card; inside, short fields go two to a
   row. On a phone the index is a row of chips that scrolls sideways.
   ════════════════════════════════════════════════════════════ */
.jr-main.jr-set { max-width: 1120px; }
.jr-set-title { font-size: 22px; letter-spacing: -.02em; margin: 2px 0 12px; }
.jr-set-nav { display: flex; gap: 8px; overflow-x: auto; margin: 0 -16px 14px; padding: 8px 16px; position: sticky; top: 52px; z-index: 10;
  background: var(--bg); border-bottom: 1px solid var(--line2); scrollbar-width: none; align-items: center; }
.jr-set-nav::-webkit-scrollbar { display: none; }
.jr-set-nav .jr-set-title, .jr-set-gt { display: none; }
.jr-set-grp { display: contents; }
.jr-set-nav a { flex: none; padding: 7px 13px; border-radius: 999px; border: 1px solid var(--line); background: var(--panel); color: var(--ink2);
  font-size: 13.5px; font-weight: 600; text-decoration: none; white-space: nowrap; }
.jr-set-nav a:hover { color: var(--ink); background: var(--panel2); }
.jr-set-nav a[aria-current] { color: var(--on-brand); background: var(--brand); border-color: var(--brand); }
.jr-set-body { min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.jr-set-body > form { display: flex; flex-direction: column; gap: 14px; }
.jr-set-body .jr-card { margin-bottom: 0; scroll-margin-top: 112px; }
.jr-set-h { margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--line2); }
.jr-set-h h2 { margin: 0; font-size: 18px; letter-spacing: -.01em; }
.jr-set-h p { margin: 3px 0 0; font-size: 13.5px; color: var(--ink3); }
.jr-set-grid { display: grid; grid-template-columns: 1fr; gap: 4px 20px; }
.jr-set-grid > .jr-fld, .jr-set-grid > .jr-check { min-width: 0; }
.jr-fld > .jr-label:first-child { margin-top: 12px; }
.jr-set-grid .jr-fld > .jr-input { max-width: none; }
.jr-set-save { position: sticky; bottom: 0; z-index: 9; display: flex; align-items: center; gap: 14px; justify-content: space-between;
  padding: 12px 16px; margin: 0 -2px; border: 1px solid var(--line); border-radius: 14px; background: var(--panel); box-shadow: 0 -8px 24px rgba(0,0,0,.18); }
.jr-set-save .jr-note { margin: 0; flex: 1; }
.jr-set-save .jr-btn { flex: none; min-width: 150px; }
@media (max-width: 560px) { .jr-set-save { flex-direction: column; align-items: stretch; } .jr-set-save .jr-note { display: none; } }
@media (min-width: 760px) {
  .jr-set-grid { grid-template-columns: 1fr 1fr; }
  .jr-set-grid > .jr-check.full { grid-column: 1 / -1; }
}
@media (min-width: 980px) {
  .jr-main.jr-set { display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 28px; align-items: start; }
  .jr-set-nav { display: flex; flex-direction: column; align-items: stretch; gap: 2px; overflow: visible; margin: 0; padding: 0; border: 0; background: none;
    position: sticky; top: 76px; max-height: calc(100vh - 96px); overflow-y: auto; }
  .jr-set-nav .jr-set-title { display: block; padding: 0 10px; }
  .jr-set-grp { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px; }
  .jr-set-gt { display: block; padding: 0 10px 4px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink3); }
  .jr-set-nav a { border: 0; background: none; border-radius: 9px; padding: 7px 10px; font-weight: 500; font-size: 14px; }
  .jr-set-nav a[aria-current] { background: var(--panel2); color: var(--ink); box-shadow: inset 3px 0 0 var(--brand); }
}

/* Tiles of one size: an exchange, with its own sync status */
.jr-tiles { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); grid-auto-rows: 1fr; }
.jr-tile { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2);
  color: var(--ink); text-decoration: none; }
.jr-tile:hover { border-color: color-mix(in srgb, var(--brand) 45%, var(--line)); }
.jr-tile-top { display: flex; align-items: center; gap: 10px; }
.jr-tile-id { flex: 1; min-width: 0; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr-tile-line { font-size: 13.5px; color: var(--ink); }
.jr-tile-sub { font-size: 12.5px; color: var(--ink3); line-height: 1.45; }
.jr-tile-go { margin-top: auto; font-size: 13px; font-weight: 600; color: var(--brand); }
.jr-sx.bad { border-color: var(--before-line, var(--bad)); background: var(--before-soft, var(--panel2)); }
.jr-sx.bad .jr-tile-line { color: var(--bad); font-weight: 600; }
.jr-sx.add { border-style: dashed; background: transparent; }
.jr-sx-plus { flex: none; width: 36px; height: 36px; display: grid; place-items: center; border-radius: 10px; border: 1px dashed var(--line); font-size: 22px; color: var(--ink3); }
.jr-sx .jr-ex-pill { font-size: 11.5px; padding: 2px 8px; }

/* AI key tiles: logo, name and state on top, the key at the foot, all one size */
.jr-ai-top { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.jr-ai-id { flex: 1 1 130px; min-width: 0; }
.jr-ai-id .jr-note { margin: 2px 0 0; font-size: 12.5px; }
.jr-ai-top .jr-ai-tag { flex: none; align-self: flex-start; margin-left: auto; }
.jr-ai-foot { margin-top: auto; display: flex; flex-direction: column; gap: 8px; }
.jr-ai-foot .jr-x-keyform { margin-top: 0; }
.jr-ai-foot .jr-x-keyform .jr-input { min-width: 0; }
.jr-ai-make { font-size: 13px; }

.jr-ex > .jr-conn { flex: 1; display: flex; flex-direction: column; gap: 10px; }
.jr-ex > .jr-note + .jr-link-btn { margin-top: auto; }

/* Backfill, folded into an exchange's tile; and the re-check line across both columns of its facts */
.jr-ex-facts .wide { grid-column: 1 / -1; }
.jr-bf { flex-basis: 100%; order: 3; }
.jr-bf > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink2); list-style: none; }
.jr-bf > summary::-webkit-details-marker { display: none; }
.jr-bf > summary::before { content: "\21BA\00a0"; }
.jr-bf[open] > summary { color: var(--ink); }
.jr-bf .jr-note { margin: 6px 0 8px; }
.jr-bf-row { display: flex; gap: 8px; flex-wrap: wrap; }
.jr-bf-row .jr-input { flex: 1; min-width: 150px; width: auto; }

/* ── Getting started, on Home ─────────────────────────────── */
.jr-first { border-color: color-mix(in srgb, var(--brand) 40%, var(--line)); }
.jr-first-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.jr-first-head h2 { margin: 0; font-size: 19px; }
.jr-first-bar { height: 6px; border-radius: 99px; background: var(--panel3, var(--panel2)); margin: 12px 0 6px; overflow: hidden; }
.jr-first-bar > span { display: block; height: 100%; background: var(--brand); border-radius: 99px; transition: width .4s; }
.jr-first-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; }
.jr-first-list > li { display: flex; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line2); }
.jr-first-list > li:first-child { border-top: 0; }
.jr-first-list .mk { flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 13px; font-weight: 700;
  border: 1.5px solid var(--line); color: var(--ink3); }
.jr-first-list > li.done .mk { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.jr-first-list > li.cur .mk { border-color: var(--brand); color: var(--brand); }
.jr-first-list .body { min-width: 0; flex: 1; }
.jr-first-list .body > b { font-size: 15px; }
.jr-first-list > li.done .body > b { color: var(--ink3); font-weight: 500; }
.jr-first-list .body p { margin: 4px 0 8px; font-size: 13.5px; color: var(--ink2); }
.jr-first-list .acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.jr-first-list .acts .jr-btn { text-decoration: none; }

/* ── Guided AI key (Turn on Ask) ──────────────────────────── */
.jr-main.jr-aiset { max-width: 820px; }
.jr-aiset h1 { font-size: 24px; letter-spacing: -.02em; margin: 6px 0 8px; }
.jr-aiset-lead { color: var(--ink2); margin: 0 0 18px; }
.jr-aiset-steps { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.jr-aiset-steps > li { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 16px; }
.jr-aiset-steps h2 { margin: 0 0 10px; font-size: 16px; display: flex; align-items: center; gap: 10px; }
.jr-aiset-steps h2 .n { width: 24px; height: 24px; border-radius: 50%; background: var(--brand); color: var(--on-brand); display: grid; place-items: center; font-size: 13px; }
.jr-aiset-pick { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); grid-auto-rows: 1fr; }
.jr-aiset-opt { display: flex; flex-direction: column; gap: 8px; padding: 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2);
  color: var(--ink); text-decoration: none; min-width: 0; }
.jr-aiset-opt:hover { border-color: color-mix(in srgb, var(--brand) 50%, var(--line)); }
.jr-aiset-opt.on { border: 2px solid var(--brand); padding: 13px; background: color-mix(in srgb, var(--brand) 8%, var(--panel2)); }
.jr-aiset-opt .top { display: flex; align-items: center; gap: 10px; font-size: 15px; }
.jr-aiset-opt .best { font-size: 13.5px; color: var(--ink2); }
.jr-aiset-opt .cost { margin-top: auto; font-size: 12.5px; color: var(--ink3); }
.jr-aiset-do { margin: 0 0 14px; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; color: var(--ink2); font-size: 14.5px; }
.jr-aiset-form { display: flex; gap: 8px; flex-wrap: wrap; }
.jr-aiset-form .jr-input { flex: 1; min-width: 200px; }
.jr-aiset-steps .jr-note { display: inline-block; margin-left: 8px; }
.jr-first-list .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Settings → Getting started: the four steps, small, and the button that puts the checklist back on Home */
.jr-gs-list { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 8px; }
.jr-gs-list > li { display: flex; align-items: center; gap: 10px; font-size: 14.5px; color: var(--ink2); }
.jr-gs-list .mk { flex: none; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font-size: 12.5px; font-weight: 700; border: 1px solid var(--line); color: var(--ink3); }
.jr-gs-list > li.done .mk { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.jr-gs-list .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.jr-gs-actions { margin: 10px 0 6px; }

/* The reset-guide button in the top bar: same look as the theme toggle; icon only on a phone. */
@media (max-width: 559px) { .jr-guide span:not(.mk) { display: none; } }

/* Ask setup: a provider that already has a key says so on its card. */
.jr-aiset-st { margin-left: auto; font-size: 11.5px; font-weight: 600; color: var(--ink3); white-space: nowrap; }
.jr-aiset-st.use { color: var(--brand); }


/* The tour: a dimmed page with one lit part and a card that points at it. */
.jr-tour { position: fixed; inset: 0; z-index: 120; }
.jr-tour-spot { position: fixed; border-radius: 10px; box-shadow: 0 0 0 9999px rgba(5, 9, 10, .62), 0 0 0 2px var(--brand); pointer-events: none; transition: left .2s, top .2s, width .2s, height .2s; }
.jr-tour-card { position: fixed; box-sizing: border-box; padding: 16px 18px 14px; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 14px 40px rgba(0, 0, 0, .4); }
.jr-tour-card h2 { margin: 2px 0 6px; font-size: 17px; }
.jr-tour-card p { margin: 0 0 14px; font-size: 14px; line-height: 1.5; color: var(--ink2); }
.jr-tour-n { font-size: 11.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink3); }
.jr-tour-row { display: flex; align-items: center; gap: 8px; }
.jr-tour-row .sp { margin-left: auto; }
@media (prefers-reduced-motion: reduce) { .jr-tour-spot { transition: none; } }

.jr-keyok { color: var(--good, #1f9d6b); }
.jr-keybad { color: var(--bad, #d6455d); font-weight: 600; }
.jr-keywarn { color: var(--warn); font-weight: 600; }
.jr-ex-group { margin: 22px 0 4px; font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink3); }
.jr-ex-warn { margin: 8px 0 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--warn); border-left-width: 3px; background: var(--warn-soft); color: var(--ink2); font-size: 13px; line-height: 1.55; }
.jr-ex-warn strong { color: var(--warn); }

/* ── the prop-firm challenge ─────────────────────────────── */
.jr-ch-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.jr-ch-head h2 { margin: 0; font-size: 20px; }
.jr-ch-state { font-size: 12px; font-weight: 700; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--line); color: var(--ink2); background: var(--panel2); }
.jr-ch-state.jr-ch-live { color: var(--brand); border-color: var(--brand); }
.jr-ch-state.jr-ch-ok { color: var(--good); border-color: var(--good-line); background: var(--good-soft); }
.jr-ch-state.jr-ch-bad { color: var(--bad); border-color: var(--bad-line); background: var(--bad-soft); }
.jr-ch-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; margin: 14px 0; }
.jr-ch-gauge { display: grid; gap: 6px; padding: 14px 16px; border-radius: 14px; border: 1px solid var(--line); background: var(--panel2); }
.jr-ch-gauge span { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--ink3); }
.jr-ch-gauge b { font-size: 24px; color: var(--ink); }
.jr-ch-gauge em { font-style: normal; font-size: 12px; color: var(--ink3); }
.jr-ch-bar { height: 8px; border-radius: 999px; background: var(--panel3); overflow: hidden; }
.jr-ch-bar i { display: block; height: 100%; border-radius: 999px; background: var(--good); transition: width .5s ease; }
.jr-ch-gauge.jr-ch-warn .jr-ch-bar i { background: var(--warn); }
.jr-ch-gauge.jr-ch-bad .jr-ch-bar i { background: var(--bad); }
.jr-ch-gauge.jr-ch-warn b { color: var(--warn); }
.jr-ch-gauge.jr-ch-bad b { color: var(--bad); }
.jr-ch-firm { margin: 0 0 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); }
.jr-ch-firm-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px 14px; margin: 8px 0 4px; }
.jr-ch-firm-row label { display: grid; gap: 4px; font-size: 12px; font-weight: 600; color: var(--ink2); }
.jr-ch-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px 14px; margin: 10px 0; }
.jr-ch-fields label { display: grid; gap: 4px; font-size: 12px; font-weight: 600; color: var(--ink2); }
.jr-banner-ch.jr-ch-warn a { color: var(--warn); }
.jr-banner-ch.jr-ch-bad a { color: var(--bad); }
@media (prefers-reduced-motion: reduce) { .jr-ch-bar i { transition: none; } }

/* ── the check-in: put off, brought back, and said ─────────── */
.jr-gate[hidden] { display: none; }
.jr-checkin .ci-part { margin: 0 0 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--brand); }
.jr-checkin .ci-opts.four .ci-chip span { font-size: 13.5px; padding-left: 3px; padding-right: 3px; }
.jr-ci-gate .ci-snooze { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; margin: 14px 0 2px; font-size: 14px; color: var(--ink2); }
.jr-ci-gate .ci-snooze .jr-btn { min-width: 56px; }
.jr-ci-chip {
  display: inline-flex; align-items: center; gap: 7px; min-height: 34px; padding: 0 12px; margin-left: 8px;
  border: 1px solid var(--brand); border-radius: 999px; background: color-mix(in srgb, var(--brand) 14%, transparent);
  color: var(--ink); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.jr-ci-chip i { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex: none; }
.jr-ci-chip:hover { background: color-mix(in srgb, var(--brand) 26%, transparent); }
.jr-ci-chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
@media (max-width: 520px) {
  .jr-top.has-ci .who, .jr-top.has-ci .jr-theme [data-theme-label] { display: none; }
  .jr-ci-chip { margin-left: 4px; padding: 0 10px; gap: 6px; font-size: 12.5px; }
}
.jr-banner-ok > span {
  display: block; padding: 10px 14px; border-radius: 12px; font-size: 14px; color: var(--ink);
  background: color-mix(in srgb, var(--brand) 12%, var(--panel, transparent)); border: 1px solid var(--brand);
}
.jr-banner-ok .tick { color: var(--brand); font-weight: 700; }
.jr-banner-ok a { display: inline; padding: 0; border: 0; background: none; color: var(--brand); text-decoration: underline; white-space: nowrap; }
.jr-cih .ci-part { margin: 14px 0 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--brand); }
.jr-cih .ci-part small { font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--ink3); }
.jr-cih .ci-later { margin: 0 0 8px; font-size: 13px; color: var(--ink3); }


/* ── Ask in the nav: an answer is ready, or being worked on ──────────
   A dot on the icon, not a number: one thing is being said — "go and look". Brand teal for an answer
   waiting, amber for one that failed (a failed answer is not a trading mistake, so not the pink),
   and a ring that breathes while a question is still being worked on. */
.jr-ask-dot { position: absolute; top: -4px; right: -7px; width: 9px; height: 9px; border-radius: 50%; display: none; box-sizing: border-box; border: 2px solid var(--panel); }
.jr-ask-dot[data-state="new"]    { display: block; background: var(--brand); }
.jr-ask-dot[data-state="failed"] { display: block; background: var(--warn); }
.jr-ask-dot[data-state="busy"]   { display: block; background: var(--ink3); animation: jrAskBreathe 1.6s ease-in-out infinite; }
@keyframes jrAskBreathe { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .jr-ask-dot[data-state="busy"] { animation: none; opacity: .7; } }

/* What an exit made and what is left, one quiet line under it. */
.jr-timeline .sub { display: block; margin-top: 2px; font-size: 13px; color: var(--ink3); }

/* ── #12 in an answer: the link, and the card about the trade ─────────────────
   The card is edged in the trade's matrix colour — followed the plan, broke it, or not judged — and never in
   profit or loss, like everything else that is coloured by the plan. */
a.jr-tref { color: var(--brand); font-weight: 600; text-decoration: none; border-bottom: 1px dotted currentColor; white-space: nowrap; }
a.jr-tref:hover, a.jr-tref:focus-visible { border-bottom-style: solid; }

.jr-tcard {
  position: fixed; z-index: 60; box-sizing: border-box;
  width: max-content; max-width: min(300px, calc(100vw - 20px));
  padding: 10px 13px 11px; border-radius: 10px;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-left: 4px solid var(--line);
  box-shadow: 0 10px 30px -10px rgba(0,0,0,.45);
  font-size: 13px; line-height: 1.4;
}
.jr-tcard.good { border-left-color: var(--good); }
.jr-tcard.bad  { border-left-color: var(--bad); }
.jr-tcard .h { display: flex; align-items: baseline; flex-wrap: wrap; gap: 7px; }
.jr-tcard .no { font-size: 15px; }
.jr-tcard .sym { font-family: 'JetBrains Mono', ui-monospace, monospace; font-weight: 600; }
.jr-tcard .side { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.jr-tcard .side.long { color: var(--dir-long); }
.jr-tcard .side.short { color: var(--dir-short); }
.jr-tcard .live { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--brand); }
.jr-tcard .m { margin-top: 3px; color: var(--ink2); display: flex; flex-wrap: wrap; gap: 0 6px; }
.jr-tcard .m .dot { color: var(--ink3); }
.jr-tcard .m .r { font-family: 'JetBrains Mono', ui-monospace, monospace; color: var(--ink); font-weight: 600; }
.jr-tcard .go { display: flex; justify-content: center; margin-top: 10px; min-height: 40px; align-items: center; }
