/* =============================================================================
   MatchCore shared shell -- header, catalog cards, trading-view panels,
   forms, tables, toasts, modals: everything that was previously duplicated
   near-identically across frontend/clob/css/style.css,
   frontend/pari-mutuel/css/style.css and frontend/stock-exchange/css/style.css.

   Each frontend/<principle>/css/style.css now just does:
     @import "../../css/tokens.css";
     @import "../../css/shell.css";
   plus whatever handful of rules are genuinely principle-specific (see the
   comment at the top of each of those files for what's left).

   Everything below reads tokens.css custom properties only -- never a
   literal color/radius/shadow/font -- so both themes repaint for free.
   ============================================================================= */
@import "tokens.css";

* { box-sizing: border-box; }

html, body { height: 100%; }

/* Flex column, not position:fixed/sticky -- a fixed footer would permanently overlap the ladder/
   chart on every scroll position, wrong for a legal notice on a data-dense page. This just pins
   the footer to the viewport bottom on short pages (an empty admin form, an account page with no
   positions) while letting it flow normally below content on long ones -- the standard "sticky
   footer" layout, distinct from position:sticky. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

/* ---- Header ---------------------------------------------------------- */
header.matchcore-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px;
  background: var(--panel-bg);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  position: sticky;
  top: 0;
  z-index: 10;
}

header.matchcore-header .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.02em;
  color: var(--ink-950);
}

/* Zero-asset brand mark -- an inline SVG wordmark (frontend/js/branding.js's
   wordmarkSvg(), auto-filled into every .brand-mark on page load), not a
   raster logo file, so there's nothing to source/license/replace to get a
   real wordmark on screen, and it repaints for free on the dark-mode toggle
   since it's colored via var(--accent)/var(--accent-2). */
.brand-mark {
  width: 26px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.brand-mark svg { width: 100%; height: 100%; }

header.matchcore-header .brand .brand-sub {
  font-weight: 500;
  color: var(--text-dim);
  font-size: 13px;
  margin-left: 2px;
}

header.matchcore-header nav a {
  margin-left: 20px;
  color: var(--text-dim);
  font-size: 14px;
  font-weight: 500;
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
header.matchcore-header nav a:hover { color: var(--text); }
header.matchcore-header nav a.active { color: var(--accent); border-color: var(--accent); }

.header-actions { display: flex; align-items: center; gap: 14px; }

.theme-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel-bg);
  color: var(--text-dim);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.theme-toggle-btn:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle-btn svg { width: 16px; height: 16px; }
.theme-toggle-btn .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle-btn .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle-btn .icon-moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle-btn .icon-sun { display: none; }
  :root:not([data-theme="light"]) .theme-toggle-btn .icon-moon { display: block; }
}

#session-widget {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
}

#session-widget .session-edit-btn {
  border: 1px solid var(--border);
  background: var(--panel-bg);
  border-radius: var(--radius-sm);
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
#session-widget .session-edit-btn:hover { border-color: var(--accent); color: var(--accent); }

main { max-width: 1120px; margin: 0 auto; padding: var(--space-5); flex: 1 0 auto; width: 100%; }

/* ---- Closed-market banner (frontend/js/marketHours.js) -- takes over #app-root's content
   outside Mon-Fri 15:00-19:00 CET/CEST, when the trading backend itself is stopped (only gateway/
   nginx stay up). Deliberately plain and calm, not an error page -- this is expected, scheduled
   downtime, not something broken. ------------------------------------------------------------ */
.market-closed-banner {
  max-width: 480px;
  margin: var(--space-6) auto;
  padding: var(--space-6) var(--space-5);
  text-align: center;
}
.market-closed-icon { font-size: 40px; margin-bottom: var(--space-3); }
.market-closed-banner h1 { font-size: 24px; margin: 0 0 var(--space-3); letter-spacing: -0.01em; }
.market-closed-banner p { color: var(--text-dim); font-size: 15px; margin: 0 0 var(--space-2); }
.market-closed-countdown { font-size: 17px; color: var(--text); }
.market-closed-countdown span { font-family: var(--mono); font-weight: 700; color: var(--accent); }

