/* Holdings tab (views/holdings.js) — docs/HOLDINGS_SPEC.md §6, §8-§12,
 * MOBILE_PLAN.md §3.3.
 *
 * Everything the shared sheets already paint stays there: .panel,
 * .panel-title, .btn, .badge, .pill, .empty-note, .form-error, .num, .muted,
 * .small, .pos/.neg, table.data (through DataTable). This file only adds the
 * tab's own anatomy: the header meta line, the StatCard row, the driver
 * columns, the sector bar list, the search/sort toolbar and the two-line
 * list-mode body. Colour, type, spacing, radius and motion come only from
 * tokens.css custom properties — no colour literal lives here (transparent,
 * currentColor and inherit are allowed).
 *
 * Responsive (§3.3): the DataTable owns the mode switch — one DOM at a time,
 * `table.data` at 768 and wider and `ul.dt-list` with the two-line rows below
 * it. The sector allocation stays its own compact table (decision A). Search
 * and sort stay. Nothing here hides a mode; the phone block only tightens
 * density and shows the day % the drivers carry.
 */

.hld {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}

.hld-state:empty,
.hld-stale:empty {
  display: none;
}

/* ---- the Watchlist detail's tab row and panes (HOLDINGS_SPEC §5) ----------
 * These rules style the .wl2-* nodes views/watchlist.js builds for the
 * Overview | Holdings tab row and the holdings host. They live HERE, not in
 * watchlist.css, because the Holdings tab owns them (views/watchlist.css is
 * not in this task's owned-file list). holdings.css is linked statically
 * from index.html, so the tab row is styled on Overview-only loads too. */

.wl2-detail-tabs {
  display: flex;
}

.wl2-overview {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}

.wl2-overview[hidden] {
  display: none;
}

.wl2-holdings-host[hidden] {
  display: none;
}

/* ---- header (§6) ---------------------------------------------------------- */

.hld-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.hld-head-line {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.hld-symbol {
  font-size: var(--fs-section);
  font-weight: var(--fw-semibold);
  color: var(--ink);
  letter-spacing: 0.01em;
}

.hld-fund-name {
  color: var(--muted);
  font-size: var(--fs-small);
}

.hld-fund-name[hidden] {
  display: none;
}

.hld-flag-note {
  display: inline-flex;
  align-items: center;
}

/* The head-line badge slot (cached / parse-quality) is a stable container
   renderHeader fills in place — the badges keep the head line's gap inside
   it, and an empty slot takes no space (and no phantom flex gap). */
.hld-head-badges {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-3);
}

.hld-head-badges:empty {
  display: none;
}

/* T127: the fund's own chart trigger next to the symbol in the head line —
   the shared chartButton() (chart-panel.css paints the icon, the hover, the
   focus ring and the 44 px touch target). An empty slot (a fund symbol no
   chart can be drawn for) takes no space. */
.hld-fund-chart {
  display: inline-flex;
  align-items: center;
  flex: none;
}

.hld-fund-chart:empty {
  display: none;
}

.hld-head-meta {
  display: flex;
  align-items: baseline;
  gap: var(--space-1);
  flex-wrap: wrap;
}

/* The meta line's node is stable (filled in place), so the loading / error
   state hides it with `hidden` — the display:flex above would otherwise
   override the UA's [hidden] rule. */
.hld-head-meta[hidden] {
  display: none;
}

/* The source attribution (§18): visible but unobtrusive — same muted small
   line, the download URL only in the title. */
.hld-source,
.hld-prices,
.hld-fetched {
  white-space: nowrap;
}

/* ---- summary StatCards (§6) ----------------------------------------------- */

.hld-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-3);
}

/* Scope to the Holdings view so the shared `.card` stays untouched.
   The card needs position:relative so the absolutely-positioned ⓘ
   explainer sits inside the card's bounds; the rule is scoped tightly
   to the Holdings stat-card wrap so it cannot leak into Dashboard,
   Watchlist, or Compare. */
.hld-stats .card.stat-card {
  position: relative;
}

/* ⓘ placed inside a stat card — appended directly to the card so the
   card itself stays the grid child (no wrap, no size change). */
.hld-info-card {
  position: absolute;
  top: var(--space-1);
  right: var(--space-1);
  z-index: 1;
}

/* ⓘ placed inline at the end of the header meta line. */
.hld-info-meta {
  margin-left: var(--space-1);
  flex: none;
}

/* ⓘ placed inline next to a section heading (Driving / Positive / Negative). */
.hld-info-heading {
  margin-left: var(--space-1);
  flex: none;
}

