/* The yt-link dashboard.
 *
 * Design decisions:
 * - This interface is an app shell, not a long document: the left rail is fixed and the
 *   view on the right changes with the hash. Moving between sections is a switch, not a
 *   scroll.
 * - The page's only "loud" element is the pipeline flow. What characterises the system is
 *   an article moving through the stages, and the chain at the top shows exactly that.
 *   Everything else is quiet: one hairline border, no shadows.
 * - Numbers are mono and `tabular-nums` everywhere, so a column does not shift when a
 *   score goes from 0.7 to 0.85.
 * - Alpha and direction use a diverging teal/rose pair — green/red does not separate
 *   under colour blindness, and its stock-ticker connotation speaks louder than the
 *   measurement itself.
 *
 * The theme has three states: with no choice it follows the OS (`prefers-color-scheme`),
 * with a choice `data-theme` sits on the root. That is why the dark palette is written
 * twice: the media query applies "when nothing is chosen", the attribute "when dark was
 * chosen explicitly". Folding them into one block would mean a user who picked light
 * still sees dark on a dark system.
 */

:root {
  color-scheme: light dark;

  --ground: #f3f2f7;
  --panel: #ffffff;
  --panel-sunk: #f7f7fb;
  --ink: #171525;
  --ink-dim: #56526b;
  --ink-faint: #8a869c;
  --line: #e4e2ee;
  --line-strong: #cbc8db;

  --signal: #5b3df5;
  --signal-ink: #ffffff;
  --signal-wash: #ece9ff;

  --positive: #0f8a80;
  --negative: #c4437b;
  --neutral: #9a96ab;
  --warn: #b4730e;
  --warn-wash: #fbf1de;
  --alert: #c0392e;

  --field: #ffffff;
  --hatch: rgba(86, 82, 107, 0.2);
  --lift: 0 1px 2px rgba(23, 21, 37, 0.05), 0 8px 24px -16px rgba(23, 21, 37, 0.28);

  --rail-width: 15rem;
  --measure: 68ch;
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;

  --sans: "Geist", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --display: "Bricolage Grotesque", var(--sans);
  --mono: "Geist Mono", ui-monospace, "SFMono-Regular", "Cascadia Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  /* Yalnızca kullanıcı AÇIK temayı seçmemişken. */
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground: #0e0d14;
    --panel: #17161f;
    --panel-sunk: #121119;
    --ink: #eae8f2;
    --ink-dim: #a09cb4;
    --ink-faint: #726e85;
    --line: #26242f;
    --line-strong: #3a3747;

    --signal: #9280ff;
    --signal-ink: #100d20;
    --signal-wash: #1f1b38;

    --positive: #3bb7ab;
    --negative: #ec7ba8;
    --neutral: #7d7a8c;
    --warn: #e0a64a;
    --warn-wash: #2c2415;
    --alert: #ef7b6e;

    --field: #101018;
    --hatch: rgba(160, 156, 180, 0.24);
    --lift: 0 1px 2px rgba(0, 0, 0, 0.5), 0 10px 28px -18px rgba(0, 0, 0, 0.9);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #0e0d14;
  --panel: #17161f;
  --panel-sunk: #121119;
  --ink: #eae8f2;
  --ink-dim: #a09cb4;
  --ink-faint: #726e85;
  --line: #26242f;
  --line-strong: #3a3747;

  --signal: #9280ff;
  --signal-ink: #100d20;
  --signal-wash: #1f1b38;

  --positive: #3bb7ab;
  --negative: #ec7ba8;
  --neutral: #7d7a8c;
  --warn: #e0a64a;
  --warn-wash: #2c2415;
  --alert: #ef7b6e;

  --field: #101018;
  --hatch: rgba(160, 156, 180, 0.24);
  --lift: 0 1px 2px rgba(0, 0, 0, 0.5), 0 10px 28px -18px rgba(0, 0, 0, 0.9);
}

:root[data-theme="light"] { color-scheme: light; }

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0;
}

h1 { font-size: 1.9rem; line-height: 1.12; }
h2 { font-size: 1.15rem; letter-spacing: -0.015em; }
h3 { font-size: 0.98rem; }

p { margin: 0.45rem 0 0; max-width: var(--measure); }

a { color: var(--signal); text-underline-offset: 0.18em; }

:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.num, td.num, .value {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  letter-spacing: -0.01em;
}

.muted { color: var(--ink-faint); }
.pos { color: var(--positive); }
.neg { color: var(--negative); }

/* --- Form öğeleri ------------------------------------------------------------ */

.field { display: block; margin-bottom: 0.9rem; }

.field > span {
  display: block;
  font-size: 0.84rem;
  color: var(--ink-dim);
  margin-bottom: 0.35rem;
}

input[type="email"],
input[type="password"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="date"],
select {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

input[type="date"] {
  color-scheme: inherit;
  padding-top: 0.54rem;
  padding-bottom: 0.54rem;
}

input[type="date"]::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 120ms ease;
}

input[type="date"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
}

input:focus-visible, select:focus-visible {
  border-color: var(--signal);
  outline: none;
  box-shadow: 0 0 0 3px var(--signal-wash);
}

button {
  font: inherit;
  font-weight: 550;
  color: var(--signal-ink);
  background: var(--signal);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  padding: 0.55rem 1.1rem;
  cursor: pointer;
  transition: filter 120ms ease, background 120ms ease;
}

button:hover { filter: brightness(1.08); }
button:disabled { opacity: 0.5; cursor: progress; }

button.quiet {
  background: var(--panel);
  color: var(--ink);
  border-color: var(--line-strong);
  font-weight: 500;
}

button.quiet:hover { filter: none; background: var(--panel-sunk); }

.form-error {
  border: 1px solid var(--alert);
  border-radius: var(--r-md);
  padding: 0.6rem 0.8rem;
  color: var(--alert);
  margin-bottom: 1rem;
  font-size: 0.9rem;
}

.hint {
  color: var(--ink-faint);
  font-size: 0.84rem;
  margin-top: 0.9rem;
  max-width: var(--measure);
}

/* --- Giriş ekranı ------------------------------------------------------------ */

.signin {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
  justify-items: center;
  padding: 2rem 1.25rem;
  background:
    radial-gradient(70rem 36rem at 50% -16rem, var(--signal-wash), transparent 70%),
    var(--ground);
}

.signin-card {
  width: 100%;
  max-width: 25rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 1.75rem;
  box-shadow: var(--lift);
}

.signin-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.wordmark {
  font-family: var(--display);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

/* Marka işareti: bir haberin zincirden geçişi — arayüzün konusu bu. */
.mark { display: block; width: 1.4rem; height: 1.4rem; flex: none; color: var(--signal); }

.prefs { display: flex; flex-direction: column; gap: 0.45rem; align-items: flex-end; }

.signin h1 { font-size: 1.55rem; }
.signin p { color: var(--ink-dim); font-size: 0.92rem; }
.signin form { margin-top: 1.4rem; }
.signin button[type="submit"] { width: 100%; margin-top: 0.4rem; }

/* Dil ve tema anahtarları aynı dili konuşur: segment kontrolü, seçili olan panel
   renginde. Dil sunucu tarafında (link), tema istemcide (düğme) çalışır. */
.lang-switch,
.theme-switch {
  display: inline-flex;
  gap: 1px;
  padding: 2px;
  background: var(--panel-sunk);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.lang-switch a,
.theme-switch button {
  font-family: var(--sans);
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--ink-faint);
  text-decoration: none;
  background: none;
  border: 0;
  border-radius: 999px;
  padding: 0.2rem 0.6rem;
  cursor: pointer;
  line-height: 1.5;
  transition: background 120ms ease, color 120ms ease;
}

.lang-switch a:hover,
.theme-switch button:hover { color: var(--ink); filter: none; }

.lang-switch a[aria-current="true"],
.theme-switch button[aria-pressed="true"] {
  color: var(--ink);
  background: var(--panel);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

/* --- Kabuk ------------------------------------------------------------------- */

.shell {
  display: grid;
  grid-template-columns: var(--rail-width) minmax(0, 1fr);
  min-height: 100vh;
}

.rail {
  border-right: 1px solid var(--line);
  background: var(--panel-sunk);
  padding: 1.4rem 1rem;
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.rail .wordmark { padding: 0 0.4rem; }

.rail > nav { display: flex; flex-direction: column; gap: 2px; }

.rail > nav a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--ink-dim);
  text-decoration: none;
  padding: 0.45rem 0.65rem;
  border-radius: var(--r-md);
  font-size: 0.93rem;
  font-weight: 500;
  transition: background 120ms ease, color 120ms ease;
}

.rail > nav a:hover { color: var(--ink); background: var(--panel); }

.rail > nav a[aria-current="page"] {
  color: var(--signal-ink);
  background: var(--signal);
}

.rail > nav svg { width: 1.05rem; height: 1.05rem; flex: none; }

.rail-foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: flex-start;
}

.rail-foot .who {
  font-size: 0.8rem;
  color: var(--ink-faint);
  overflow-wrap: anywhere;
  padding: 0 0.4rem;
}