/* ---- Catalog -- Polymarket-style cards: question, big colored probability,
   category, volume ------------------------------------------------------ */
.market-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: var(--space-4);
}

.market-card {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}

.market-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}

.market-card .question {
  font-weight: 600;
  font-size: 15px;
  line-height: 1.35;
  min-height: 40px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.market-card .row { display: flex; align-items: center; justify-content: space-between; }

.probability-pill {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 20px;
  padding: 4px 12px;
  border-radius: var(--radius-md);
  display: inline-block;
  background: var(--bg-alt);
  color: var(--text-dim);
}
.probability-pill.pill-yes { background: var(--yes-bg); color: var(--yes-strong); }
.probability-pill.pill-no { background: var(--no-bg); color: var(--no-strong); }
.probability-pill.pill-neutral { background: var(--accent-bg); color: var(--accent); }

.market-card .meta { font-size: 12px; color: var(--text-dim); display: flex; gap: 10px; }

/* A labeled section within a catalog page ("Featured", "Markets", ...) -- shared by stock-exchange
   and pari-mutuel's own featured-strip-above-the-grid layout, not principle-specific. */
.panel-section { margin-bottom: var(--space-6); }
.section-heading { font-size: 15px; font-weight: 700; margin: 0 0 var(--space-3); color: var(--text); }

.badge {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.badge.open { background: var(--accent-bg); color: var(--accent); }
.badge.resolved { background: var(--bg-alt); color: var(--text-dim); }

/* ---- Avatar-style image slots -- flags (pari-mutuel outcomes) and company
   logos (stock tickers). Flags are real images (frontend/assets/flags/);
   logos are a not-yet-populated assets/logos/<TICKER>.svg convention. Both
   fall back to the same small colored initial badge via onerror if the
   underlying file is ever missing -- see frontend/js/branding.js. Nothing
   here assumes a real image file exists; everything looks finished either
   way. ------------------------------------------------------------------ */
/* The real flag files (frontend/assets/flags/) are square icon-style images (256x256, a few
   48x48), not wide banners -- a wide box with object-fit:cover was scaling to match width and
   cropping the top/bottom off every flag. Square box + matching aspect ratio means no cropping
   either way (cover and contain behave identically once the aspect ratio actually matches). */
.flag-img {
  width: 20px;
  height: 20px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 1px var(--border);
  flex: none;
  vertical-align: middle;
}

/* Real admin-supplied per-outcome images (frontend/js/branding.js's outcomeImageSlotHtml) --
   arbitrary aspect ratio/resolution unlike the flag set, so object-fit:cover + a fixed circular
   box is the only sizing that can't ever blow out a card's layout. Base size matches .flag-img;
   .pool-featured-card's own .outcome-avatar scope overrides to 28px for its larger leaderboard rows. */
.outcome-avatar-img {
  width: 20px;
  height: 20px;
  object-fit: cover;
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--border);
  flex: none;
  vertical-align: middle;
}

.avatar-badge {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  flex: none;
  background: var(--gradient-brand);
}

.logo-slot img {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  object-fit: contain;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  flex: none;
}

/* Admin-side live preview (pari-mutuel create-market form) -- see poolAdmin.js's
   updateOutcomeFlagPreview(). Same chip shape regardless of whether an outcome resolves to a real
   flag or the plain initial-badge fallback, so an admin can see both at a glance. */
.outcome-flag-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: -4px;
}
.outcome-flag-preview:empty { margin-top: 0; }
.outcome-flag-preview-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 6px;
  border-radius: var(--radius-pill);
  background: var(--bg-alt);
  font-size: 12px;
  color: var(--text-dim);
}

/* ---- Trading view -- Kalshi-style visible ladder, not an abstracted toggle */
.trading-layout {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--space-5);
}

.panel {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  box-shadow: var(--shadow-sm);
}