/* Headings with an inline ⓘ keep their baseline alignment with the title.
   Scoped to .hld so the shared `.panel-title` is unchanged elsewhere.
   The drivers titles use a block-level flex container (not inline-flex)
   so their vertical margins collapse with the block title above — at
   1440 the Driving panel matches origin/main's 201 px instead of
   growing 2 px. */
.hld .panel-title,
.hld-driver-title {
  display: flex;
  align-items: baseline;
  gap: var(--space-1);
}

.hld-title-text {
  display: inline;
}

/* The explainer body inside the Popover. Plain text plus, for the
   concentration cards, the listed top holdings. */
.hld-explainer {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-width: 100%;
}

.hld-explainer-text {
  margin: 0;
}

.hld-top-row {
  display: grid;
  grid-template-columns: minmax(50px, auto) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--fs-small);
  padding: 2px 0;
}

.hld-top-tick {
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

.hld-top-name {
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hld-top-weight {
  color: var(--muted);
}

/* ---- driving the ETF today (§10) ------------------------------------------ */

.hld-drivers {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.hld-driver-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-4);
}

.hld-driver-title {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
}

.hld-driver-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.hld-driver {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--panel-border);
  font-size: var(--fs-small);
}

.hld-driver:last-child {
  border-bottom: 0;
}

.hld-driver.pos .hld-driver-contrib { color: var(--pos); }
.hld-driver.neg .hld-driver-contrib { color: var(--neg); }

.hld-driver-rank {
  flex: none;
  min-width: 1.25em;
}

.hld-driver-sym {
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

.hld-driver-contrib {
  margin-left: auto;
  font-weight: var(--fw-medium);
}

/* The day % the phone rows carry (§3.3 "day % with sign") — hidden at
   desktop so the 1024/1440 snapshot does not grow a node. */
.hld-driver-day {
  display: none;
  color: var(--ink-2);
  font-size: var(--fs-label);
  min-width: 4.5em;
  text-align: right;
}

.hld-driver-empty {
  border-bottom: 0;
}

/* The approximation formula (and, when a search is active, the note that
   the lists reflect it) — one muted line under the two lists. */
.hld-driver-note {
  margin: 0;
}

.hld-driver-note:empty {
  display: none;
}

/* ---- sector allocation (§11) ---------------------------------------------- */

.hld-sectors {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.hld-sectors[hidden] {
  display: none;
}

.hld-sector-rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.hld-sector {
  display: grid;
  grid-template-columns: minmax(120px, 220px) minmax(60px, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--fs-small);
}

.hld-sector-label {
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hld-sector-bar {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  overflow: hidden;
}

.hld-sector-fill {
  display: block;
  /* §3.3: the bar width is a --w custom property written per row; the
     colour stays the accent token. */
  width: var(--w, 0%);
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.hld-sector-weight {
  color: var(--ink-2);
  font-size: var(--fs-label);
}

/* ---- table toolbar (search + §9 sort) -------------------------------------- */

.hld-table {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.hld-table[hidden] {
  display: none;
}

.hld-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-2) var(--space-4);
}

.hld-tool {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.hld-tool-label {
  display: block;
}

.hld-search,
.hld-sort {
  appearance: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-small);
  padding: var(--space-1) var(--space-2);
  height: 30px;
}

.hld-search {
  width: 230px;
  max-width: 100%;
}

.hld-search:focus-visible,
.hld-sort:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

/* ---- table cells ------------------------------------------------------------ */

.hld-holding {
  display: inline-flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.hld-tick {
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

/* T120: the ticker is the chart-panel trigger — a real button that keeps the
   plain ticker look and adds only the hover cue and the focus ring.
   The face is .num's IBM Plex Mono: a <button> does not inherit the font the
   way a <span> does, so it has to be spelled out — `font-family: inherit`
   here outranks styles.css `.num` and drops the mono face. */
button.hld-tick {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: inherit;
  line-height: inherit;
  font-weight: var(--fw-semibold);
  text-align: inherit;
}

button.hld-tick:hover {
  color: var(--accent);
}

button.hld-tick:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.hld-name {
  overflow-wrap: anywhere;
}

/* T127: the ticker text and the shared chartButton() icon on one line (the
   same pairing Dashboard's .sym-cell-row uses). The icon's >=44 px touch
   target is painted by chart-panel.css's .chart-btn::after, so this row's
   height is unchanged on a phone and the table never scrolls sideways. */
.hld-tick-row {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex: none;
  min-width: 0;
}

.hld-info {
  /* Real <button> (Owner request 2026-09-24): the trigger is a button
     so Enter / Space activate it natively, but its visual stays the
     small ⓘ. Strip the default button chrome. */
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  margin: 0;
  font: inherit;
  cursor: help;
  color: var(--muted);
  font-size: var(--fs-label);
  border: 1px solid var(--axis);
  border-radius: var(--radius-pill);
  line-height: 1;
  padding: 1px 5px;
}

.hld-info:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

/* The DataTable's own ⓘ (`button.dt-info` — the header's, and the list-mode
   sort-bar / expand-dl ones) wears the SAME pill as the `.hld-info` triggers
   above: one Holdings view, one ⓘ treatment. The second selector reaches
   data-table.css's header min-box rule, which the pill's own box replaces
   (the touch zone is re-grown to 44 px by the ::after pattern below, exactly
   as `.hld-info` does). */
.hld-table button.dt-info,
.hld-table table.data th.dt-th-has-info .dt-th-inner button.dt-info {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  margin: 0;
  min-width: 0;
  min-height: 0;
  font: inherit;
  cursor: help;
  color: var(--muted);
  font-size: var(--fs-label);
  border: 1px solid var(--axis);
  border-radius: var(--radius-pill);
  line-height: 1;
  padding: 1px 5px;
}

.hld-table button.dt-info:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

/* Pattern 1 (§2.9): the ⓘ's visual stays ~24 px; on touch its hit area
   grows to 44 × 44 in every direction. z-index keeps the extension on
   top of the neighbouring ▾ toggle so the 44 px probe sees the ⓘ, not
   the toggle. Every ⓘ gets the same 44 px tap zone — the inline
   triggers use ::after on a position:relative trigger, the card-placed
   triggers use ::after on their own position:absolute box (which IS
   the positioning context for the ::after). */
@media (pointer: coarse), (max-width: 767.98px) {
  /* T120: the ticker button gets the same treatment as the ⓘ — the visual
     stays the row's own text (18 x 20) and the 44 x 44 target is painted by
     a transparent ::after, so the row height and the table's density are
     untouched. */
  button.hld-tick {
    position: relative;
    z-index: 1;
  }

  button.hld-tick::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, var(--hit-min));
    height: max(100%, var(--hit-min));
    pointer-events: auto;
  }

  .hld-info:not(.hld-info-card) {
    position: relative;
    z-index: 1;
  }

  .hld-info::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, var(--hit-min));
    height: max(100%, var(--hit-min));
    pointer-events: auto;
  }

  /* The card-placed triggers must keep their absolute positioning on
     touch (the card is the positioning context). The rule above keeps
     them at position:relative only because it was scoped with :not —
     re-assert the absolute explicitly so the cascade does not flip them
     into the flex flow on a phone. */
  .hld-info.hld-info-card {
    position: absolute;
  }

  /* Same 44 px extension for the DataTable's pill-wearing ⓘ (see the
     `.hld-table button.dt-info` rule above: the pill box is small, so the
     touch zone is painted by an overlay exactly as `.hld-info` does). */
  .hld-table button.dt-info {
    position: relative;
    z-index: 1;
  }

  .hld-table button.dt-info::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, var(--hit-min));
    height: max(100%, var(--hit-min));
    pointer-events: auto;
  }
}