.rail-foot form { width: 100%; }
.rail-foot form button { width: 100%; }

.menu-toggle { display: none; }

.menu-toggle:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* --- Üst çubuk ---------------------------------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8rem clamp(1rem, 3vw, 2.5rem);
  background: var(--ground);
  border-bottom: 1px solid var(--line);
}

.topbar h2 { font-size: 1.1rem; }
.topbar .spacer { flex: 1; }

/* Canlı durum rozeti: LLM duraklatıldıysa uyarı rengine geçer. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.82rem;
  font-weight: 500;
  padding: 0.25rem 0.7rem 0.25rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--ink-dim);
  white-space: nowrap;
}

.pill i {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--positive);
  flex: none;
}

.pill.paused { border-color: var(--warn); background: var(--warn-wash); color: var(--warn); }
.pill.paused i { background: var(--warn); }

main { padding: 1.75rem clamp(1rem, 3vw, 2.5rem) 4rem; max-width: 84rem; }

/* Görünümler hash ile değişir; aynı anda yalnızca biri görünür. */
.view[hidden] { display: none; }

.view-head { margin-bottom: 1.5rem; }
.view-head p { color: var(--ink-dim); font-size: 0.93rem; }

.block { margin-top: 2rem; }
.block-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.85rem;
  flex-wrap: wrap;
}
.block-head p { margin: 0; font-size: 0.85rem; color: var(--ink-faint); }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 1.15rem 1.25rem;
}

.notice {
  border: 1px solid var(--warn);
  background: var(--warn-wash);
  color: var(--warn);
  border-radius: var(--r-md);
  padding: 0.7rem 0.9rem;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
  max-width: var(--measure);
}

/* --- Ölçüm şeridi -------------------------------------------------------------- */

/* Sekiz ölçüm iki tam sıra yapar. `auto-fit` yedi sütun çizip sekizinciyi tek başına
   bırakıyordu — yarım kalan sıra düzeni bozuyor. */
.readout {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  margin: 0 0 1.75rem;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.readout > div { background: var(--panel); padding: 0.9rem 1.1rem; }

.readout dt {
  font-size: 0.8rem;
  color: var(--ink-dim);
  margin-bottom: 0.25rem;
}

.readout dd {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.6rem;
  line-height: 1.1;
  letter-spacing: -0.03em;
}

@media (min-width: 44rem) { .readout { grid-template-columns: repeat(4, 1fr); } }

.state-paused { color: var(--warn); }
.state-running { color: var(--positive); }

/* --- Today: the health line ----------------------------------------------------- */

/* One sentence where five scattered indicators used to be. It is the width of the page
   and it is the first thing under the title, because "is this working" is asked before
   anything else on the screen can be trusted. */
.health {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 0.2rem 0.7rem;
  margin-bottom: 1.5rem;
  padding: 0.85rem 1.1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--neutral);
  border-radius: var(--r-lg);
  background: var(--panel);
}
.health-text { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.health-text b { font-size: 1.02rem; }
.health-notes { font-size: 0.87rem; color: var(--ink-dim); }

/* The explanation of a bad state, on its own line rather than in a tooltip: the reader
   who most needs it is the one who does not yet know to hover. A good state has none. */
.health-hint {
  grid-column: 2;
  margin: 0.3rem 0 0;
  font-size: 0.84rem;
  color: var(--ink-faint);
  max-width: 62ch;
}

/* Pinned to the first line rather than centred: on a narrow screen the notes wrap and a
   centred dot drifts down beside them, away from the word it marks. */
.health-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--neutral);
  align-self: start;
  margin-top: 0.45rem;
}
.health[data-tone="ok"] { border-left-color: var(--positive); }
.health[data-tone="ok"] .health-dot { background: var(--positive); }
.health[data-tone="paused"] { border-left-color: var(--warn); background: var(--warn-wash); }
.health[data-tone="paused"] .health-dot { background: var(--warn); }
.health[data-tone="warn"] { border-left-color: var(--warn); }
.health[data-tone="warn"] .health-dot { background: var(--warn); }
.health[data-tone="bad"] { border-left-color: var(--negative); }
.health[data-tone="bad"] .health-dot { background: var(--negative); }

/* --- Today: the four figures ----------------------------------------------------- */

/* Four numbers with room to be read, in place of a strip of ten. Each carries the one
   line that makes it mean something — a count of signals says nothing without what it
   was drawn from. */
.figures { margin-bottom: 1.75rem; }

.figure-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: 0;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.figure { background: var(--panel); padding: 1rem 1.15rem 0.9rem; }
.figure dt { font-size: 0.8rem; color: var(--ink-dim); }
.figure dd { margin: 0; }

.figure-value {
  margin-top: 0.25rem;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.85rem;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.03em;
}
.figure-note { margin-top: 0.25rem; font-size: 0.78rem; color: var(--ink-faint); }

.figure.tone-signal .figure-value { color: var(--signal); }
.figure.tone-warn .figure-value { color: var(--warn); }

