/* ─── Reset / base ─────────────────────────────────────────────────────── */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
:root {
  --bg: #0e0f13;
  --bg-elev: #181a20;
  --bg-card: #1c1f27;
  --border: #262a34;
  --text: #e9ecf1;
  --text-dim: #8b929f;
  --accent: #4c8dff;
  --green: #2fd07a;
  --red: #ff5d5d;
  --amber: #f5b53d;
}
html, body {
  margin: 0; padding: 0;
  font-family: "Manrope", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  background: var(--bg); color: var(--text);
  height: 100%;
  overscroll-behavior: none;
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.01em;
}
/* Monospace tabular figures for that trading-terminal feel + perfect alignment. */
.card-value, .holding-row .val, .holding-row .pct, .holding-row .qty,
.proposal-grid .val, .card-row .val, .mono {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.hidden { display: none !important; }
.muted { color: var(--text-dim); font-size: 13px; }
code { background: #2a2e38; padding: 2px 5px; border-radius: 4px; font-size: 12px; }
.error-msg { color: var(--red); margin-top: 10px; font-size: 13px; }

button {
  font-family: inherit; font-size: 15px;
  border: none; cursor: pointer; outline: none;
  border-radius: 10px;
  transition: transform 0.08s ease, opacity 0.12s ease, background 0.15s ease;
}
button:active { transform: scale(0.97); opacity: 0.85; }

input {
  width: 100%; font-size: 16px;   /* 16px prevents iOS zoom-on-focus */
  padding: 12px; margin-top: 6px;
  background: var(--bg-elev); color: var(--text); border: 1px solid var(--border);
  border-radius: 10px; outline: none;
  font-family: inherit;
  transition: border-color 0.15s ease;
  -webkit-appearance: none; appearance: none;   /* stop iOS date/number intrinsic sizing */
  min-width: 0; max-width: 100%; box-sizing: border-box;
}
/* iOS date inputs: force them to fill the field and align left like the rest. */
input[type="date"] {
  -webkit-appearance: none; appearance: none;
  min-height: 46px; line-height: 1.2;
  display: block; text-align: left;
}
input[type="date"]::-webkit-date-and-time-value { text-align: left; }
input:focus { border-color: var(--accent); }

select {
  width: 100%; font-size: 16px;
  padding: 12px; margin-top: 6px;
  background: var(--bg-elev); color: var(--text); border: 1px solid var(--border);
  border-radius: 10px; outline: none; font-family: inherit;
}
select:focus { border-color: var(--accent); }

.log-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.log-grid input, .log-grid select { margin-top: 0; }
.log-grid #log-symbol, .log-grid #log-notes { grid-column: 1 / -1; }


/* ─── Layout ───────────────────────────────────────────────────────────── */
.screen { display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: env(safe-area-inset-top, 12px) 16px 12px 16px;
  padding-top: max(env(safe-area-inset-top, 12px), 12px);
  background: rgba(14,15,19,0.85); backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 10;
}
.topbar h2 { margin: 0; font-size: 19px; font-weight: 700; letter-spacing: -0.3px; }

.iconbtn {
  background: transparent; color: var(--text-dim);
  font-size: 22px; width: 36px; height: 36px;
  border-radius: 18px;
}
.iconbtn:hover { background: var(--bg-elev); color: #fff; }

#content {
  flex: 1; overflow-y: auto;
  padding: 14px 14px;
  padding-bottom: 96px;  /* clear tab bar */
  -webkit-overflow-scrolling: touch;
}

.tabbar {
  position: fixed; bottom: 0; left: 0; right: 0;
  display: flex; justify-content: flex-start;
  background: rgba(20,22,28,0.92); backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--border);
  /* Left/right insets matter in LANDSCAPE on a notched phone: iPhone 16 Pro
     turned sideways puts the Dynamic Island over one end of this bar, and
     without these the first or last tab sits underneath it. */
  padding: 6px env(safe-area-inset-right, 0px)
           calc(env(safe-area-inset-bottom, 4px) + 6px)
           env(safe-area-inset-left, 0px);
  z-index: 10;
  /* TEN tabs will not fit a phone at a legible size — 402pt (iPhone 16 Pro)
     divided ten ways is 40pt, under Apple's 44pt minimum touch target.
     Scrolling horizontally keeps every label readable and every target
     hittable instead of squeezing them all in. Snap points stop it settling
     half-way between two tabs. */
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.tabbar::-webkit-scrollbar { display: none; }
.tab {
  /* A fixed minimum keeps the touch target above the ~44px Apple guideline
     however many tabs there are. flex:1 alone would shrink them below it. */
  flex: 0 0 auto;
  min-width: 68px;
  scroll-snap-align: center;
  background: transparent; color: var(--text-dim);
  padding: 6px 0; font-size: 11px; text-align: center;
}
.tab:nth-child(n) > * { line-height: 1.2; }
.tab.active { color: var(--accent); }
.tab span { font-size: 11px; }

/* ─── Setup screen ─────────────────────────────────────────────────────── */
#setup-screen { padding: env(safe-area-inset-top, 20px) 20px 20px 20px; }
.setup-card {
  background: var(--bg-card); border-radius: 16px; padding: 24px;
  margin-top: 40px; border: 1px solid var(--border);
  box-shadow: 0 12px 40px rgba(0,0,0,0.4);
}
.setup-card h1 { margin: 0 0 6px 0; font-size: 24px; letter-spacing: -0.5px; }
.setup-card label {
  display: block; font-size: 13px; color: var(--text-dim);
  margin-top: 14px;
}
.setup-card small { display: block; margin-top: 4px; line-height: 1.4; }

.primary {
  width: 100%; background: var(--accent); color: white;
  padding: 15px; border-radius: 12px; font-weight: 600;
}
.primary:hover { background: #3b7be6; }
.primary:disabled { background: #444a57; cursor: not-allowed; }

/* ─── Cards (general) ──────────────────────────────────────────────────── */
.card {
  background: var(--bg-card); border-radius: 16px;
  padding: 16px; margin-bottom: 12px;
  border: 1px solid var(--border);
  box-shadow: 0 2px 10px rgba(0,0,0,0.18);
}
.card-title {
  font-size: 12px; color: var(--text-dim); margin: 0 0 6px 0;
  text-transform: uppercase; letter-spacing: 0.6px; font-weight: 600;
}
.card-value { font-size: 28px; font-weight: 800; margin: 0; letter-spacing: -0.5px; }

.card-row {
  display: flex; justify-content: space-between; align-items: center;
  margin: 8px 0;
}
.card-row .lbl { color: var(--text-dim); font-size: 13px; }
.card-row .val { font-weight: 600; }

.green { color: var(--green); }
.red   { color: var(--red); }
.amber { color: var(--amber); }
.blue  { color: var(--accent); }

/* ─── Portfolio summary ────────────────────────────────────────────────── */
.summary-card {
  position: relative;
  background:
    radial-gradient(120% 120% at 0% 0%, rgba(76,141,255,0.18), transparent 55%),
    linear-gradient(160deg, #20242e 0%, #14161c 100%);
  padding: 20px; border: 1px solid #2d3340;
  border-radius: 16px;
  box-shadow: inset 0 3px 0 0 var(--accent);
  min-height: 0; height: auto;
}
.summary-card .card-value { font-size: 34px; }

/* ─── Holding rows ─────────────────────────────────────────────────────── */
.holding-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 13px 0;
  border-bottom: 1px solid var(--border);
}
.holding-row:last-child { border-bottom: none; }
.holding-row .sym { font-weight: 700; font-size: 16px; letter-spacing: -0.2px; }
.holding-row .qty { color: var(--text-dim); font-size: 12px; margin-top: 2px; }
.holding-row .val { text-align: right; font-weight: 700; }
.holding-row .pct { font-size: 12px; text-align: right; margin-top: 2px; }

/* ─── Proposal cards ───────────────────────────────────────────────────── */
.proposal-card {
  background: #222; border: 2px solid #3498db;
  border-radius: 12px; padding: 14px; margin-bottom: 10px;
}
.proposal-card.buy { border-color: #2ecc71; }
.proposal-card.sell { border-color: #e74c3c; }
.proposal-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 8px;
}
.proposal-head .sym {
  font-size: 18px; font-weight: 700;
}
.proposal-head .side-pill {
  font-size: 11px; padding: 3px 10px; border-radius: 10px;
  font-weight: 700; letter-spacing: 0.5px;
}
.side-pill.buy  { background: #2ecc71; color: #0a3320; }
.side-pill.sell { background: #e74c3c; color: #3a0e0e; }

.proposal-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px;
  margin: 10px 0;
}
.proposal-grid .lbl { color: #888; font-size: 11px; }
.proposal-grid .val { font-size: 13px; font-weight: 600; }

.proposal-rationale {
  background: #1a1a1a; border-radius: 8px;
  padding: 10px; margin: 8px 0;
  font-size: 12px; line-height: 1.4; color: #ccc;
  white-space: pre-wrap;
}

.proposal-actions {
  display: flex; gap: 8px; margin-top: 12px;
}
.proposal-actions button {
  flex: 1; padding: 12px; border-radius: 8px;
  font-weight: 700; font-size: 14px;
  color: white;
}
.btn-approve { background: #27ae60; }
.btn-approve:hover { background: #229954; }
.btn-reject  { background: #c0392b; }
.btn-reject:hover  { background: #a02818; }

/* ─── Scan screen ──────────────────────────────────────────────────────── */
.scan-input-row { display: flex; gap: 8px; }
.scan-input-row input { flex: 1; }
.scan-input-row button {
  background: #3498db; color: white;
  padding: 0 18px; border-radius: 8px; font-weight: 600;
}

.vote-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 0; border-bottom: 1px solid #2a2a2a;
}
.vote-row:last-child { border-bottom: none; }
.vote-row .src { font-size: 13px; }
.vote-row .dir {
  font-size: 11px; padding: 2px 8px; border-radius: 8px;
  font-weight: 700;
}
.vote-row .dir.BUY { background: #2ecc7133; color: #2ecc71; }
.vote-row .dir.SELL { background: #e74c3c33; color: #e74c3c; }
.vote-row .dir.NEUTRAL { background: #88888833; color: #aaa; }
.vote-row .rationale { font-size: 11px; color: #888; margin-top: 3px; }

/* ─── Empty state ──────────────────────────────────────────────────────── */
.empty-state {
  text-align: center; padding: 60px 20px;
  color: #666;
}
.empty-state .icon { font-size: 48px; margin-bottom: 10px; }

/* ─── Toast ────────────────────────────────────────────────────────────── */
.toast {
  position: fixed; bottom: 100px; left: 50%; transform: translateX(-50%);
  background: #333; color: white;
  padding: 12px 20px; border-radius: 24px;
  font-size: 13px; max-width: 90%;
  box-shadow: 0 4px 12px rgba(0,0,0,0.4);
  z-index: 100;
}
.toast.success { background: #27ae60; }
.toast.error   { background: #c0392b; }

/* ─── Loading spinner ──────────────────────────────────────────────────── */
.spinner {
  border: 3px solid #333; border-top-color: #3498db;
  border-radius: 50%; width: 28px; height: 28px;
  animation: spin 0.8s linear infinite;
  margin: 20px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ─── Tappable holding rows ──────────────────────────────────────────────── */
.holding-row.tappable { cursor: pointer; transition: background 0.12s; }
.holding-row.tappable:active { background: #2a2a2a; }

/* ─── Detail sheet (bottom modal) ────────────────────────────────────────── */
.detail-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,0.6);
  display: none; align-items: flex-end; z-index: 1000;
}
.detail-overlay.open { display: flex; }
.detail-sheet {
  background: var(--bg-elev); width: 100%; max-height: 85vh; overflow-y: auto;
  overflow-x: hidden; box-sizing: border-box;
  border-radius: 20px 20px 0 0; padding: 20px;
  padding-bottom: calc(20px + env(safe-area-inset-bottom));
  animation: sheetUp 0.22s ease-out;
}
.detail-sheet * { max-width: 100%; box-sizing: border-box; }
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.detail-head { display: flex; justify-content: space-between; align-items: flex-start; }
.detail-close {
  background: #2a2a2a; border: none; color: #ccc; width: 34px; height: 34px;
  border-radius: 50%; font-size: 16px; cursor: pointer; flex: none;
}

/* ─── Page-load motion: staggered card reveal ────────────────────────────── */
@keyframes cardIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
#content .card {
  animation: cardIn 0.32s ease-out both;
}
#content .card:nth-child(1) { animation-delay: 0.00s; }
#content .card:nth-child(2) { animation-delay: 0.05s; }
#content .card:nth-child(3) { animation-delay: 0.10s; }
#content .card:nth-child(4) { animation-delay: 0.15s; }
#content .card:nth-child(n+5) { animation-delay: 0.18s; }

/* Pill refinements */
.side-pill { text-transform: uppercase; }

/* ─── Skeleton loaders ───────────────────────────────────────────────────── */
.skel {
  background: linear-gradient(100deg, #1c1f27 30%, #242833 50%, #1c1f27 70%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite linear;
  border-radius: 16px; margin-bottom: 12px;
}
.skel-card { width: 100%; }
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ─── Empty state polish ─────────────────────────────────────────────────── */
.empty-state {
  text-align: center; color: var(--text-dim);
  padding: 60px 20px; font-size: 15px;
}
.empty-state .icon { font-size: 44px; margin-bottom: 12px; opacity: 0.7; }

/* ─── Number emphasis ────────────────────────────────────────────────────── */
.summary-card .card-value { letter-spacing: -1px; }

/* Subtle press feedback on tappable holding rows */
.holding-row.tappable { border-radius: 10px; padding-left: 8px; padding-right: 8px; margin: 0 -8px; }
.holding-row.tappable:active { background: rgba(255,255,255,0.04); }

/* ─── Segmented control ──────────────────────────────────────────────────── */
.segmented {
  display: flex; gap: 4px; background: var(--bg-elev);
  border: 1px solid var(--border); border-radius: 12px; padding: 4px;
  margin-bottom: 12px;
}
.segmented button {
  flex: 1; background: transparent; color: var(--text-dim);
  padding: 9px 0; font-size: 13px; font-weight: 600; border-radius: 9px;
}
.segmented button.on { background: var(--accent); color: #fff; }

/* ─── Form fields (edit/amend modals) ────────────────────────────────────── */
.form-field { margin-top: 14px; }
.form-field label {
  display: block; font-size: 12px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600;
  margin-bottom: 2px;
}
.form-field .log-grid & { margin-top: 0; }

/* ─────────────────────────────────────────────────────────────────────────
   LANDSCAPE / horizontal layout — a genuinely different configuration:
   the bottom tab bar becomes a LEFT SIDEBAR, the top bar shrinks, and
   content flows into multiple columns. Portrait keeps the phone layout
   (bottom tabs, single column). No HTML change — pure CSS reflow.
   ───────────────────────────────────────────────────────────────────────── */
/* WIDTH ALONE WAS THE WRONG TEST.
   iPhone 16 Pro in landscape is 874 x 402pt. 874 >= 700, so it matched this
   block and got the tablet sidebar: a 210pt column eating a quarter of the
   width, and ten stacked tabs inside a viewport only 402pt tall. The base
   .tabbar sets overflow-y: hidden, so whatever did not fit was not merely
   cramped, it was unreachable — Research and Settings could not be tapped.

   min-height gates on the SHORT side, which is what actually decides whether
   a sidebar is sensible. iPad Pro 11" landscape (1194 x 834) still matches;
   iPhone 16 Pro (402) and 16 Pro Max (440) landscape no longer do and keep
   the phone layout, which already handles many tabs by scrolling. */
@media (orientation: landscape) and (min-width: 700px) and (min-height: 500px) {
  /* App shell becomes a row: [sidebar][main area]. */
  #app-screen {
    display: grid;
    grid-template-columns: 210px 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas: "side top" "side content";
    height: 100vh;
  }
  .topbar { grid-area: top; padding: 14px 24px; }
  .topbar h2 { font-size: 22px; }

  /* Tab bar -> vertical sidebar on the left. */
  .tabbar {
    position: static; grid-area: side;
    flex-direction: column; justify-content: flex-start; align-items: stretch;
    gap: 4px;
    padding: 18px 12px 18px max(12px, env(safe-area-inset-left, 0px));
    border-top: none; border-right: 1px solid var(--border);
    background: var(--bg-elev);
    /* The base rule is overflow-x: auto / overflow-y: hidden, correct for a
       horizontal bar and silently destructive for a vertical one: any tab
       past the fold becomes unreachable rather than scrollable. The height
       gate above should prevent that, but a tab added later, a larger Dynamic
       Type setting, or an iPad in Split View can all overflow a sidebar that
       fits today. Scrolling the axis it now stacks on costs nothing and
       removes the whole failure mode. */
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .tabbar .tab {
    display: flex; align-items: center; gap: 12px;
    text-align: left; font-size: 14px; padding: 13px 14px;
    border-radius: 10px;
  }
  .tabbar .tab br { display: none; }
  .tabbar .tab span { font-size: 14px; }
  .tabbar .tab.active { background: rgba(76,141,255,0.14); }

  /* Content uses the SAME block layout as portrait (which works perfectly):
     every card stacks top-to-bottom and scrolls vertically only. NO grid on
     #content — the grid was collapsing the toggle bar. The only landscape
     extras are the sidebar (above) and a 2-column holdings list (below). */
  #content {
    grid-area: content;
    overflow-y: auto; overflow-x: hidden;
    display: block;
    padding: 18px 24px 24px;
    max-width: 1100px;
  }
  .summary-card .card-value { font-size: 42px; }

  /* Use the width: holdings flow into 2 columns inside their card. This is a
     contained grid (only inside .holdings-list), so it can't affect the
     top-level cards or the toggle bar. */
  .holdings-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 28px;
  }
  .holdings-list .holding-row { min-width: 0; }

  /* Detail / edit sheets become centered modals. */
  .detail-overlay { align-items: center; justify-content: center; }
  .detail-sheet { width: 480px; max-width: 92vw; border-radius: 20px; max-height: 88vh; }
  @keyframes sheetUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
}

/* Wide tablets: holdings into 3 columns (still a contained grid).
   iPad Pro 11" landscape is 1194 x 834, so it lands here. */
@media (orientation: landscape) and (min-width: 1100px) and (min-height: 500px) {
  #app-screen { grid-template-columns: 240px 1fr; }
  #content { max-width: 1300px; }
  .holdings-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ─────────────────────────────────────────────────────────────────────────
   FIVE TABS ON A PHONE — the FUTU/moomoo convention.

   Ten tabs in a scrolling bar kept every target legible but put most
   destinations behind a sideways swipe nobody performs. Four primary tabs
   plus More is five slots: 402pt / 5 = 80pt each on an iPhone 16 Pro, well
   over the 44pt minimum, and nothing is hidden behind a gesture.

   COLLAPSE ONLY WHERE THE SCREEN IS ACTUALLY NARROW. iPad Pro 11" portrait is
   834pt: ten tabs at the 78pt floor is 780pt and fits with room over, so the
   tablet keeps every tab visible and never shows More. Comma = OR: narrow
   portrait, or a short landscape (a phone on its side).
   ───────────────────────────────────────────────────────────────────────── */
.tabbtn-more { display: none; }          /* created by tabs_more_28.js */

@media (max-width: 767px),
       (orientation: landscape) and (max-height: 499px) {
  .tabbar .tab[data-group="more"] { display: none; }
  .tabbtn-more { display: block; }
  /* Five equal slots instead of the horizontal scroll. */
  .tabbar { overflow-x: hidden; justify-content: space-around; }
  .tabbar .tab { flex: 1 1 0; min-width: 0; }
}

/* The More sheet. Rises from the bottom, where the thumb already is. */
.more-overlay {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(0,0,0,0.5);
  display: flex; align-items: flex-end; justify-content: center;
}
.more-overlay.hidden { display: none; }
.more-sheet {
  width: 100%; max-width: 520px;
  background: var(--bg-card);
  border-top: 1px solid var(--border);
  border-radius: 18px 18px 0 0;
  padding: 10px 10px calc(env(safe-area-inset-bottom, 8px) + 14px);
  animation: moreUp 0.22s ease-out both;
  max-height: 70vh; overflow-y: auto;
}
@keyframes moreUp { from { transform: translateY(18px); opacity: 0; }
                    to   { transform: translateY(0);    opacity: 1; } }
.more-title {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--text-dim); padding: 8px 12px 10px;
}
.more-item {
  display: flex; align-items: center; gap: 14px;
  width: 100%; padding: 15px 12px;      /* >= 44pt tall */
  background: transparent; color: var(--text);
  font-size: 16px; text-align: left; border-radius: 12px;
}
.more-item.active { background: rgba(76,141,255,0.14); color: var(--accent); }
.more-icon { font-size: 19px; width: 24px; text-align: center; }

/* On a tablet the sheet is never opened, but if the window is resized down
   mid-session it should centre rather than cling to the bottom edge. */
@media (min-width: 768px) and (orientation: portrait) {
  .more-overlay { align-items: center; }
  .more-sheet { border-radius: 18px; max-width: 460px; }
}

/* Portrait = the phone layout (single column, bottom tabs). */
@media (orientation: portrait) {
  #content { display: block; }
  .holdings-list { display: block; }
}

/* ─────────────────────────────────────────────────────────────────────────
   TABLET PORTRAIT — iPad Pro 11" is 834 x 1194pt this way up.

   Until now portrait meant "phone", whatever the width, so the iPad held
   upright got a layout designed for 402pt stretched across 834: one column of
   holdings using half the screen, and card text running the full width, which
   is roughly 100 characters per line — about twice a comfortable measure.

   Deliberately NOT the landscape treatment. A sidebar is wrong here: at
   834pt wide, taking 210 for navigation leaves the content narrower than it
   would be with bottom tabs, and the bottom of a held tablet is where the
   thumbs already are. So: keep the tab bar, use the width for content.

   MUST come after the generic portrait block above, which sets
   .holdings-list to display: block — equal specificity, so source order is
   what decides.
   ───────────────────────────────────────────────────────────────────────── */
@media (orientation: portrait) and (min-width: 768px) {
  /* Cap the measure and centre it rather than filling 834pt with text. */
  #content {
    max-width: 780px;
    margin-left: auto; margin-right: auto;
    padding: 22px 24px 110px;
  }

  /* Two columns of holdings: ~350pt each, wider than the whole iPhone. */
  .holdings-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 24px;
  }
  .holdings-list .holding-row { min-width: 0; }

  /* Ten tabs at the 68pt floor is 680pt, which fits 834 with room over.
     Centre them so the bar reads as designed for this width rather than as
     a phone bar with empty space on the right. */
  .tabbar { justify-content: center; }
  .tabbar .tab { min-width: 78px; }

  .topbar { padding-left: 24px; padding-right: 24px; }
  .topbar h2 { font-size: 22px; }
  .summary-card .card-value { font-size: 38px; }

  /* Sheets as centred modals, same as landscape — a full-width sheet on a
     tablet is a lot of travel for a small form. */
  .detail-overlay { align-items: center; justify-content: center; }
  .detail-sheet { width: 520px; max-width: 92vw; border-radius: 20px;
                  max-height: 86vh; }
}