/* ---- list-mode body (§3.3): the two-line row the DataTable renders ---------- */

/* Sits inside span.dt-item-body / div.dt-item-main; li.dt-item owns the
   row's padding and separator, so this only stacks the two lines. */
.hld-mrow {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.hld-mrow-top {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}

.hld-mrow-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hld-mrow-weight {
  flex: none;
  color: var(--ink-2);
}

.hld-mrow-quote {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
  min-width: 0;
}

.hld-mrow-price {
  color: var(--ink-2);
}

.hld-mrow-contrib {
  margin-left: auto;
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  color: var(--ink-2);
}

.hld-mrow-contrib .num.pos { color: var(--pos); }
.hld-mrow-contrib .num.neg { color: var(--neg); }

@media (max-width: 767.98px) {
  /* StatCards stay two columns at every phone width (§2.11): 136 px is the
     widest min that still gives 2 columns inside 320's 304 px content. */
  .hld-stats {
    grid-template-columns: repeat(auto-fit, minmax(min(136px, 100%), 1fr));
  }

  /* The drivers show the day % beside the contribution (§3.3). */
  .hld-driver-day {
    display: inline;
  }

  /* The toolbar stacks: search fills the row, sort follows. F1's
     `input[type="search"]` rule already raises the text to 16 px. */
  .hld-toolbar {
    flex-direction: column;
    align-items: stretch;
  }

  .hld-search {
    width: 100%;
  }

  .hld-sector {
    grid-template-columns: minmax(90px, 1fr) minmax(48px, 2fr) auto;
    gap: var(--space-2);
  }
}