@media (min-width: 52rem) { .figure-row { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* --- Today: the day's decisions -------------------------------------------------- */

/* The list this page never had. Rows, not cards: the reader is scanning for a symbol and
   a direction, and six cards of equal weight make that scan slower, not richer. */
.signal-list { display: flex; flex-direction: column; }

.signal {
  display: grid;
  grid-template-columns: 3.4rem minmax(5rem, auto) 2.6rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0.2rem 0.9rem;
  padding: 0.6rem 0.2rem;
  color: inherit;
  text-decoration: none;
  border-top: 1px solid var(--line);
}
.signal:first-child { border-top: 0; padding-top: 0.15rem; }
.signal:hover { background: var(--panel-sunk); }

.signal-dir {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 550;
  text-align: center;
  border-radius: var(--r-sm);
  padding: 0.12rem 0.3rem;
}
/* Direction is the first thing read and the only place on the row where colour carries
   meaning; the score beside it is deliberately plain, because a number tinted by its own
   size tells the reader what to think before they have read it. */
.dir-buy { color: var(--positive); background: color-mix(in oklab, var(--positive) 12%, transparent); }
.dir-sell { color: var(--negative); background: color-mix(in oklab, var(--negative) 12%, transparent); }

.signal-symbol { display: flex; flex-direction: column; }
.signal-symbol b { font-family: var(--mono); font-size: 0.92rem; }
.signal-warn { font-size: 0.68rem; color: var(--warn); }

.signal-score { font-size: 0.92rem; color: var(--ink-dim); }

.signal-title {
  font-size: 0.88rem;
  color: var(--ink-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.signal-sent { font-size: 0.78rem; color: var(--positive); white-space: nowrap; }
.signal-sent.muted { color: var(--ink-faint); }

.signal-rest {
  display: inline-block;
  margin-top: 0.8rem;
  font-size: 0.84rem;
}

/* --- Today: where the news stopped ------------------------------------------------ */

/* Proportions first, counts underneath. The question is what share of a day's news died
   at which stop, and a column of numbers answers it only after the reader has done the
   division themselves. */
.resting-bar {
  display: flex;
  gap: 2px;
  height: 0.85rem;
  margin-bottom: 1rem;
  border-radius: 999px;
  overflow: hidden;
}
/* A floor, so a stop that took five of a thousand articles still draws a mark. Without it
   the only visible segment is the one that swallows the day, and the bar says "everything
   was discarded" — which is close enough to true to be misleading. */
.resting-part { flex-basis: 0; min-width: 4px; background: var(--neutral); }
.resting-part.tone-drop { background: var(--neutral); }
.resting-part.tone-near { background: var(--warn); }
.resting-part.tone-sent { background: var(--positive); }
.resting-part.tone-bad { background: var(--negative); }
.resting-part.tone-moving { background: var(--signal); }

.resting-key {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: 0.55rem 1.3rem;
  margin: 0 0 0.9rem;
}
.resting-item dt { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--ink-dim); }
.resting-item dt i { width: 0.5rem; height: 0.5rem; border-radius: 2px; background: var(--neutral); flex: none; }
.resting-item.tone-near dt i { background: var(--warn); }
.resting-item.tone-sent dt i { background: var(--positive); }
.resting-item.tone-bad dt i { background: var(--negative); }
.resting-item.tone-moving dt i { background: var(--signal); }

.resting-item dd {
  margin: 0.1rem 0 0 0.9rem;
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.resting-item dd b { font-size: 1.05rem; font-weight: 500; }
.resting-item dd small { font-size: 0.75rem; color: var(--ink-faint); }

/* A section heading's tab group sits on the heading's line, not on its own above the
   card, so switching windows does not move the card it switches. */
.block-head .horizon-tabs { margin-bottom: 0; }

.quiet-link { font-size: 0.85rem; }

/* Narrow screens: the signal row folds in two. The headline is the part that can take a
   second line — the symbol, the direction, the score and whether it went out are what a
   phone is scanning for, and none of them may be pushed off the right edge. */
@media (max-width: 46rem) {
  .signal {
    grid-template-columns: auto auto auto minmax(0, 1fr);
    row-gap: 0.25rem;
    padding: 0.7rem 0.2rem;
  }
  .signal-dir { grid-area: 1 / 1; }
  .signal-symbol { grid-area: 1 / 2; }
  .signal-score { grid-area: 1 / 3; }
  .signal-sent { grid-area: 1 / 4; justify-self: end; }
  .signal-title { grid-area: 2 / 1 / 3 / -1; white-space: normal; }

  .figure { padding: 0.85rem 0.9rem; }
  .figure-value { font-size: 1.55rem; }
  .health { padding: 0.75rem 0.9rem; }
  .resting-key { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }

  /* Two labels sharing a phone's width wrap into each other and the heading loses its
     shape; the note drops to its own line instead. */
  .ledger > summary { flex-wrap: wrap; }
  .ledger > summary small { flex-basis: 100%; margin-left: 0.96rem; }
}

/* --- Canlılık göstergesi ------------------------------------------------------- */

/* The dashboard refreshes itself; the only honest way to say so is to show when it last
   refreshed. A breathing dot says "live", the timestamp next to it says "really live" —
   that is what tells a frozen page from a quiet one. */

.live-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.live-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.82rem;
  color: var(--ink-dim);
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 999px;
  padding: 0.25rem 0.35rem 0.25rem 0.75rem;
  white-space: nowrap;
}

.live-badge .quiet {
  font-size: 0.78rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
}

.live-stamp {
  color: var(--ink-faint);
  font-size: 0.78rem;
  min-width: 6.5ch;
}

.live-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--positive);
  flex: none;
  position: relative;
}

/* Halka noktanın kendisinden çıkıp sönüyor: dikkat çekmeden ritim veriyor. */
.live-dot::after {
  content: "";
  position: absolute;
  inset: -0.35rem;
  border-radius: 50%;
  border: 1px solid currentColor;
  color: var(--positive);
  opacity: 0;
}
.live-dot[data-state="live"]::after { animation: ring 2.4s ease-out infinite; }
.live-dot[data-state="asleep"] { background: var(--neutral); }
.live-dot[data-state="failing"] { background: var(--warn); }
.live-dot[data-state="failing"]::after { color: var(--warn); animation: ring 1.2s ease-out infinite; }

@keyframes ring {
  0% { opacity: 0.55; transform: scale(0.6); }
  70% { opacity: 0; transform: scale(1.35); }
  100% { opacity: 0; transform: scale(1.35); }
}

/* --- Stations ------------------------------------------------------------------ */

/* Deliberately no progress bar here. The stages run in parallel: every card is a separate
   worker fed by its own queue, and it does not wait for its neighbour. Lining the cards up
   and joining them would say "first this, then that", which is not how the system works.
   The order is only the order in which an article visits them. */

/* Registered so the border light can turn: an unregistered custom property is a string
   and cannot be interpolated. A browser without `@property` shows a still border. */
@property --station-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.stations {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.85rem;
}

/* Three background layers so the border can be a gradient: a wash in the card's tone from
   the top-right corner, the panel itself, and beneath both the "border", which only shows
   through the transparent 1px edge. */
.station {
  --tone: var(--neutral);
  --tone-wash: transparent;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.95rem 1.05rem 0.85rem;
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  background:
    radial-gradient(120% 85% at 100% 0%, var(--tone-wash), transparent 60%) padding-box,
    linear-gradient(var(--panel), var(--panel)) padding-box,
    linear-gradient(var(--line), var(--line)) border-box;
  transition: box-shadow 0.4s ease, transform 0.25s ease;
  animation: station-in 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
  animation-delay: calc(var(--order, 0) * 45ms);
}

.station:hover {
  transform: translateY(-2px);
  box-shadow: var(--lift);
}

/* A working card's border carries a light that circles it. It moves only while there is
   work in the inbox, so which stages are busy reads without reading a single number. */
.station[data-state="working"] {
  --tone: var(--signal);
  --tone-wash: var(--signal-wash);
  background:
    radial-gradient(120% 85% at 100% 0%, var(--tone-wash), transparent 60%) padding-box,
    linear-gradient(var(--panel), var(--panel)) padding-box,
    conic-gradient(
      from var(--station-angle),
      var(--line) 0deg 210deg,
      color-mix(in oklab, var(--signal) 45%, var(--line)) 270deg,
      var(--signal) 330deg,
      var(--line) 360deg
    ) border-box;
  box-shadow: 0 16px 36px -28px var(--signal);
  animation:
    station-in 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) backwards,
    station-orbit 4.8s linear infinite;
}

.station[data-state="blocked"] {
  --tone: var(--warn);
  --tone-wash: var(--warn-wash);
  background:
    radial-gradient(120% 85% at 100% 0%, var(--tone-wash), transparent 60%) padding-box,
    linear-gradient(var(--panel), var(--panel)) padding-box,
    linear-gradient(var(--warn), var(--warn)) border-box;
}

@keyframes station-orbit {
  to { --station-angle: 360deg; }
}

@keyframes station-in {
  from { opacity: 0; transform: translateY(8px); }
}

.station header {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.station-index {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  padding: 0.08rem 0.34rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--panel-sunk);
}

.station h3 {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.station-state {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  white-space: nowrap;
  padding: 0.1rem 0.5rem 0.1rem 0.4rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-sunk);
  color: var(--ink-faint);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: lowercase;
}
.station-state i {
  width: 0.42rem;
  height: 0.42rem;
  flex: none;
  border-radius: 50%;
  background: var(--line-strong);
}
.station[data-state="working"] .station-state {
  color: var(--signal);
  background: var(--signal-wash);
  border-color: color-mix(in oklab, var(--signal) 30%, transparent);
}
.station[data-state="working"] .station-state i {
  background: var(--signal);
  animation: beacon 1.8s ease-out infinite;
}
.station[data-state="blocked"] .station-state {
  color: var(--warn);
  background: var(--warn-wash);
  border-color: color-mix(in oklab, var(--warn) 35%, transparent);
}
.station[data-state="blocked"] .station-state i {
  background: var(--warn);
  animation: beacon 1.2s ease-out infinite;
}

/* The dot sends out a ring in its own colour (`currentColor` is the chip's text). */
@keyframes beacon {
  0% { box-shadow: 0 0 0 0 color-mix(in oklab, currentColor 60%, transparent); }
  70%, 100% { box-shadow: 0 0 0 0.42rem color-mix(in oklab, currentColor 0%, transparent); }
}

.station-main {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.station-figure {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 2.4rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.05em;
}
.station[data-state="idle"] .station-figure { color: var(--ink-faint); }

.station-figure-label { font-size: 0.78rem; color: var(--ink-dim); }

/* The trend is drawn in the card's tone — violet while working, amber when stalled, grey
   when idle — so the colour already says which state the line belongs to. */
.station-trend {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  color: var(--tone);
}

.station-trend-head {
  display: flex;
  justify-content: space-between;
  font-size: 0.66rem;
  color: var(--ink-faint);
}

.station-trend-total {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
}

.station-spark-box {
  position: relative;
  height: 2.75rem;
}

.station-spark {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.spark-line {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.spark-hit { fill: transparent; }
.spark-hit:hover { fill: color-mix(in oklab, currentColor 12%, transparent); }

.spark-dot {
  position: absolute;
  right: -3px;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px color-mix(in oklab, currentColor 24%, transparent);
  pointer-events: none;
}

.station-spark-empty {
  display: block;
  height: 100%;
  border-bottom: 1px dashed var(--line);
}

/* Card heights are equalised by the grid; pushing the tiles to the bottom keeps their
   rows aligned from card to card. */
.station-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.2rem, 1fr));
  gap: 0.4rem;
  margin: auto 0 0;
}

.station-metrics div {
  padding: 0.38rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--panel-sunk);
  transition: background-color 0.3s ease, border-color 0.3s ease;
}
.station-metrics div[hidden] { display: none; }
.station-metrics div.hot {
  background: color-mix(in oklab, var(--tone) 9%, var(--panel));
  border-color: color-mix(in oklab, var(--tone) 30%, var(--line));
}
/* Labels wrap rather than truncate: "Done · 60 min" does not fit a third of a card, and a
   label cut to "Done · 60…" hides the window the number is counted over. */
.station-metrics dt {
  font-size: 0.64rem;
  line-height: 1.3;
  color: var(--ink-faint);
}
.station-metrics dd {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1rem;
}
.station-metrics div.hot dd { color: var(--tone); }

.station-foot {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.75rem;
  padding-top: 0.55rem;
  border-top: 1px dashed var(--line);
  font-size: 0.7rem;
  color: var(--ink-faint);
}
.station-foot .num { color: var(--ink-dim); }

/* Değişen sayı bir an vurgulanır ve söner: bir tikte neyin oynadığı, tüm ekranı
   yeniden çizmeden görünsün. */
.changed { animation: lift 0.9s ease-out; }

@keyframes lift {
  0% { color: var(--signal); transform: translateY(0.18em); }
  35% { color: var(--signal); transform: translateY(0); }
  100% { transform: translateY(0); }
}

.readout dd.tone-signal { color: var(--signal); }
.readout dd.tone-warn { color: var(--warn); }

/* --- Activity volume ------------------------------------------------------------ */

