/* Overview (design v9, board Overview). The page head holds the one primary
   action. An active team (one with tasks) sees one money card (its balance
   with how many days it lasts, the reserved amount, the amount owed and
   what it spent this month), then the recent tasks beside the 接入 card
   (its newest key, its callback endpoint and the API address with its copy
   control, or, until the console publishes one, where it is documented). A
   new team sees the money card beside the get-started checklist, the
   models its price list names and the empty recent tasks. Cards, buttons, badges, tables, snippets and dialogs
   are the v9 classes of the shared stylesheet; this file places them. The
   section is a size container, so the layout follows the content column,
   not the window. */
.overview { display: flex; flex-direction: column; gap: 16px; container-type: inline-size; }
.overview > .page-head { align-items: center; margin: 0 0 8px; }
.overview > .page-head .btn .glyph { margin-left: -2px; }
.overview > .page-head .page-title:focus { outline: none; }
.overview .card { margin: 0; }

/* First row: the money card alone, or beside the checklist (1 : 2). */
.overview-lead { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: stretch; }
.overview-lead:has(> .overview-start:not([hidden])) { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }

/* Money: one card, a cell per figure, hairlines between them. The available
   balance leads at 36/44 with the top-up help under it; the reserved amount
   and the amount owed are 20/28. Only the amount owed is red. A cell that
   has nothing to say is hidden: the reserved amount at zero while a debt
   shows, or whenever the balance could not be read. */
.overview-money { display: flex; flex-wrap: wrap; padding: 0; container-type: inline-size; }
.overview-credit, .overview-stat { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; padding: 20px; }
.overview-credit { flex: 1.4 1 0; container-type: inline-size; }
.overview-stat { flex: 1 1 0; border-left: 1px solid var(--line-soft); }
.overview-credit .stat-label, .overview-stat .stat-label { margin: 0; }
.overview-stat-label { display: inline-flex; align-items: center; gap: 6px; }
.overview-hint { color: var(--text-3); cursor: help; }
/* The amount never breaks inside its digits. Its size follows the cell (7em
   holds a six-digit balance), up to 36px. A longer balance moves its whole
   tail to the next line instead of running past the card. The last four of
   the six decimals stay out of the headline figure, as in the balance
   chip. */
.overview-amount { min-width: 0; max-width: 100%; margin-top: 4px; color: var(--text-3); font-size: 14px; line-height: 20px; }
.overview-amount .money { --amount-size: 36px; display: inline-flex; flex-wrap: wrap; align-items: baseline; max-width: 100%; color: var(--text-1); font-size: clamp(24px, calc((100cqi - 40px) / 7), var(--amount-size)); line-height: 44px; font-weight: 600; letter-spacing: -.01em; white-space: nowrap; font-variant-numeric: tabular-nums; }
.overview-amount .money-tail { display: none; }
.overview-amount:not(:has(.money)) { margin: 14px 0 10px; }
.overview-runway { margin: 8px 0 0; color: var(--text-3); font-size: 13px; line-height: 20px; }
/* Less than a day of balance at the last week's spend is a warning. */
.overview-runway.is-short { color: var(--warning-fg); }
.overview-topup { margin-top: 12px; }
.overview-figure { min-width: 0; max-width: 100%; margin: 20px 0 0; color: var(--text-1); font: 600 20px/28px var(--font-sans); font-variant-numeric: tabular-nums; }
.overview-figure .money { display: inline-flex; flex-wrap: wrap; align-items: baseline; max-width: 100%; font-size: 20px; white-space: nowrap; }
/* Words in a figure's place (本月消费 still being read, unreadable, or too
   long a ledger) are muted body text, as the balance's are, never a figure
   beside the amounts. */
.overview-figure:not(:has(.money)) { color: var(--text-3); font: 400 14px/20px var(--font-sans); }
/* The reserved amount drops its last four decimals, as the balance does.
   The amount owed shows them only when they are not zero (an amount below
   one cent), so the card never shows less than is owed. */