.market-title-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.market-title-row h1 { font-size: 21px; margin: 0; letter-spacing: -0.01em; }

/* Market-level cover image (Polymarket/Kalshi's own "image"/"icon" concept) -- optional, admin-set
   via imageUrl/logoUrl. Catalog cards get a full-width strip above the question; detail pages get
   a small square next to the h1, same slot pattern as .ticker-logo/.logo-slot. */
.market-card-cover {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 1px var(--border);
  background: var(--bg-alt);
  flex: none;
}
.market-heading { display: flex; align-items: center; gap: 10px; }
.market-cover-img {
  width: 32px;
  height: 32px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  flex: none;
}
.market-resolution-source {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  white-space: pre-wrap;
}

.range-tabs { display: flex; gap: 6px; margin-bottom: 10px; }
.range-tabs button {
  border: 1px solid var(--border);
  background: var(--panel-bg);
  border-radius: var(--radius-sm);
  padding: 4px 11px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.range-tabs button:hover { border-color: var(--border-strong); }
.range-tabs button.active { background: var(--accent); color: white; border-color: var(--accent); }

#chart-container { width: 100%; height: 320px; }

.ladder-header {
  display: flex;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 13px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
  color: var(--text-dim);
}

/* table-layout: fixed + explicit per-column widths, not auto-sizing: the ask/bid ladder is two
   separate <table> elements (see frontend/*/js/depth.js) stacked to look like one continuous
   book, so each side's columns need identical widths -- left to auto-sizing, whichever side's
   numbers happened to be wider on a given render (Size/Total, not just Price) shifted that whole
   table's column boundaries independently of the other, so Price never lined up between the two. */