/* `.chart-svg` sets its height from the aspect ratio; here it is fixed, because the
   buckets deserve the same height at every screen width (`preserveAspectRatio="none"`)
   and switching between day, week and month should not make the card jump. */
.chart-svg.activity { width: 100%; height: 130px; }

.activity-bar { transition: fill 0.3s ease; }
.activity-bar.empty { opacity: 0.6; }

.legend {
  display: flex;
  gap: 1rem;
  margin-top: 0.6rem;
  font-size: 0.78rem;
  color: var(--ink-dim);
}
.legend-key { display: inline-flex; align-items: center; gap: 0.4rem; }
.legend-key i { width: 0.6rem; height: 0.6rem; border-radius: 2px; }
.legend-key.neutral i { background: var(--neutral); }
.legend-key.signal i { background: var(--signal); }

/* With reduced motion the dashboard still refreshes, it just does not move. */
@media (prefers-reduced-motion: reduce) {
  .live-dot::after,
  .station,
  .station-state i,
  .changed {
    animation: none !important;
  }
  .station:hover { transform: none; }
}

/* --- Tablolar ------------------------------------------------------------------ */

table { border-collapse: collapse; width: 100%; font-size: 0.9rem; }

caption {
  text-align: left;
  color: var(--ink-faint);
  font-size: 0.84rem;
  padding-bottom: 0.6rem;
}

th {
  text-align: left;
  font-weight: 550;
  color: var(--ink-dim);
  font-size: 0.82rem;
  padding: 0 0.85rem 0.5rem 0;
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}

td {
  padding: 0.55rem 0.85rem 0.55rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: baseline;
}

tbody tr:last-child td { border-bottom: 0; }

th.right, td.right { text-align: right; }
/* Yalnızca son sütun kenara dayanır; her sağa yaslı sütunda payı sıfırlamak
   komşu başlıkları birbirine yapıştırıyordu. */
th:last-child, td:last-child { padding-right: 0; }

.table-scroll { overflow-x: auto; }

/* Sayı yerine oran gösteren mikro çubuk: sütunun kendisi ölçek. */
.bar-cell { width: 8rem; min-width: 6rem; }
.microbar-track {
  display: block;
  height: 0.45rem;
  background: var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.microbar {
  display: block;
  height: 100%;
  background: var(--signal);
  border-radius: 999px;
  min-width: 2px;
}
.microbar.low { background: var(--warn); }

/* --- Kalibrasyon ---------------------------------------------------------------- */

.horizon-tabs {
  display: inline-flex;
  gap: 2px;
  margin-bottom: 1.25rem;
  padding: 3px;
  background: var(--panel-sunk);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.horizon-tabs button {
  background: transparent;
  color: var(--ink-dim);
  border: 0;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.83rem;
  padding: 0.25rem 0.85rem;
}

.horizon-tabs button:hover { filter: none; color: var(--ink); }

.horizon-tabs button[aria-pressed="true"] {
  color: var(--signal-ink);
  background: var(--signal);
}

.chart-figure { margin: 0; }

.chart-figure figcaption {
  color: var(--ink-faint);
  font-size: 0.84rem;
  margin-top: 0.7rem;
  max-width: var(--measure);
}

.chart-svg { display: block; width: 100%; height: auto; overflow: visible; }

.chart-svg .grid { stroke: var(--line); stroke-width: 1; }
.chart-svg .zero { stroke: var(--line-strong); stroke-width: 1; }
.chart-svg .tick { fill: var(--ink-faint); font-size: 11px; font-family: var(--mono); }
.chart-svg .bar-label { fill: var(--ink); font-size: 11px; font-family: var(--mono); }
.chart-svg .bar-sub { fill: var(--ink-faint); font-size: 10px; font-family: var(--mono); }
.chart-svg .bar { transition: opacity 120ms ease; }
.chart-svg .bar:hover { opacity: 0.82; }

/* Paper portföy (backlog item 18): iki çizgi, aynı eksen. Endeks çizgisi bilerek
   soluk ve kesikli — karşılaştırma ölçütü, ikinci bir sonuç değil. */
.chart-svg.portfolio { height: 260px; }
.chart-svg .pf-strategy { stroke: var(--signal); stroke-width: 2; fill: none; }
.chart-svg .pf-benchmark {
  stroke: var(--neutral);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  fill: none;
}
circle.pf-strategy { fill: var(--signal); stroke: none; }
circle.pf-benchmark { fill: var(--neutral); stroke: none; }
.portfolio-block .legend { margin-top: 0.4rem; }

/* Huni (claude-adjudication.md, Faz 0): skor kovaları + üstlerine çizilen iki kapı.
   Kapı çizgileri farklı renk DEĞİL farklı desen: ikisi de eşik, biri diğerinden daha
   "iyi" değil — gönderim kapısı sürekli, eskalasyon kapısı kesikli. */

/* Sabit yükseklik YOK: viewBox'ın en boy oranı korunuyor, yani sabit bir yükseklik
   geniş bir sütunda çizimi 720 pikselde bırakıp yanlarını boş bırakırdı. Yükseklik
   genişlikten türeyince yazılar da sütunla birlikte büyür — okunurluk sorunu tam
   olarak buradaydı. */
.chart-svg .funnel-bar { fill: var(--signal); opacity: 0.72; transition: opacity 120ms ease; }
.chart-svg .funnel-bar:hover { opacity: 0.92; }
.chart-svg .funnel-gate { stroke: var(--ink); stroke-width: 1.5; }
.chart-svg .funnel-gate.gate-escalation { stroke-dasharray: 4 3; stroke: var(--ink-dim); }

/* Kapı etiketi çizgisiyle aynı ağırlıkta olmalı: metnin hangi çizgiye ait olduğu
   ancak renkten okunur, ikisi de üstteki şeritte yan yana duruyor. */
.chart-svg .gate-label { fill: var(--ink); font-size: 11px; font-family: var(--mono); }
.chart-svg .gate-label.gate-escalation { fill: var(--ink-dim); }

/* Sayılar ızgaranın ve kapı çizgisinin ÜSTÜNDE duruyor ve çizgi bir kovanın tam
   ortasından geçebiliyor. Harflerin çevresine panel renginde ince bir kontur konur:
   kesişme artık sayıyı bozmuyor, çizgiyi de kesmiyor. */
.chart-svg.funnel .bar-label,
.chart-svg.funnel .tick {
  paint-order: stroke;
  stroke: var(--panel);
  stroke-width: 3px;
  stroke-linejoin: round;
}

.legend {
  display: flex;
  gap: 1.25rem;
  font-size: 0.82rem;
  color: var(--ink-dim);
  margin-top: 0.75rem;
  flex-wrap: wrap;
}
.legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
.legend i { width: 0.75rem; height: 0.75rem; border-radius: 2px; display: inline-block; }

.correlation { margin-top: 1.5rem; }
.correlation .row {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr) 4.5rem;
  align-items: center;
  gap: 1rem;
  padding: 0.45rem 0;
}
.correlation .axis {
  position: relative;
  height: 1.35rem;
  border-radius: var(--r-sm);
  background: var(--panel-sunk);
}
.correlation .axis::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  border-left: 1px solid var(--line-strong);
}
.correlation .axis > i {
  position: absolute;
  top: 0.4rem;
  height: 0.55rem;
  border-radius: 999px;
  background: var(--positive);
}
.correlation .axis > i.neg { background: var(--negative); }
.correlation .scale {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr) 4.5rem;
  gap: 1rem;
  font-size: 0.75rem;
  color: var(--ink-faint);
  font-family: var(--mono);
}
.correlation .scale div:nth-child(2) { display: flex; justify-content: space-between; }

.unreliable { color: var(--ink-faint); }

/* --- Fırsatlar ------------------------------------------------------------------ */

.filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  margin-bottom: 1rem;
  font-size: 0.88rem;
  color: var(--ink-dim);
}
/* Alan genişliği `width: 100%` varsayılanından geri alınır: burası dikey bir form
   değil tek satırlık bir çubuk, kutular içeriği kadar yer kaplamalı. */
.filters input[type="search"], .filters select {
  width: auto;
  padding: 0.35rem 0.5rem;
  font-size: 0.84rem;
}
.filters input[type="search"] { max-width: 8rem; }
/* İz araması sembol kutusu değil, cümlelik bir yer tutucu taşıyor. */
#trace-search { max-width: 16rem; }
.filters label { white-space: nowrap; }
.filters .num { margin-left: auto; }

.opportunity-list { display: flex; flex-direction: column; gap: 0.6rem; }

/* Katlanabilir kart (bkz. app.js, `opportunityRow`): kapalı satır taranmak, açık kart
   okunmak içindir. Düzen `summary`'ye değil içindeki satıra verilir — `summary`'nin
   `display`'ini değiştirmek bazı tarayıcılarda açma/kapamayı bozuyor (aynı ders
   `.step-summary`'de de yazılı). */
.opportunity {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 0.15rem 1.15rem;
}

.opportunity-summary {
  cursor: pointer;
  list-style: none;
  padding: 0.75rem 0;
}
.opportunity-summary::-webkit-details-marker { display: none; }
.opportunity-summary::marker { content: ""; }