.overview-figure .money-tail { color: var(--text-3); font-size: 14px; }
.overview-stat:not(.overview-due) .overview-figure .money-tail, .overview-figure.is-whole .money-tail { display: none; }
.overview-due .overview-figure, .overview-due .overview-figure .money, .overview-due .overview-figure .money-tail { color: var(--danger-fg); }
.overview-stat-link, .overview-stat-note { margin: auto 0 0; padding-top: 16px; font-size: 13px; line-height: 20px; }
.overview .btn.btn-link.overview-stat-link { margin-top: auto; font-size: 13px; line-height: 20px; }
.overview-stat-note { color: var(--text-2); }

/* Get started (new teams): a count, a close button and three steps ticked
   from what this page read. A step that is not done is one link. */
.overview-start-head { display: flex; align-items: center; gap: 12px; }
.overview-steps { margin: 0; padding: 0; list-style: none; }
.overview-steps > li { position: relative; display: flex; align-items: center; gap: 12px; min-height: 60px; padding: 10px 16px 10px 20px; border-top: 1px solid var(--line-soft); transition: background-color var(--t-hover) var(--ease); }
.overview-steps > li:has(> .step-link):hover { background: var(--gray-50); }
.step-mark { position: relative; flex: none; width: 20px; height: 20px; border: 1px solid var(--gray-400); border-radius: 50%; background: var(--gray-0); }
.overview-steps > li.is-done .step-mark { border-color: var(--violet-600); background: var(--violet-600); }
.overview-steps > li.is-done .step-mark::after { content: ""; position: absolute; top: 5px; left: 4.5px; width: 8px; height: 4px; border: solid #fff; border-width: 0 0 2px 2px; transform: rotate(-45deg); }
.step-text { display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; color: inherit; text-decoration: none; }
.step-link::after { content: ""; position: absolute; inset: 0; }
.step-link:hover { color: inherit; text-decoration: none; }
.step-link:focus-visible { outline: none; }
.step-link:focus-visible::after { border-radius: var(--r-8); box-shadow: inset 0 0 0 2px var(--focus); }
.step-name { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; color: var(--text-1); font: 500 14px/20px var(--font-sans); }
.step-desc { color: var(--text-3); font-size: 13px; line-height: 20px; }
.step-done, .step-unknown { display: none; color: var(--text-3); font-size: 13px; line-height: 20px; }
.overview-steps > li.is-done .step-done, .overview-steps > li.is-unknown .step-unknown { display: block; }
.overview-steps > li:is(.is-done, .is-unknown) .step-desc { display: none; }
.overview-steps > li.is-done .step-name { color: var(--text-2); }
.overview-steps > li.is-done .step-chevron { visibility: hidden; }
.step-chevron { margin-left: auto; color: var(--gray-400); }
.overview-steps > li:hover .step-chevron { color: var(--gray-700); }

/* The models a new team can use, as its price list names them: a card
   with its cover (a plain one naming the model when the page has none),
   what the model can do and the team's own rate. A model the page has no
   card for joins the same grid. */
.overview-models-block { display: flex; flex-direction: column; gap: 12px; }
.overview-sechead { margin: 8px 0 0; }
.overview-models { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.overview-model { display: flex; flex-direction: column; overflow: hidden; padding: 0; color: inherit; text-decoration: none; }
.overview-model:hover { color: inherit; text-decoration: none; }
.overview-cover { display: block; aspect-ratio: 16 / 9; }
.overview-cover img { display: block; }
.overview-model-body { display: flex; flex-direction: column; gap: 4px; padding: 16px 20px 20px; }
.overview-model-name { color: var(--text-1); font: 600 16px/24px var(--font-sans); }
.overview-model-desc { color: var(--text-2); font-size: 13px; line-height: 20px; }
.overview-model-price { display: flex; align-items: baseline; gap: 6px; margin-top: 8px; }
.overview-model-price:has(> .overview-model-rate:empty) { display: none; }
.overview-model-rate { color: var(--text-1); font: 600 16px/24px var(--font-sans); font-variant-numeric: tabular-nums; }
.overview-model-unit { color: var(--text-3); font-size: 12px; line-height: 16px; }
.overview-model-more { display: contents; }
.overview-cover-plain { display: grid; place-items: center; background: linear-gradient(135deg, var(--violet-50), var(--gray-100)); }
.overview-cover-name { color: var(--violet-700); font: 600 20px/28px var(--font-sans); letter-spacing: -.01em; }

/* Second row: the recent tasks beside the 接入 card (751 : 368 on the
   board); one column for a new team, or in a narrow content column. */
.overview-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
.overview-grid:has(> .overview-connect:not([hidden])) { grid-template-columns: minmax(0, 1fr) minmax(0, 368px); }
.overview-card-head { align-items: center; padding-bottom: 12px; }
.overview .btn.btn-link.overview-more { font-size: 13px; line-height: 20px; white-space: nowrap; }

/* Recent tasks: the table runs to the card edges, rows are 56px with the
   edition tile, the model (the row's one link, stretched over the row) and
   the task ID with the key that created it. Loading and failure are one
   line. The list is a size container: under 560px (phones) each task
   becomes one two-line block. */
.overview-tasks { container-type: inline-size; border-top: 1px solid var(--line-soft); }
.overview-tasks:empty, .overview-tasks:not(:has(> *)) { padding: 20px; color: var(--text-3); font-size: 13px; line-height: 20px; }
.overview-tasks-note { margin: 0; padding: 20px; color: var(--text-3); font-size: 13px; line-height: 20px; }
.overview-tasks > .empty { padding: 24px 16px 40px; }
.overview-table-scroll { overflow-x: auto; }
.overview-table-scroll .table td { height: 56px; }
.overview-table-scroll .table th:nth-child(3), .overview-table-scroll .table th:nth-child(4) { width: 1%; }
.overview-cell-state, .overview-cell-settlement, .overview-time { white-space: nowrap; }
.overview-cell-settlement { color: var(--text-2); }
.overview-time { color: var(--text-2); font-variant-numeric: tabular-nums; }
.overview-task { display: flex; align-items: center; gap: 12px; min-width: 0; }
.overview-tile { background: var(--gray-50); color: var(--gray-600); font: 500 12px/16px var(--font-sans); }
.overview-tasks tbody tr:hover .overview-tile { background: var(--gray-100); }
.overview-task-text { display: flex; flex-direction: column; min-width: 0; }
.overview-task-link { overflow: hidden; color: var(--text-1); font-size: 14px; line-height: 20px; text-overflow: ellipsis; white-space: nowrap; }
.overview-task-link:hover { color: var(--text-1); }
.overview-task-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.overview-task-sub { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; }
.overview-task-id { font: 400 12px/20px var(--font-mono); white-space: nowrap; }
.overview-task-key { overflow: hidden; max-width: 16em; text-overflow: ellipsis; white-space: nowrap; }
.overview-task-key::before { content: "·"; margin-right: 8px; color: var(--gray-400); }

/* 接入: state, not navigation; each row is one link to where it is
   managed. */
.overview-int-list { display: flex; flex-direction: column; }
.overview-int-row { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 12px 20px; border-top: 1px solid var(--line-soft); color: inherit; text-decoration: none; transition: background-color var(--t-hover) var(--ease); }
.overview-int-row:hover { background: var(--gray-50); color: inherit; text-decoration: none; }
.overview-int-row:last-child { border-radius: 0 0 var(--r-12) var(--r-12); }
.overview-int-row:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.overview-int-main { display: flex; flex: 1 1 auto; flex-direction: column; gap: 4px; min-width: 0; }
.overview-int-k { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--text-3); font: 500 12px/16px var(--font-sans); }
.overview-int-k > span + span { font-weight: 400; white-space: nowrap; }
.overview-int-v { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; color: var(--text-1); font-size: 14px; line-height: 20px; }
.overview-int-v .mono { overflow: hidden; max-width: 100%; font-size: 13px; line-height: 20px; text-overflow: ellipsis; white-space: nowrap; }
.overview-int-v .badge { flex: none; }
.overview-int-muted, .overview-int-v .overview-int-muted { color: var(--text-3); }
.overview-int-chev { flex: none; color: var(--gray-400); }
.overview-int-row:hover .overview-int-chev { color: var(--gray-700); }

/* 接入's API address (FE9-ADDR), once the console publishes one, in place
   of the link to where it is documented: the board's 40px snippet, the
   address with its copy icon. The row holds its own control, so it is not
   a link and does not light up on hover. As on the API key page, the icon
   names its action in the board's tooltip while it is hovered (where the
   device can hover) or focused, and a copy that worked shows a check and
   「已复制」 for 1.6 seconds. A failed copy is said under the snippet. */
.overview-int-address { flex-direction: column; align-items: stretch; gap: 8px; padding-bottom: 20px; }
.overview-int-address:hover { background: none; }
.overview-int-address > .overview-int-k { margin: 0; }
.overview-copy { flex: none; }
.overview-copy > .tooltip { position: absolute; bottom: calc(100% + 6px); left: 50%; z-index: var(--z-tooltip); display: none; white-space: nowrap; transform: translateX(-50%); pointer-events: none; }
@media (hover: hover) {
  .overview-copy:hover:not(.is-copied) > .overview-tip { display: block; }
}
.overview-copy:focus-visible:not(.is-copied) > .overview-tip { display: block; }
.btn.overview-copy.is-copied, .btn.overview-copy.is-copied:hover { color: var(--success-fg); }
.overview-copy.is-copied > .glyph { display: none; }
.overview-copy.is-copied::after { content: ""; width: 12px; height: 12px; background: currentColor; clip-path: path("M1.4 6.4L2.9 4.9L4.9 6.9L9.1 2.7L10.6 4.2L4.9 9.9Z"); }
.overview-copy.is-copied > .overview-copied { display: block; }
.overview-int-status { margin: 0; color: var(--danger-fg); font-size: 12px; line-height: 16px; }
.overview-int-status:empty { display: none; }

/* How to top up: the v9 dialog over a blurred backdrop, three numbered
   steps, the team ID to quote with the payment and the two actions. Phones
   get a bottom sheet. */
.overview-layer { position: fixed; inset: 0; z-index: var(--z-overlay); display: grid; place-items: center; padding: 16px; }
.overview-backdrop { position: absolute; inset: 0; background: rgba(16, 22, 31, .48); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.overview-dialog { z-index: 1; gap: 16px; }
.overview-dialog-close { position: absolute; top: 16px; right: 16px; }
.overview-dialog .dialog-title { padding-right: 40px; }
.overview-topup-steps { display: flex; flex-direction: column; gap: 12px; margin: 4px 0 0; padding: 0; list-style: none; counter-reset: topup; }
.overview-topup-steps > li { position: relative; padding-left: 34px; color: var(--text-1); font-size: 14px; line-height: 22px; counter-increment: topup; }
.overview-topup-steps > li::before { content: counter(topup); position: absolute; top: 0; left: 0; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--gray-100); color: var(--text-2); font: 500 12px/16px var(--font-sans); }
.overview-topup-team { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.overview-topup-team .label { margin: 0; }
.overview-team { font: 400 13px/20px var(--font-mono); user-select: all; }
.overview-topup-status { margin: 0; color: var(--success-fg); font-size: 12px; line-height: 16px; }
.overview-topup-status:empty { display: none; }
.overview-dialog-foot { align-items: center; margin-top: 4px; }

/* Session tools under the page: the sign-out of a restricted session. The
   frame's account menu holds the sign-out of a full one, so this button
   shows only while the account section is hidden. */
.overview-sign-out { margin-top: 16px; }
#account:not([hidden]) ~ .overview-sign-out { display: none; }
#restricted { margin: 0; padding: 10px 12px 10px 16px; border: 1px solid var(--warning-border); border-radius: var(--r-8); background: var(--warning-tint); color: var(--warning-fg); font-size: 14px; line-height: 20px; }
#session-status { margin: 12px 0 0; color: var(--text-2); font-size: 13px; line-height: 20px; }
#session-status:empty { display: none; }

/* A content column under 976px (the board's 1280px window) stacks the
   recent tasks and 接入, whose rows then sit side by side while there is
   room; under 768px the money card and the checklist stack too, and under
   640px the model cards. */
@container (max-width: 975px) {
  .overview-grid:has(> .overview-connect:not([hidden])) { grid-template-columns: minmax(0, 1fr); }
}
@container (min-width: 640px) and (max-width: 975px) {
  .overview-int-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .overview-int-row { align-items: flex-start; padding-bottom: 16px; }
  .overview-int-row + .overview-int-row { border-left: 1px solid var(--line-soft); }
  .overview-int-row:last-child { border-radius: 0 0 var(--r-12) 0; }
  .overview-int-row:first-child { border-radius: 0 0 0 var(--r-12); }
  .overview-int-chev { display: none; }
  /* The address keeps its snippet the width of its column. */
  .overview-int-row.overview-int-address { align-items: stretch; }
}
@container (max-width: 767px) {
  .overview-lead:has(> .overview-start:not([hidden])) { grid-template-columns: minmax(0, 1fr); }
}
@container (max-width: 639px) {
  .overview-models { grid-template-columns: minmax(0, 1fr); }
}

/* A money card under 520px: the available balance on its own row over a
   row of the other figures. */
@container (max-width: 519px) {
  .overview-credit { flex-basis: 100%; }
  .overview-spend-since { display: none; }
  .overview-stat { padding: 16px 20px; border-top: 1px solid var(--line-soft); }
  .overview-credit + .overview-stat { border-left: 0; }
  .overview-figure { margin-top: 4px; }
  .overview-stat-link, .overview-stat-note, .overview .btn.btn-link.overview-stat-link { padding-top: 4px; }
}

/* A recent-tasks list under 560px: one block per task, the edition tile and
   the task over its state, settlement and time. Nothing is cut off and
   nothing scrolls sideways. */
@container (max-width: 559px) {
  .overview-table-scroll { overflow: visible; }
  .overview-table-scroll .table, .overview-table-scroll tbody { display: block; width: 100%; }
  .overview-table-scroll thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .overview-table-scroll tbody tr { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "task task task" "state settlement time"; align-items: center; gap: 8px 10px; padding: 12px 16px; border-bottom: 1px solid var(--line-soft); }
  .overview-table-scroll tbody tr:last-child { border-bottom: 0; }
  .overview-table-scroll .table td, .overview-table-scroll .table tr > :first-child, .overview-table-scroll .table tr > :last-child { display: block; height: auto; min-width: 0; padding: 0; border: 0; }
  .overview-table-scroll td:nth-child(1) { grid-area: state; }
  .overview-table-scroll td:nth-child(2) { grid-area: task; }
  .overview-table-scroll td:nth-child(3) { grid-area: settlement; font-size: 13px; }
  .overview-table-scroll td:nth-child(4) { grid-area: time; font-size: 13px; text-align: right; }
}

/* Phones: every text link keeps a 44px tap target. */
@media (max-width: 767px) {
  .overview > .page-head { margin-bottom: 0; }
  .overview-steps > li { min-height: 64px; padding-left: 16px; }
  .overview .btn.btn-link { position: relative; }
  .overview .btn.btn-link::before { content: ""; position: absolute; inset: -12px -4px; }
  .overview-int-row { min-height: 56px; }
  .overview-layer { align-items: end; padding: 0; }
  .overview-dialog-foot { flex-direction: column-reverse; align-items: stretch; }
}

/* State badges carry the v9 marks: a dot while queued, a pulsing violet
   dot while processing, a check on success and a cross on failure. */
.overview-tasks .state-badge { gap: 6px; }
.overview-tasks .state-badge::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--neutral-dot); }
.overview-tasks .state-badge.state-run::before { background: var(--info-dot); animation: v9-pulse 1.6s var(--ease) infinite; }
.overview-tasks .state-badge.state-ok::before, .overview-tasks .state-badge.state-fail::before { width: 10px; height: 10px; border-radius: 0; background: currentColor; }
.overview-tasks .state-badge.state-ok::before { clip-path: path("M1.2 5.3L2.4 4.1L4.1 5.8L7.6 2.3L8.8 3.5L4.1 8.2Z"); }
.overview-tasks .state-badge.state-fail::before { clip-path: path("M2.3 1.2L5 3.9L7.7 1.2L8.8 2.3L6.1 5L8.8 7.7L7.7 8.8L5 6.1L2.3 8.8L1.2 7.7L3.9 5L1.2 2.3Z"); }
@media (prefers-reduced-motion: reduce) {
  .overview-tasks .state-badge.state-run::before { animation: none; }
}