table.ladder { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 13px; table-layout: fixed; }
table.ladder th:nth-child(1), table.ladder td:nth-child(1) { width: 36%; }
table.ladder th:nth-child(2), table.ladder td:nth-child(2) { width: 32%; }
table.ladder th:nth-child(3), table.ladder td:nth-child(3) { width: 32%; }
table.ladder th { text-align: right; color: var(--text-dim); font-weight: 500; padding: 3px 4px; }
table.ladder td { text-align: right; padding: 3px 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.ladder tr.ask td.price { color: var(--no-strong); font-weight: 600; }
table.ladder tr.bid td.price { color: var(--yes-strong); font-weight: 600; }
/* Depth bar: a background gradient sized by --depth-pct (set inline per row), not absolute
   positioning -- a <tr> is an unreliable containing block for position:absolute across browsers
   (table layout), which let an earlier version of this bar escape its row and cover the page. */
table.ladder tr.ask { background: linear-gradient(to left, var(--no-bg) var(--depth-pct, 0%), transparent var(--depth-pct, 0%)); }
table.ladder tr.bid { background: linear-gradient(to left, var(--yes-bg) var(--depth-pct, 0%), transparent var(--depth-pct, 0%)); }

.trade-row { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 12px; padding: 3px 0; }
.trade-row.buy { color: var(--yes-strong); }
.trade-row.sell { color: var(--no-strong); }

form.order-form { display: flex; flex-direction: column; gap: 10px; }
form.order-form .side-toggle { display: flex; gap: 8px; }
form.order-form .side-toggle button {
  flex: 1; padding: 10px; border-radius: var(--radius-md); border: 1px solid var(--border); background: var(--panel-bg);
  font-weight: 600; cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
form.order-form .side-toggle button:hover { border-color: var(--border-strong); }
form.order-form .side-toggle button.buy.active { background: var(--yes-bg); border-color: var(--yes); color: var(--yes-strong); }
form.order-form .side-toggle button.sell.active { background: var(--no-bg); border-color: var(--no); color: var(--no-strong); }

input, select, textarea {
  font-family: var(--mono);
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 14px;
  width: 100%;
  background: var(--panel-bg);
  color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
textarea { resize: vertical; font-family: var(--font-sans); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}

button.submit-btn {
  padding: 11px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--accent);
  color: white;
  font-weight: 600;
  cursor: pointer;
  font-size: 14px;
  box-shadow: var(--shadow-sm);
  transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
button.submit-btn:hover { background: var(--accent-hover); box-shadow: var(--shadow-md); }
button.submit-btn:active { transform: translateY(1px); }
button.submit-btn:disabled { background: var(--bg-alt); color: var(--text-faint); cursor: not-allowed; box-shadow: none; }

.balance-widget {
  font-family: var(--mono);
  font-size: 13px;
  display: flex;
  justify-content: space-between;
  padding: 8px 0 2px;
  color: var(--text-dim);
}
.balance-widget .balance-amount { color: var(--text); font-weight: 600; }
.balance-widget .balance-amount.insufficient { color: var(--no-strong); }

/* STEP-8: pari-mutuel outcome list -- a bar per outcome sized by its own implied percentage
   (poolCents/totalPoolCents), the pari-mutuel analog of the CLOB ladder's depth bars. */
.outcome-row { margin: 10px 0; }
.outcome-row-top { display: flex; align-items: center; justify-content: space-between; font-size: 13px; margin-bottom: 4px; gap: 8px; }
.outcome-row-top .outcome-name { display: flex; align-items: center; gap: 6px; font-weight: 500; }
.outcome-bar-track { height: 8px; border-radius: var(--radius-pill); background: var(--bg-alt); overflow: hidden; }
.outcome-bar-fill { height: 100%; background: var(--gradient-brand); border-radius: var(--radius-pill); transition: width 0.4s ease; }

.inline-result { font-size: 13px; padding: 9px 10px; border-radius: var(--radius-md); margin-top: 4px; }
.inline-result.success { background: var(--yes-bg); color: var(--yes-strong); }
.inline-result.error { background: var(--no-bg); color: var(--no-strong); }

table.orders-table { width: 100%; font-size: 13px; border-collapse: collapse; }
table.orders-table th, table.orders-table td { text-align: left; padding: 8px 6px; border-bottom: 1px solid var(--border); }
table.orders-table button.cancel-btn {
  border: 1px solid var(--no); color: var(--no-strong); background: none; border-radius: var(--radius-sm); padding: 3px 8px; cursor: pointer; font-size: 12px;
  transition: background 0.15s ease;
}
table.orders-table button.cancel-btn:hover { background: var(--no-bg); }

/* Portfolio P&L (STEP-6) */
.pnl-positive { color: var(--yes-strong); font-weight: 600; }
.pnl-negative { color: var(--no-strong); font-weight: 600; }

/* Account transactions grid (STEP-8) */
table.tx-table tr.tx-row { cursor: pointer; }
table.tx-table tr.tx-row:hover { background: var(--bg); }
table.tx-table .tx-chevron { color: var(--text-dim); width: 14px; }
table.tx-table tr.tx-detail td { background: var(--bg); padding: 10px 12px; }
.tx-detail-fields { display: flex; flex-wrap: wrap; gap: 6px 24px; }
.tx-detail-field { font-size: 12px; color: var(--text-dim); }
.tx-detail-field .label { color: var(--text-dim); margin-right: 4px; }

/* Admin */
.admin-tabs { display: flex; gap: 8px; margin-bottom: 16px; }
.admin-tabs button {
  padding: 8px 16px; border-radius: var(--radius-md); border: 1px solid var(--border); background: var(--panel-bg); cursor: pointer; font-weight: 600;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.admin-tabs button:hover { border-color: var(--border-strong); }
.admin-tabs button.active { background: var(--accent); color: white; border-color: var(--accent); }

.quote-panel { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.quote-panel .side-block { border: 1px solid var(--border); border-radius: var(--radius-md); padding: 14px; }
.quote-panel .side-block.bid { border-color: var(--yes); }
.quote-panel .side-block.ask { border-color: var(--no); }
.quote-panel .price-input-row { display: flex; align-items: center; gap: 6px; }
.quote-panel .price-input-row input { text-align: center; font-size: 22px; font-weight: 700; }
.quote-panel .nudge-btn {
  width: 36px; height: 36px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--panel-bg);
  font-size: 18px; cursor: pointer;
}

.house-position-widget {
  font-family: var(--mono);
  font-size: 13px;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px 16px;
  margin-bottom: 16px;
  display: flex;
  gap: 24px;
  box-shadow: var(--shadow-sm);
}
.house-position-widget .label { color: var(--text-dim); }

.hint { font-size: 12px; color: var(--text-dim); margin-top: 4px; }

/* Auth (STEP-6) */
.auth-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(11, 18, 32, 0.55);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.auth-modal {
  position: relative;
  background: var(--panel-bg);
  border-radius: var(--radius-lg);
  padding: 26px;
  width: 320px;
  max-width: calc(100vw - 32px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: var(--shadow-lg);
}
.auth-modal h2 { margin: 0 0 6px; font-size: 17px; }
.auth-modal label { font-size: 13px; color: var(--text-dim); display: flex; flex-direction: column; gap: 4px; }
.auth-modal-actions { display: flex; gap: 8px; margin-top: 6px; }
.auth-modal-actions .submit-btn { flex: 1; }
.auth-modal-actions .submit-btn.secondary { background: var(--panel-bg); color: var(--text); border: 1px solid var(--border); box-shadow: none; }
.auth-modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  border: none;
  background: none;
  font-size: 18px;
  line-height: 1;
  color: var(--text-dim);
  cursor: pointer;
}

/* Legal/disclaimer footer (frontend/js/footer.js) -- var(--bg-alt), not var(--panel-bg)/var(--bg),
   so it reads as visually distinct from both the page body and the card panels above it. */
footer.matchcore-footer {
  flex-shrink: 0;
  background: var(--bg-alt);
  border-top: 1px solid var(--border);
  margin-top: var(--space-6);
  padding: var(--space-5) var(--space-4);
}
footer.matchcore-footer .footer-inner {
  max-width: 1120px;
  margin: 0 auto;
}
footer.matchcore-footer .footer-copyright {
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 10px;
}
footer.matchcore-footer .footer-simulated-notice {
  font-size: 13px;
  font-weight: 700;
  color: var(--no-strong);
  margin-bottom: 6px;
}
footer.matchcore-footer p {
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-dim);
  margin: 0;
}

#matchcore-toast-container {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.matchcore-toast {
  min-width: 240px;
  max-width: 360px;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  font-size: 13px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translateX(16px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.matchcore-toast.visible { opacity: 1; transform: translateX(0); }
.matchcore-toast.error { background: var(--no-bg); color: var(--no-strong); border: 1px solid var(--no); }
.matchcore-toast.info { background: var(--panel-bg); color: var(--text); border: 1px solid var(--border); }

/* ---- Vision gallery (concept-design thumbnails + click-to-enlarge lightbox) -- shared, not
   scoped to one page's own <style> block, since frontend/js/marketHours.js's own closed-banner
   renders this same gallery on every page (root index.html and every principle's own subpage). */
.vision-section {
  max-width: 980px;
  margin: 0 auto;
  padding: 0 var(--space-4) var(--space-6);
  text-align: center;
}
.vision-section h2 { font-size: 20px; margin: 0 0 var(--space-2); }
.vision-section .vision-note { color: var(--text-dim); font-size: 14px; max-width: 560px; margin: 0 auto var(--space-5); }
.vision-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-4);
}
.vision-thumb {
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel-bg);
  overflow: hidden;
  cursor: zoom-in;
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.vision-thumb:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); border-color: var(--border-strong); }
.vision-thumb img { display: block; width: 100%; height: auto; }
.vision-lightbox {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(4, 8, 16, 0.82);
  z-index: 100;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
}
.vision-lightbox.open { display: flex; }
.vision-lightbox img {
  max-width: min(1100px, 100%);
  max-height: 88vh;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}
.vision-lightbox-close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.vision-lightbox-close:hover { background: rgba(255, 255, 255, 0.18); }