.opportunity-summary-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.opportunity-summary:hover .headline,
.opportunity-summary:hover .step-caret { color: var(--signal); border-color: var(--signal); }
.opportunity[open] > .opportunity-summary .step-caret { transform: rotate(45deg); }

/* Kapakta başlık tek satır kalır: iki satıra taşan bir başlık, altındaki kartı aşağı
   itip listenin taranabilirliğini bitirir. */
.opportunity-summary .headline {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.opportunity .summary-side {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.8rem;
  color: var(--ink-dim);
  white-space: nowrap;
}
.opportunity .lead-score b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 550;
  color: var(--ink);
}
.opportunity .sent-mark { color: var(--ink-faint); }
.opportunity .sent-mark.sent { color: var(--positive); }

.opportunity-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 11rem);
  gap: 1.25rem;
  padding: 0.9rem 0 1rem 1.25rem;
  border-top: 1px solid var(--line);
}

.opportunity .ident {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: none;
}
.opportunity .ticker {
  font-family: var(--mono);
  font-size: 1.05rem;
  font-weight: 550;
  letter-spacing: -0.02em;
}

/* Yön etiketi: ölçüm bölümüyle aynı ıraksak çift, aynı anlam. */
.dir {
  font-size: 0.72rem;
  font-weight: 550;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  border: 1px solid currentColor;
}
.dir.buy { color: var(--positive); }
.dir.sell { color: var(--negative); }

.opportunity .headline { font-weight: 550; letter-spacing: -0.01em; }
.opportunity .thesis {
  color: var(--ink-dim);
  font-size: 0.88rem;
  max-width: var(--measure);
}
.opportunity .meta {
  font-size: 0.8rem;
  color: var(--ink-faint);
  margin-top: 0.45rem;
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}
.opportunity .scores {
  display: flex;
  gap: 0.9rem;
  font-size: 0.82rem;
  color: var(--ink-dim);
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}
.opportunity .scores b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 550;
  color: var(--ink);
}
.opportunity .measures { font-size: 0.82rem; }
.opportunity .measures div {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  padding: 0.1rem 0;
}

.verdict-tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 500;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--ink-dim);
}
.verdict-tag.rejected { color: var(--alert); border-color: var(--alert); }
/* Hâkimin etiketi verify'ınkiyle karışmasın: aynı satırda iki hüküm durur. */
.verdict-tag.judge { border-style: dashed; }

.more { margin-top: 1.25rem; }

/* --- Hesap ---------------------------------------------------------------------- */

.account { max-width: 54rem; }

/* Underlined tabs rather than the pill switch of the rail foot: those pick a setting,
   these pick a page of settings, and the panel below reads as hanging off the line. */
.tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1.25rem;
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs [role="tab"] {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex: none;
  background: none;
  color: var(--ink-dim);
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  margin-bottom: -1px;
  padding: 0.65rem 0.9rem;
  font-weight: 500;
  white-space: nowrap;
  transition: color 120ms ease, border-color 120ms ease;
}

.tabs [role="tab"] svg { width: 1.05rem; height: 1.05rem; flex: none; }
.tabs [role="tab"]:hover { color: var(--ink); filter: none; }

.tabs [role="tab"][aria-selected="true"] {
  color: var(--ink);
  border-bottom-color: var(--signal);
}

.tabs [role="tab"][aria-selected="true"] svg { color: var(--signal); }

/* One setting per panel: what it is on the left, the fields on the right. */
.tab-panel { padding: 1.5rem 1.6rem; }

.setting {
  display: grid;
  grid-template-columns: minmax(0, 16rem) minmax(0, 1fr);
  gap: 1.25rem 2.5rem;
}

.setting-head h3 { margin-bottom: 0.4rem; }
.setting-head .hint { margin-top: 0; }
.setting-body { max-width: 26rem; }
.setting-body button[type="submit"] { margin-top: 0.3rem; }

@media (max-width: 40rem) {
  .setting { grid-template-columns: minmax(0, 1fr); }
  .tab-panel { padding: 1.15rem 1.25rem; }
  /* Three tabs fit a 375 px phone only with tighter padding; past that the list scrolls. */
  .tabs [role="tab"] { padding: 0.6rem 0.55rem; gap: 0.4rem; }
}

.inline-check { display: flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; margin-bottom: 0.5rem; }
.status-line { font-size: 0.85rem; margin-top: 0.75rem; min-height: 1.2rem; }
.status-line.ok { color: var(--positive); }
.status-line.bad { color: var(--alert); }

/* Per-currency subtotals under the position table. One line per currency because the
   book is never converted: a second currency simply adds a row rather than joining a
   wrong sum. */
#position-totals { margin-top: 0.9rem; }
#position-totals h3 { font-size: 0.95rem; }
#position-totals .hint { margin-bottom: 0.8rem; }

/* The current price is a chip in the accent colour so it never reads as the buy price
   next to it; the day's direction colours only the change, and the time sits inside. */
.price-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.12rem 0.6rem;
  border-radius: 999px;
  background: var(--signal-wash);
  color: var(--signal);
  border: 1px solid color-mix(in oklab, var(--signal) 30%, transparent);
  white-space: nowrap;
  font-size: 0.85rem;
}
.price-chip b { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 600; }
.price-chip .chip-change { font-family: var(--mono); font-size: 0.74rem; }
.price-chip.up .chip-change { color: var(--positive); }
.price-chip.down .chip-change { color: var(--negative); }
.price-chip time { font-size: 0.72rem; color: var(--ink-dim); }

.holding-since { display: block; font-size: 0.74rem; }

/* A label over a number: the building block of the purchase and sale previews. */
.figure { display: inline-flex; flex-direction: column; gap: 0.05rem; }
.figure small { font-size: 0.72rem; color: var(--ink-dim); }
.figure.pos b { color: var(--positive); }
.figure.neg b { color: var(--negative); }
.sell-pnl b { font-size: 1.1rem; }

/* What the purchase resolves to and what it totals, under the add form. */
.add-preview {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 1.2rem;
  margin-top: 0.75rem;
  font-size: 0.88rem;
}
.add-preview:empty { display: none; }
.lookup-name { font-weight: 550; }

.sell-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem;
  margin-top: 0.6rem;
}
.sell-form .field { margin-bottom: 0; }
.sell-form input { width: 8rem; padding: 0.35rem 0.5rem; font-size: 0.9rem; }
.sell-form button { padding: 0.35rem 0.75rem; font-size: 0.9rem; }
.input-with { display: flex; align-items: center; gap: 0.3rem; }

.sell-preview {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 1.4rem;
  margin-top: 0.7rem;
  min-height: 1.6rem;
}

/* The ticker field's suggestion list. Positioned over the page rather than pushing the
   form down: a list that reflowed the fields under it would move the quantity input away
   from the cursor on every keystroke. */
.field-suggest { position: relative; }

.suggest-list {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.25rem);
  left: 0;
  /* The ticker field itself is narrow (7rem); the list has to hold a company name, so it
     is allowed to be wider than what it hangs from. */
  min-width: min(24rem, 80vw);
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  max-height: 17rem;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: var(--lift);
}

.suggest-list li { margin: 0; }

.suggest-row {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  width: 100%;
  padding: 0.4rem 0.5rem;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.suggest-row:hover,
.suggest-row:focus-visible { background: var(--panel-sunk); }
.suggest-row b { font-size: 0.9rem; }
/* The name is the part that catches the wrong company, so it may wrap rather than being
   cut off at the edge of the list. */
.suggest-name { font-size: 0.84rem; }
.suggest-row small { font-size: 0.72rem; }
.suggest-empty { padding: 0.4rem 0.5rem; font-size: 0.85rem; }

/* --- Portfolio ------------------------------------------------------------------ */

/* One card per currency, never a combined figure: nothing is converted. The cards are
   capped rather than stretched — a lone GBP wallet spanning the whole page would make
   one currency look like the whole book. */
.wallets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15.5rem, 21rem));
  gap: 1rem;
}

/* The card fills its grid cell and the figures are pushed to its foot, so the rule above
   them lands on the same line in every card however much one wallet has to say about
   money that has not settled. */
.wallet { display: flex; flex-direction: column; gap: 0.15rem; height: 100%; }

.wallet-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
.wallet-head small { font-size: 0.78rem; color: var(--ink-dim); }
.wallet-code {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.05rem 0.3rem;
}

/* The one loud number on the screen: what the next purchase is sized against. */
.wallet-cash {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.75rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
}
.wallet-cash.neg { color: var(--negative); }

/* Money that exists but cannot be spent today, never folded into the figure above it:
   the optimistic reading is the expensive one here. */
.wallet-pending { margin: 0.35rem 0 0; font-size: 0.82rem; color: var(--ink-dim); }
.wallet-pending .num { color: var(--ink); }

.wallet-schedule { margin-top: 0.45rem; }
.wallet-schedule > summary {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.82rem;
  color: var(--ink-dim);
  cursor: pointer;
  list-style: none;
}
.wallet-schedule > summary::-webkit-details-marker { display: none; }
.wallet-schedule > summary:hover { color: var(--ink); }
.wallet-schedule .mini-table { margin-top: 0.4rem; }
/* The header names a balance, not a movement, so it is allowed the two lines it needs
   in a card this narrow; the rows themselves stay on one. */
