/* op-panel · assets.gf.cx — collapsible operational panel
   ────────────────────────────────────────────────────────────────────────
   The generic core of the status-hub operational panel: panel chrome, the
   sort segment + list/cards view toggle, the collapsible roll-up shell, and
   the card-view reflow (one <table> reflows to a card grid — no second DOM).
   Behaviour lives in op-panel.js. Surface-specific extensions (sparklines,
   sort-by-entity pins, per-surface flashes) layer ON TOP of this in the host
   page and are intentionally NOT part of the module.

   Single source of truth: this file. The status-hub renderer
   (gfcx_status_hub_render.py) imports it rather than inlining a copy.

   Tokens: consumes the gf.cx design-system custom properties, with hex
   fallbacks below so the module themes correctly on any surface. A surface
   that defines its own --accent/--line/etc overrides these. */

:root {
  --op-line:        var(--line, rgba(26,24,22,0.12));
  --op-line-strong: var(--line-strong, rgba(26,24,22,0.32));
  --op-ink:         var(--ink, #1a1816);
  --op-ink-soft:    var(--ink-soft, #5a544d);
  --op-accent:      var(--accent, #2c4a3a);
  --op-red:         var(--red, #a83333);
  --op-gold:        var(--gold, #dc7e00);
  --op-mono:        var(--mono, ui-monospace, 'SF Mono', 'Roboto Mono', monospace);
}

/* ── segmented control — sort segment + list/cards toggle share it ────────── */
.view-toggle { margin-left: auto; display: inline-flex; gap: 0;
               border: 1px solid var(--op-line); border-radius: 7px; overflow: hidden; }
.view-toggle__btn { font-family: var(--op-mono); font-size: 11px; letter-spacing: 0.4px;
                    text-transform: uppercase; padding: 3px 11px; border: 0;
                    background: transparent; color: var(--op-ink-soft); cursor: pointer;
                    transition: background .12s, color .12s; }
.view-toggle__btn + .view-toggle__btn { border-left: 1px solid var(--op-line); }
.view-toggle__btn:hover { color: var(--op-accent); }
.view-toggle__btn.is-active { background: var(--op-accent); color: #fff; }

/* ── panel chrome — head row carries the h2 + a controls cluster ──────────── */
.op-panel { scroll-margin-top: 12px; }
.op-panel__head { display: flex; align-items: baseline; gap: 10px 14px; flex-wrap: wrap; }
.op-panel__head h2 { margin: 0; }
.op-panel__head + p { margin-top: 6px; }
.op-panel__head--controls { justify-content: flex-end; margin-top: 10px; }
.op-controls { margin-left: auto; display: inline-flex; align-items: center;
               gap: 10px; flex-wrap: wrap; }
.op-sort { display: inline-flex; gap: 0; border: 1px solid var(--op-line);
           border-radius: 7px; overflow: hidden; }
.op-sort__btn { font-family: var(--op-mono); font-size: 11px; letter-spacing: 0.4px;
                text-transform: uppercase; padding: 3px 11px; border: 0;
                background: transparent; color: var(--op-ink-soft); cursor: pointer;
                transition: background .12s, color .12s; }
.op-sort__btn + .op-sort__btn { border-left: 1px solid var(--op-line); }
.op-sort__btn:hover { color: var(--op-accent); }
.op-sort__btn.is-active { background: var(--op-accent); color: #fff; }

/* ── collapsible shell — roll-up of stat-cards at rest, detail on expand ──── */
.op-panel--collapsible { margin-top: 8px; }
.op-collapse > summary { list-style: none; cursor: pointer; display: block; }
.op-collapse > summary::-webkit-details-marker { display: none; }
.op-collapse > summary::marker { content: ""; }   /* kill native triangle in WebKit/FOUC */
/* the title + its +/- marker sit as a unit, nudged down toward its card row */
.op-collapse__bar { display: flex; align-items: baseline; gap: 10px; position: relative; top: 8px; }
.op-collapse__bar h2 { margin: 0; }
.op-collapse__marker { margin-left: auto; font-family: var(--op-mono);
     font-size: 22px; line-height: 1; color: var(--op-ink-soft); transition: color .12s; }
.op-collapse__marker::after { content: "+"; }
.op-collapse[open] .op-collapse__marker::after { content: "\2212"; color: var(--op-accent); }
.op-collapse > summary:hover .op-collapse__marker { color: var(--op-accent); }
.op-collapse__stats { margin-top: 14px; }
.op-collapse[open] .op-collapse__stats { margin-bottom: 6px; }
/* Standard roll-up figure size (Dan 2026-08-04: "fonts too large for $0.55 …
   reduce"). The card primitive's 22px serif value reads too heavy for the money
   figures in the status roll-ups, so the op-panel pattern steps it down — one
   value, every panel's roll-up cards follow. Tune here, not per-surface. */
.op-collapse__stats .card__value { font-size: 17px; }

/* ── card view — the SAME <table> rows reflow into a responsive card grid via
      data-view="cards" on the panel (no second DOM copy). thead hidden; each
      <tr> becomes a card; each <td> a key:value line labelled by data-th.
      TWO table flavours share these rules: the status-hub `.scheduled-jobs`
      table, and the generic `.op-cardable` table — any surface can opt a plain
      table into card view by marking the <table> `.op-cardable`, each <td>
      `data-th="…"`, and the head cell `data-card-title`. The generic flavour
      carries no verdict rails / sched-* semantics (see below); those stay
      status-hub-only. ──── */
.op-panel[data-view="cards"] table.scheduled-jobs,
.op-panel[data-view="cards"] table.op-cardable { margin-bottom: 24px; }
.op-panel[data-view="cards"] table.scheduled-jobs thead,
.op-panel[data-view="cards"] table.op-cardable thead { position: absolute;
     width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.op-panel[data-view="cards"] table.scheduled-jobs tbody,
.op-panel[data-view="cards"] table.op-cardable tbody { display: grid;
     grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 12px; }
.op-panel[data-view="cards"] tr.sched-row,
.op-panel[data-view="cards"] table.op-cardable tbody > tr { display: block; border: 1px solid var(--op-line);
     border-radius: 9px; padding: 12px 14px; background: rgba(255,255,255,0.5); }
.op-panel[data-view="cards"] tr.sched-row td,
.op-panel[data-view="cards"] table.op-cardable tbody > tr > td { display: flex; justify-content: space-between;
     align-items: baseline; gap: 12px; border-bottom: 0; padding: 3px 0; white-space: normal; }
.op-panel[data-view="cards"] tr.sched-row td:first-child,
.op-panel[data-view="cards"] table.op-cardable tbody > tr > td:first-child { border-left: 0; }
.op-panel[data-view="cards"] tr.sched-row td::before,
.op-panel[data-view="cards"] table.op-cardable tbody > tr > td[data-th]::before { content: attr(data-th);
     font-family: var(--op-mono); font-size: 10px; text-transform: uppercase;
     letter-spacing: 0.8px; color: var(--op-ink-soft); flex: none; }
/* label cell = card title: drop its data-th label, make it a full-width head.
   the tr.sched-row prefix outweighs the generic `tr td` flex rule above. */
.op-panel[data-view="cards"] tr.sched-row td.sched-label,
.op-panel[data-view="cards"] table.op-cardable tbody > tr > td[data-card-title] { display: block; font-size: 14px;
     margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--op-line); }
.op-panel[data-view="cards"] tr.sched-row td.sched-label::before,
.op-panel[data-view="cards"] table.op-cardable tbody > tr > td[data-card-title]::before { display: none; }
.op-panel[data-view="cards"] tr.sched-row td.sched-status { text-align: right; font-size: 15px;
     padding-top: 3px; }
/* verdict rail on the card edge (mirrors the list-view td:first-child rail) */
.op-panel[data-view="cards"] tr.sched-row--failed { border-left: 3px solid var(--op-red); }
.op-panel[data-view="cards"] tr.sched-row--not-loaded { border-left: 3px solid var(--op-gold); }
.op-panel[data-view="cards"] tr.sched-row--recovered { border-left: 3px solid var(--op-gold); }
.op-panel[data-view="cards"] tr.sched-row--pending { border-left: 3px solid rgba(26,24,22,0.18); }

/* ── list-view figure-header alignment (the core pattern — Dan 2026-08-04:
   "add the patch to the core-page-pattern to avoid future build errors").
   A numeric/glyph column marks its header <th class="amount">, but the data
   cells in these jobs tables render LEFT (status glyphs, money composites like
   "$0.50 / $25 · 2%", speed numbers). So the header default must be LEFT to sit
   over its values — a centered default floats the header 17–149px right of the
   data (the status.gf regression this rule prevents from recurring on any
   surface). A column that is genuinely right-aligned overrides per-id in the
   host page (e.g. status.gf's #active State). Header text-align must equal its
   column's cell align — set it here once, every surface inherits it. */
table.scheduled-jobs th.amount,
table.op-cardable th.amount { text-align: left; }

/* ── list-view verdict rails — a faint status tint + a left accent bar ─────── */
tr.sched-row--failed { background: rgba(168,51,51,0.06); }
tr.sched-row--failed td:first-child { border-left: 3px solid var(--op-red); }
tr.sched-row--not-loaded { background: rgba(184,134,42,0.06); }
tr.sched-row--not-loaded td:first-child { border-left: 3px solid var(--op-gold); }
/* recovered = fixed + re-run green, but a sticky exit code hasn't caught up
   until the next scheduled run. Amber, not red — worth a glance, self-clears. */
tr.sched-row--recovered { background: rgba(184,134,42,0.06); }
tr.sched-row--recovered td:first-child { border-left: 3px solid var(--op-gold); }
tr.sched-row--pending td:first-child { border-left: 3px solid rgba(26,24,22,0.18); }

/* ── Per-chart line/stack pill (paired with [data-chart-toggle] in op-panel.js).
   A .view-toggle placed in a right-aligned row above an embedded chart; the
   inactive datawrapper iframe is hidden so only one view shows at a time. The
   pill reuses .view-toggle / .view-toggle__btn styling above. */
.chart-view-toggle-row { display: flex; justify-content: flex-end; margin-bottom: 6px; }
[data-chart-toggle] iframe[data-cview][hidden] { display: none !important; }

/* ── Standard data-figure treatment (Dan 2026-08-04: "how we handle these
   font/sizes should be built into the status pattern" · "full size, suffix
   equal + muted"). A JSON-sourced money/metric figure and its secondary
   context (e.g. "$0.50" + "/ $25 · 2%") render at the SAME size — the context
   differs by muted colour + regular weight only, never a smaller font. Works
   in both the card roll-up (.card__value) and the op-panel table (.amount),
   so every panel's figures read level. Use .op-figure__ctx on the suffix. */
.op-figure__ctx { color: var(--op-ink-soft); font-weight: 400; }

/* ── whole-card link affordance + ring gauge (Dan 2026-08-04: #google-gcp cards
   deep-link to the authoritative GCP console; the ring encodes % of cap). Kept
   generic on the shelf so #anthropic / /spend/ can adopt rings later. ──── */
.card--link { display: block; text-decoration: none; color: inherit; cursor: pointer;
              transition: border-color .12s, box-shadow .12s; }
.card--link:hover { border-color: var(--op-accent); box-shadow: 0 4px 16px rgba(26,24,22,0.07); }
.card--link .card__label { display: flex; align-items: center; gap: 6px; }
.card--link .card__ext { margin-left: auto; font-family: var(--op-mono); font-size: 11px;
                         color: var(--op-ink-soft); transition: color .12s; }
.card--link:hover .card__ext { color: var(--op-accent); }
.card__mark { width: 12px; height: 12px; flex: none; color: var(--op-ink-soft); }

.card-ring-row { display: flex; align-items: center; gap: 12px; margin-top: 8px; }
.card-ring-figure { min-width: 0; }
.card-ring { flex: none; }
.card-ring__track { fill: none; stroke: rgba(26,24,22,0.10); stroke-width: 5; }
.card-ring__fill  { fill: none; stroke: var(--op-accent); stroke-width: 5; stroke-linecap: round; }
.card-ring__pct   { font-family: var(--op-mono); font-size: 10px; fill: var(--op-ink-soft); }
.card-ring--amber .card-ring__fill  { stroke: var(--op-gold); }
.card-ring--amber .card-ring__track { stroke: rgba(220,126,0,0.15); }
.card-ring--amber .card-ring__pct   { fill: var(--op-gold); }
.card-ring--red   .card-ring__fill  { stroke: var(--op-red); }
.card-ring--red   .card-ring__track { stroke: rgba(168,51,51,0.15); }
.card-ring--red   .card-ring__pct   { fill: var(--op-red); }

/* Ring cards' labels run one line ("Cloud Run") or two ("Account total" wrapped
   at narrow width). Reserve two lines and top-align, so every label's first line
   — and the ring-row beneath it — lands at the same Y across the grid. Without
   this, a single-line label floats its whole card's ring up out of alignment. */
.card--ring .card__label { align-items: flex-start; min-height: 2lh; }

/* ring-less Daily-cost variant — no cap to fill, so a dashed border + a larger
   ~est figure, never a filled ring. */
.card--daily { border-style: dashed; background: rgba(255,255,255,0.35); }
.card__value--daily { font-size: 22px; }