.schedule-table th { white-space: normal; }
.schedule-table td { white-space: nowrap; }
.schedule-table td small { display: block; font-size: 0.72rem; }

.wallet-rows {
  /* Pushed to the foot of the card, so the rule above these figures lands on the same
     line in every card however much one wallet has to say about money in transit. */
  margin: auto 0 0;
  padding-top: 0.8rem;
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.3rem 1rem;
  font-size: 0.87rem;
}
.wallet-rows dt { color: var(--ink-dim); }
.wallet-rows dd {
  margin: 0;
  text-align: right;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.wallet-rows dd.pos { color: var(--positive); }
.wallet-rows dd.neg { color: var(--negative); }
.wallet-rows dd.muted { font-family: var(--sans); color: var(--ink-faint); }

.wallet-warn { margin: 0.6rem 0 0; font-size: 0.8rem; color: var(--negative); }

/* The shared chevron of the two things this screen folds away. */
.wallet-schedule > summary::before,
.ledger > summary::before {
  content: "";
  flex: none;
  width: 0.36rem;
  height: 0.36rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 120ms ease;
}
.wallet-schedule[open] > summary::before,
.ledger[open] > summary::before { transform: rotate(45deg); }

/* A section heading with its controls on the same line. */
.block-head .block-actions {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-left: auto;
}
.block-head .inline-check { margin: 0; font-size: 0.85rem; }

.drawer { margin-bottom: 1rem; }
.drawer[hidden] { display: none; }

/* --- Holdings -------------------------------------------------------------------- */

/* The name column takes the slack; every other column sizes to its own number, so the
   figures stay in a block on the right instead of drifting apart. */
/* Scoped to its own rows throughout: the panel that opens under a holding carries a
   table of its own, and a bare descendant selector would size and hide that one too. */
.holdings-table > tbody > tr > td:first-child { min-width: 11rem; }
.holdings-table > thead > tr > th:not(:first-child),
.holdings-table > tbody > tr > td:not(:first-child) { white-space: nowrap; }

.holding-name { display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap; }
.holding-name b { font-size: 0.95rem; }

/* The verdict of the scheduled review, next to the name it is about. HOLD is not written
   at all: the default is silence, and a column of "HOLD" says nothing. */
.verdict {
  font-size: 0.7rem;
  font-weight: 550;
  white-space: nowrap;
  border-radius: var(--r-sm);
  padding: 0.05rem 0.3rem;
  border: 1px solid color-mix(in oklab, var(--warn) 35%, transparent);
  background: var(--warn-wash);
  color: var(--warn);
}

/* What the columns hidden on a narrow screen carry instead. */
.holding-facts { display: none; }

/* Gain and loss read as one figure with its parts underneath, rather than three columns
   the reader has to add up. Amount and percentage are separate elements: when the column
   narrows, the percentage takes its own line cleanly instead of leaving a separator
   dangling at the start of a wrapped one. */
td.pnl-cell .pnl-pct::before {
  content: "·";
  margin: 0 0.35em;
  color: var(--ink-faint);
}
td.pnl-cell small {
  display: block;
  margin-top: 0.1rem;
  font-family: var(--sans);
  font-size: 0.72rem;
  color: var(--ink-faint);
}

/* --- Cash ledger ----------------------------------------------------------------- */

/* A log, not a figure: closed by default and under the holdings. What can be invested
   today is in the wallets at the top of the page. */
.ledger > summary {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.5rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--display);
  font-size: 1.05rem;
  font-weight: 600;
}
.ledger > summary::-webkit-details-marker { display: none; }
.ledger > summary::before { align-self: center; color: var(--ink-faint); }
.ledger > summary small {
  font-family: var(--sans);
  font-size: 0.82rem;
  font-weight: 400;
  color: var(--ink-faint);
}
.ledger-body { padding-top: 0.5rem; }

/* What the log is for on the left, the way to write to it on the right — the same head
   the holdings block carries, so the two halves of the portfolio screen are read the same
   way. */
.ledger-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.25rem;
  margin-bottom: 1rem;
}
.ledger-head .hint { margin-top: 0; }
.ledger-head button { flex: none; white-space: nowrap; }

/* The note takes whatever the other columns leave; everything else sizes to its own
   content and stays on one line. A date broken after the comma reads as two dates, and an
   amount broken after its sign leaves a minus alone at the end of a line. */
.cash-table > thead > tr > th,
.cash-table > tbody > tr > td { white-space: nowrap; }
.cash-table > tbody > tr > td { vertical-align: top; }
/* The two cells made of words rather than figures wrap; they are written with the same
   path as the rule above, which would otherwise win on specificity and push a long note
   off the side of the card. */
.cash-table > tbody > tr > td.cash-note { width: 100%; white-space: normal; }
.cash-table > tbody > tr > td.cash-movement { white-space: normal; }

/* The note column takes every pixel the others leave, so this one has to ask for what
   it needs: under 10rem the line naming the trade a row came from breaks in two, and a
   two-line cell in a table of one-line cells reads as a second entry. */
.cash-movement { min-width: 10rem; }
.cash-kind { display: block; }
/* Its own line under the kind: side by side, at the width this column gets, the two ran
   together into one word. */
.cash-origin {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.74rem;
  color: var(--ink-faint);
}

/* The amount is the cell being scanned for, so it keeps the colour that says which way
   the money went — but not also the weight: a column where every row is bold and coloured
   has no emphasis left for the row that matters. */
.cash-amount { font-weight: 500; }

/* Three answers, one column. Most rows have landed and are written faintly; the row still
   waiting keeps full ink and a marker, because that is the row a purchase has to wait
   for. */
.cash-settles.landed { color: var(--ink-faint); }
.cash-settles.pending::before,
.cash-facts.pending::before {
  content: "";
  display: inline-block;
  width: 0.34rem;
  height: 0.34rem;
  margin-right: 0.4rem;
  vertical-align: 0.08em;
  border-radius: 50%;
  background: var(--warn);
}
/* Money whose settlement date nobody filled in: not late, just unknown — so it is marked
   rather than coloured like a problem. */
.cash-settles.unknown {
  color: var(--ink-dim);
  text-decoration: underline dotted var(--line-strong);
  text-underline-offset: 0.25em;
  cursor: help;
}

.cash-table .cash-note { color: var(--ink-faint); }
.cash-blank { color: var(--ink-faint); border-bottom: 0; }

/* Removing a movement is rare and irreversible, so it does not sit in the reader's way:
   the button is there on the row under the pointer, and for anyone arriving by keyboard
   the moment it takes focus. */
.cash-table td.cash-action { width: 1%; }
.cash-remove {
  padding: 0.25rem 0.55rem;
  font-size: 0.78rem;
  opacity: 0;
  transition: opacity 120ms ease;
}
.cash-table > tbody > tr:hover .cash-remove,
.cash-remove:focus-visible { opacity: 1; }
/* The tint is what makes the appearing button legible: without it a control fades in with
   nothing saying which row it belongs to. */
.cash-table > tbody > tr:hover > td { background: var(--panel-sunk); }
/* Nothing hovers on a touch screen. */
@media (hover: none) {
  .cash-remove { opacity: 1; }
}

/* What the two columns dropped on a narrow screen carry instead; on a wide one the
   columns themselves say it. */
.cash-facts { display: none; }

@media (prefers-reduced-motion: reduce) {
  .wallet-schedule > summary::before,
  .ledger > summary::before,
  .cash-remove { transition: none; }
}

/* Narrow screens: the holdings table drops to what a phone can read — the share, what it
   is worth and what it has made. The columns that go carry their numbers under the name
   instead, so nothing is lost and nothing scrolls sideways. */
@media (max-width: 54rem) {
  .holdings-table > thead > tr > th:nth-child(2),
  .holdings-table > tbody > tr > td:nth-child(2),
  .holdings-table > thead > tr > th:nth-child(3),
  .holdings-table > tbody > tr > td:nth-child(3),
  .holdings-table > thead > tr > th:nth-child(4),
  .holdings-table > tbody > tr > td:nth-child(4) { display: none; }

  .holding-facts {
    display: block;
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.74rem;
    color: var(--ink-dim);
  }

  .holdings-table > tbody > tr > td:first-child { min-width: 0; }
  .holdings-table > thead > tr > th,
  .holdings-table > tbody > tr > td { padding-right: 0.35rem; }
  /* Same path as the nowrap rule above, or it loses to it on specificity and a cost
     warning stretches the column off the screen. */
  .holdings-table > tbody > tr > td.pnl-cell { white-space: normal; }
  /* The cell may wrap between the amount and the percentage; the amount itself may not
     — a minus sign left alone at the end of a line reads as a dash. */
  .holdings-table > tbody > tr > td.pnl-cell b { white-space: nowrap; }
  .holding-facts { white-space: nowrap; }
  .block-head .block-actions button { white-space: nowrap; }
  /* Three figures and a button have to share a phone, so the row gives up what it can
     afford to: the card's side padding, a little type, and the bulk of a desktop
     button. */
  .holdings-table > thead > tr > th,
  .holdings-table > tbody > tr > td { font-size: 0.8rem; }
  .holdings-table > tbody > tr > td button { padding: 0.3rem 0.5rem; font-size: 0.8rem; }
  .card:has(> .holdings-table) { padding: 0.9rem 0.7rem; }
  /* The split between what is still open and what was banked is detail; the total is the
     figure a phone has room for. The panel underneath still carries both. */
  .holdings-table td.pnl-cell small { display: none; }
  .holdings-table td.pnl-cell .pnl-pct { display: block; }
  .holdings-table td.pnl-cell .pnl-pct::before { content: none; }

  .wallets { grid-template-columns: minmax(0, 1fr); }
  .block-head .block-actions { width: 100%; margin-left: 0; }
  /* The stacking rules for `.row-form` are NOT here: they lose to the base rule, which is
     written further down the file at the same specificity. They sit under it instead. */

  /* The ledger drops to what a phone can read — what happened, and how much. The
     settlement date and the note move under the movement rather than being lost, the same
     way the holdings table folds its columns. */
  .cash-table > thead > tr > th:nth-child(4),
  .cash-table > tbody > tr > td:nth-child(4),
  .cash-table > thead > tr > th:nth-child(5),
  .cash-table > tbody > tr > td:nth-child(5) { display: none; }

  .cash-facts {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.74rem;
    color: var(--ink-dim);
  }

  .cash-table > thead > tr > th,
  .cash-table > tbody > tr > td { font-size: 0.8rem; padding-right: 0.35rem; }
  .card:has(> .cash-table) { padding: 0.9rem 0.7rem; }
  /* Always on here — nothing hovers — and it gives back the width it takes by dropping
     its label: four columns and a written-out “Remove” are some thirty pixels more than a
     360px card has, and this is the only column that can give them up without losing an
     answer. The name stays on the button itself (`aria-label`), so nothing changes for a
     reader that listens rather than looks. */
  .cash-remove { font-size: 0; line-height: 1; padding: 0.45rem 0.6rem; }
  .cash-remove::after { content: "\00D7"; font-size: 1.05rem; line-height: 1; }
  /* The width the movement asks for is the last thing standing between four columns and
     the edge of a 360px card; the kind wraps onto a second line instead. */
  .cash-movement { min-width: 6rem; }
  /* A date is the widest thing a phone has to keep whole, and mono type sets it wider
     than it needs to be; tightening it buys the column that would otherwise scroll. */
  .cash-table > tbody > tr > td.cash-date { letter-spacing: -0.04em; padding-right: 0.3rem; }
  /* The ledger head stacks: the button keeps its own line rather than squeezing the
     sentence that explains the section into a column. */
  .ledger-head { flex-direction: column; gap: 0.75rem; }
}

.sales-block { flex: 2 1 22rem; }
.mini-table { margin-top: 0.5rem; font-size: 0.85rem; }
.mini-table td { padding-top: 0.35rem; padding-bottom: 0.35rem; }

/* --- Row forms -------------------------------------------------------------------
   One line of fields and a button — the recipient form, the purchase form, the cash
   form — wrapping onto a second line when they no longer fit. */

.row-form .row-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.9rem;
}

.row-form .row-fields .field { margin-bottom: 0; }
.row-form .row-fields button { flex: none; }

/* One field per line on a phone, each the full width of the card.
   This block has to come AFTER the base rule above: the two carry the same specificity,
   so written earlier — which is where it was until the cash form made it visible — the
   media query loses and the fields keep their own widths, ragged and pushed to the right
   edge by `align-items: flex-end`. */
@media (max-width: 54rem) {
  .row-form .row-fields { flex-direction: column; align-items: stretch; }
  .row-form .row-fields button { align-self: flex-start; }
}

/* Every width below is a width for a ROW. Stacked, a flex-basis is read as a HEIGHT, and
   the same numbers turn six fields into six 8-to-14rem tall boxes. So they are confined
   to the wide layout rather than undone underneath it: a reset has to out-specify every
   rule it covers, and the two the reset missed — a `:first-child` and a `:has()` — are
   exactly the kind the next form adds. */
@media (min-width: 54.0625rem) {
  .row-form .row-fields .field { flex: 1 1 9rem; }
  /* The recipient form: the address is the field that needs the room. */
  .row-form .row-fields .field:first-child { flex: 2 1 16rem; }

  /* The purchase form: four fields and a button. A symbol does not need the width an
     email address does; the date field takes enough for the picker icon and a written
     date. */
  #position-add .row-fields .field { flex: 1 1 8rem; }
  #position-add .row-fields .field:first-child { flex: 1 1 7rem; }
  #position-add .row-fields .field-date,
  #position-add .row-fields .field:has(input[type="date"]) { flex: 1.2 1 9.5rem; }

  /* The cash form: six fields and a button, so it wraps onto a second line on most
     screens. The note — the one field with no width of its own — is given the slack,
     and the button rides at the end of the line rather than being left alone under the
     first field. */
  #cash-add .row-fields .field { flex: 1 1 8rem; }
  #cash-add .row-fields .field-short { flex: 0 1 5.5rem; }
  #cash-add .row-fields .field-date { flex: 1.2 1 9.5rem; }
  #cash-add .row-fields .field-note { flex: 3 1 14rem; }
}

/* Satır içi düzenleme alanları: tabloyu forma çevirmeden, hücre yüksekliğinde. */
.cell-input {
  padding: 0.35rem 0.5rem;
  font-size: 0.85rem;
  min-width: 5rem;
  width: auto;
}

/* The row opens a panel underneath instead of holding a form in its last cell: closing
   by amount, correcting a cost and reading the three numbers behind a P&L all need more
   room than a column has. The panel is a sibling row spanning the table, not a nested
   table, so the columns above it stay where they are. */
tr.panel-row > td {
  padding: 0;
  background: var(--panel-sunk);
  border-top: 0;
}

.position-panel {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  padding: 1rem 0.75rem 1.2rem;
}

.panel-block { flex: 1 1 15rem; min-width: 0; }
.panel-block h4 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; }
.panel-block .hint { margin-top: 0.5rem; }

.panel-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
}

.panel-form input { width: 7rem; padding: 0.35rem 0.5rem; font-size: 0.9rem; }
.panel-form select { width: auto; padding: 0.35rem 0.4rem; font-size: 0.9rem; }
.panel-form button { padding: 0.35rem 0.75rem; font-size: 0.9rem; }

/* Cost and current worth read as a pair; the difference sits under them because it is
   what the pair was shown for. */
.panel-figures {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  gap: 0.2rem 1.2rem;
  margin-top: 0.6rem;
  font-size: 0.9rem;
}

.panel-figures dt { color: var(--ink-dim); }
.panel-figures dd { text-align: right; }

.panel-diff { margin-top: 0.5rem; font-size: 1.25rem; }
.panel-diff span { font-size: 0.9rem; }
.panel-diff.pos { color: var(--positive); }
.panel-diff.neg { color: var(--negative); }

td.center, th.center { text-align: center; }

/* Pasif alıcı listede kalır ama satırı söner: kapatıldığı görünmeli. */
tbody tr.muted-row td:not(:last-child) { color: var(--ink-faint); }

button.quiet.danger { color: var(--alert); }
button.quiet.danger:hover { border-color: var(--alert); }
button.quiet:disabled { opacity: 0.4; cursor: not-allowed; }

/* --- Durum bildirimi -------------------------------------------------------------- */

.loading, .failed { color: var(--ink-faint); font-size: 0.88rem; padding: 0.5rem 0; }
.failed { color: var(--alert); }

.empty {
  color: var(--ink-dim);
  font-size: 0.9rem;
  text-align: center;
  padding: 2.5rem 1rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  max-width: none;
}

.tooltip {
  position: fixed;
  z-index: 10;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: var(--lift);
  padding: 0.5rem 0.7rem;
  font-size: 0.8rem;
  font-family: var(--mono);
  pointer-events: none;
  white-space: pre-line;
}
.tooltip[hidden] { display: none; }

/* --- İz ------------------------------------------------------------------------
 *
 * Solda seçim, sağda zincir. Adımlar dikey bir hatta dizilir ve numaralanır —
 * burada numara süs değil: sıra gerçek, bir haber adımları bu sırayla geçti ve
 * verify geri gönderdiyse aynı adım ikinci kez görünür.
 */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.trace-layout {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.trace-picker {
  position: sticky;
  top: 4.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: calc(100vh - 6rem);
}

#trace-list {
  /* Sütunun kalanını kaydırılabilir liste alır; `min-height` olmadan flex çocuğu
     küçülmeyi reddedip yan sütunu taşırıyor. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 2px;
}

.trace-item {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 0.6rem 0.7rem;
  font-weight: 400;
  cursor: pointer;
}

.trace-item:hover { filter: none; background: var(--panel-sunk); }

.trace-item[aria-current="true"] {
  border-color: var(--signal);
  background: var(--signal-wash);
}

.trace-item-title {
  display: block;
  font-size: 0.88rem;
  font-weight: 500;
  line-height: 1.35;
  /* Başlıklar uzun; iki satırda kesilir ki liste taranabilir kalsın. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.trace-item-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.3rem;
  font-size: 0.75rem;
  color: var(--ink-faint);
}

/* --- Adım zinciri ---------------------------------------------------------------- */

/* Her adım katlanır bir `details`. Varsayılan kapalı: iz tekrar turlarıyla on adımı
   geçebiliyor ve hepsi açıkken aranan adım ancak kaydırılarak bulunuyordu. */

.steps-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  font-size: 0.82rem;
}
.steps-head .quiet { margin-left: auto; }

.steps { display: flex; flex-direction: column; }

.step { position: relative; padding-left: 1.6rem; }

/* Adımları birbirine bağlayan hat. Son adımda kesilir. */
.step::before {
  content: "";
  position: absolute;
  left: 0.31rem;
  top: 1.6rem;
  bottom: 0;
  width: 2px;
  background: var(--line);
}
.step:last-child::before { display: none; }

/* `summary` blok kalır; düzen içindeki satıra verilir. `display`'ini flex'e çevirmek
   bazı tarayıcılarda `details`'in açma/kapamasını bozuyor. */
.step-summary {
  cursor: pointer;
  list-style: none;
  padding: 0.55rem 0;
}
.step-summary::-webkit-details-marker { display: none; }
.step-summary::marker { content: ""; }

.step-summary-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Katlanabilirliğin görünür işareti. Yalnızca imleç değişimi yeterli değildi:
   dokunmatik bir ekranda hover diye bir şey yok. */
.step-caret {
  width: 0.5rem;
  height: 0.5rem;
  border-right: 1.5px solid var(--ink-faint);
  border-bottom: 1.5px solid var(--ink-faint);
  transform: rotate(-45deg);
  transition: transform 0.12s ease;
}
.step[open] > .step-summary .step-caret { transform: rotate(45deg); }

.step-summary:hover .step-title,
.step-summary:hover .step-caret { color: var(--signal); border-color: var(--signal); }

.step-dot {
  position: absolute;
  left: 0;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: var(--signal);
  /* Kapalı adım soluk, açık adım dolu: hangilerinin açıldığı hattan okunur. */
  opacity: 0.45;
}
.step[open] > .step-summary .step-dot { opacity: 1; }

.step-when {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.75rem;
  color: var(--ink-faint);
  white-space: nowrap;
}

.step-title {
  font-family: var(--display);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.step-body { margin: 0 0 0.75rem; }

.step-intro { margin: 0 0 0.75rem; font-size: 0.85rem; color: var(--ink-faint); }

.step-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.75rem;
  color: var(--ink-faint);
  padding-bottom: 0.75rem;
  margin-bottom: 0.75rem;
  border-bottom: 1px solid var(--line);
}

.step .headline { font-weight: 550; letter-spacing: -0.01em; margin: 0 0 0.75rem; }

.sub { margin-top: 1rem; }
.sub h4 {
  font-family: var(--display);
  font-size: 0.88rem;
  font-weight: 600;
  margin: 0 0 0.4rem;
}

/* --- Etiket/değer listesi --------------------------------------------------------- */

.kv-list { margin: 0; display: flex; flex-direction: column; gap: 0.55rem; }

.kv { display: grid; grid-template-columns: minmax(6rem, 9rem) minmax(0, 1fr); gap: 0.9rem; }

.kv dt { font-size: 0.82rem; color: var(--ink-dim); }
/* Etiketsiz satır: değer tam genişliği alır, boş bir sütun bırakmaz. */
.kv:has(dt:empty) { grid-template-columns: minmax(0, 1fr); }
.kv dt:empty { display: none; }
.kv dd { margin: 0; font-size: 0.9rem; }
.kv dd b { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* Eşik rozetleri: geçti/durdu hem renkle hem kelimeyle söylenir. */
.gate {
  display: inline-block;
  margin-left: 0.5rem;
  font-size: 0.75rem;
  padding: 0.05rem 0.5rem;
  border-radius: 999px;
  border: 1px solid currentColor;
}
.gate.pass { color: var(--positive); }
.gate.stop { color: var(--negative); }

.bullets { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: 0.25rem; }
.bullets li { font-size: 0.88rem; }

.findings { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.findings > li { display: grid; grid-template-columns: 6.5rem minmax(0, 1fr); gap: 0.75rem; }

/* Statü rozeti. Çıplak metin olarak yazıldığında başlığın devamı gibi okunuyordu. */
.chip {
  display: inline-block;
  font-size: 0.72rem;
  line-height: 1.5;
  padding: 0.05rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--panel-sunk);
  color: var(--ink-dim);
  white-space: nowrap;
}
/* Son duraklar renkle ayrılır: bir haberin gönderildiği mi yoksa elendiği mi, listede
   tarayarak görülmesi gereken tek şey. */
.chip.status-notified { color: var(--positive); border-color: currentColor; }
.chip.status-failed,
.chip.status-rejected { color: var(--negative); border-color: currentColor; }
.chip.status-discarded,
.chip.status-expired,
.chip.status-no_opportunity,
.chip.status-below_threshold { color: var(--ink-faint); }

/* Yan panelde başlığın altındaki satır dar; rozet oraya sığmak zorunda. */
.trace-item-meta .chip { font-size: 0.7rem; padding: 0 0.45rem; }

.tag {
  align-self: start;
  font-size: 0.72rem;
  padding: 0.05rem 0.5rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  text-align: center;
}
.tag.supports { color: var(--positive); }
.tag.contradicts { color: var(--negative); }

.claim { margin: 0; font-size: 0.9rem; font-weight: 500; }
.evidence { margin: 0.2rem 0 0; font-size: 0.88rem; color: var(--ink-dim); }
.source {
  display: inline-block;
  margin-top: 0.2rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  overflow-wrap: anywhere;
}

/* --- Katlanır bloklar -------------------------------------------------------------- */

.disclosure { margin-top: 0.9rem; }

.disclosure > summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--ink-dim);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
}

.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::before { content: "+"; font-family: var(--mono); }
.disclosure[open] > summary::before { content: "−"; }
.disclosure > summary:hover { color: var(--ink); }

.raw {
  margin: 0.6rem 0 0;
  padding: 0.75rem 0.85rem;
  background: var(--panel-sunk);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-family: var(--mono);
  font-size: 0.78rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 28rem;
  overflow-y: auto;
}

table.compact { font-size: 0.85rem; }
table.compact th { font-size: 0.78rem; }
table.compact td { padding-top: 0.35rem; padding-bottom: 0.35rem; }

@media (max-width: 64rem) {
  .trace-layout { grid-template-columns: minmax(0, 1fr); }
  .trace-picker { position: static; max-height: none; }
  #trace-list { max-height: 22rem; }
  .findings > li { grid-template-columns: minmax(0, 1fr); gap: 0.35rem; }
  .tag { justify-self: start; }
  .kv { grid-template-columns: minmax(0, 1fr); gap: 0.15rem; }
}

@media (max-width: 64rem) {
  /* `start`, not the default stretch: with `min-height: 100vh` the grid handed any height
     the content left over to the rail row, so a shorter view (or account tab) grew the top
     bar and pushed the heading down. */
  .shell { grid-template-columns: minmax(0, 1fr); align-content: start; }
  .rail {
    position: static;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--line);
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.75rem 1rem;
  }
  .rail .wordmark { flex: 1; }

  /* The rail does not fit on one line, so navigation and foot both move into the
     drawer: while closed the header holds only the wordmark and the button. */
  .rail > nav,
  .rail-foot { display: none; }
  .rail.menu-open > nav {
    display: flex;
    flex-basis: 100%;
    gap: 2px;
  }
  .rail.menu-open .rail-foot { display: flex; }
  .menu-toggle {
    background: none;
    border: none;
    color: var(--ink-dim);
    width: 2rem;
    height: 2rem;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border-radius: var(--r-md);
    transition: color 120ms ease, background 120ms ease;
  }
  .menu-toggle:hover { color: var(--ink); background: var(--panel); }
  .menu-toggle svg { width: 1.3rem; height: 1.3rem; }
  .rail-foot {
    flex-basis: 100%;
    margin-top: 0.2rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--line);
  }
  .opportunity-body { grid-template-columns: minmax(0, 1fr); gap: 0.7rem; padding-left: 0; }
  /* Dar ekranda kapak sarılır; başlık kendi satırını alır ve kırpılmaz. */
  .opportunity-summary-row { flex-wrap: wrap; gap: 0.5rem; }
  .opportunity-summary .headline { flex-basis: 100%; white-space: normal; }
  .opportunity .summary-side { margin-left: 0; }
}

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

/* Bir tablo hücresinde alt alta duran birkaç küçük öğe (durum rozeti + düğme, ya da kod +
   açıklama). Hücreyi genişletmemesi için satır sarması serbest bırakılır. */
.cell-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
}
.cell-stack code {
  font-size: 0.85rem;
  letter-spacing: 0.05em;
}
