/* API keys (design v9, board ApiKeys; S-413 FE9-KEY2): the page head with
   its one primary (创建 API 密钥), the key table in one card (名称, 密钥
   with 查看, 隐藏 and 复制 and their tooltips, 状态, 消费上限, 有效期,
   最近使用 once the list carries it, 创建时间, then 停用 or 启用 and a ⋯
   menu of 修改上限, 复制连接信息 (a key in use, once the console publishes
   its API address) and 删除 per row), then the access card with the request
   headers, the published API address with its copy control (or, until the
   console publishes one, a link to where it is documented), the 快速开始 and
   创建视频任务 links and a request sample in four languages. Creating a
   key, the new key, editing a
   limit and deleting open modal v9 dialogs; a finished change is a v9
   toast. While the page waits for its session check a skeleton of the
   table stands in; a page that cannot be shown says why in one card with
   its two ways out. Cards, buttons, fields, switches, segments, badges,
   menus, meters, tables, tooltips, toasts and code are the v9 classes of
   the shared stylesheet; this file places them and draws the two menu
   glyphs. */
.keys { display: flex; flex-direction: column; gap: 16px; container-type: inline-size; }
.keys > .page-head { margin-bottom: 8px; }
.keys .card { margin: 0; padding: 0; }

/* The key table. The card is a size container: under 640px (phones) each
   key becomes one block (see the end of the file), so no amount or action
   is ever cut off. Times read MM-DD HH:mm, so the table fits a 640px card;
   if a long name still makes it wider than the card, it scrolls sideways
   with the action column pinned to the right edge. An empty list drops the
   width floor so its message stays centred. */
.keys-card { container-type: inline-size; }
.keys-table { container-type: scroll-state; }
.keys-table .table { min-width: 620px; }
.keys-table .table:has(.keys-empty-row) { min-width: 0; }
.keys-table th, .keys-table td { padding-right: 12px; padding-left: 12px; }
.keys-table td { height: 56px; vertical-align: middle; }
.keys-table th.keys-actions-head, .keys-table td.key-actions-cell { position: sticky; right: 0; z-index: 1; width: 1%; text-align: right; background-color: var(--surface); }
/* An open menu rises over the later rows' pinned cells. */
.keys-table td.key-actions-cell:has(.key-menu[open]) { z-index: 5; }
.keys-table tbody tr:hover > td.key-actions-cell { background-color: var(--gray-50); }
@container scroll-state(scrollable: inline-end) {
  .keys-table th.keys-actions-head, .keys-table td.key-actions-cell { box-shadow: inset 1px 0 0 var(--line), -8px 0 8px -8px rgba(26, 35, 48, .18); }
}
.keys-cell-label { display: none; }
/* The board's proportions: the name takes 18% and the key 30%; the other
   columns share the rest. */
.key-name-cell { width: 18%; min-width: 120px; }
.key-name { color: var(--text-1); font-size: 14px; line-height: 20px; font-weight: 500; overflow-wrap: anywhere; }
.key-cell { width: 30%; min-width: 150px; }
.key-secret { display: inline-flex; align-items: center; gap: 2px; color: var(--text-2); font-size: 13px; line-height: 20px; white-space: nowrap; }
.key-secret code { color: var(--text-1); font: 400 13px/20px var(--font-mono); letter-spacing: .02em; }
.key-secret .key-copy { margin-left: 4px; color: var(--text-3); }
.key-secret .key-copy:hover { color: var(--text-1); }
/* 查看 (an eye) and 隐藏 (a struck eye, in its place while the key is
   shown) sit between the key and 复制. A shown key is twelve-character
   chunks that never break (the board's <wbr> chunks), so it wraps only
   between two chunks and never widens the table past its card. Every chunk
   is as wide as twelve characters with the key's letter spacing (the last,
   shorter one too), so each line holds as many chunks as the others: 24
   and 22 characters at 1440px, one chunk a line at 1024px. As on the board
   its cell turns light grey, the controls level with its first line, and
   隐藏 reads as the pressed icon button. */
.key-secret .key-eye { margin-left: 4px; color: var(--text-3); }
.key-secret .key-eye:hover { color: var(--text-1); }
.key-secret .key-eye ~ .key-copy { margin-left: 0; }
.key-secret.is-shown { align-items: flex-start; }
.key-secret.is-shown > code { white-space: normal; }
.key-secret.is-shown > .key-eye, .key-secret.is-shown > .key-eye:hover { background: var(--accent-tint); color: var(--violet-700); }
.key-chunk { display: inline-block; min-width: calc(12ch + .24em); white-space: nowrap; }
.keys-table td.key-cell:has(> .key-secret.is-shown) { background: var(--gray-25); }
/* 查看, 隐藏 and 复制 name their action in the board's tooltip over the
   control while it is hovered or focused. A copy control that just copied
   shows a check, and the row's icon control 「已复制」 in the tooltip's
   place, for 1.6 seconds. */
.key-copied { display: none; }
.key-secret .key-eye, .key-copy { position: relative; }
.key-secret .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) {
  .key-secret .btn:hover:not(:disabled, .is-copied) > .key-tip { display: block; }
}
.key-secret .btn:focus-visible:not(.is-copied) > .key-tip { display: block; }
.key-secret .key-copy.is-copied, .key-secret .key-copy.is-copied:hover { color: var(--success-fg); }
.key-copy.is-copied > .glyph { display: none; }
.key-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"); }
.key-secret .key-copy.is-copied > .key-copied { display: block; }
:is(.keys-code-copy, #integration-created-copy).is-copied { color: var(--success-fg); }
:is(.keys-code-copy, #integration-created-copy).is-copied > :is(.glyph, .key-copy-label) { display: none; }
:is(.keys-code-copy, #integration-created-copy).is-copied::before { content: ""; position: static; 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"); }
:is(.keys-code-copy, #integration-created-copy).is-copied > .key-copied { display: inline; }
#integration-created-copy.is-copied { color: #fff; }
/* The limit is a number column: right-aligned, whole cents without their
   zero tail. Once the list carries what a key used, a 4px bar of that use
   against the limit sits under it (amber from 70 and red from 90 percent,
   one width class a step of five percent) over the amount used. */
.keys-table td.num { min-width: 88px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.keys-table td.num .money-tail { color: var(--text-3); }
.key-usage { display: block; color: var(--text-1); font-size: 13px; line-height: 20px; }
.key-usage-limit { color: var(--text-3); }
.key-meter { display: block; width: 100%; min-width: 96px; margin-top: 4px; }
.key-meter.is-warning > span { background: var(--warning-dot); }
.key-meter.is-danger > span { background: var(--danger-solid); }
.key-meter-0 { width: 0; } .key-meter-1 { width: 5%; } .key-meter-2 { width: 10%; } .key-meter-3 { width: 15%; } .key-meter-4 { width: 20%; }
.key-meter-5 { width: 25%; } .key-meter-6 { width: 30%; } .key-meter-7 { width: 35%; } .key-meter-8 { width: 40%; } .key-meter-9 { width: 45%; }
.key-meter-10 { width: 50%; } .key-meter-11 { width: 55%; } .key-meter-12 { width: 60%; } .key-meter-13 { width: 65%; } .key-meter-14 { width: 70%; }
.key-meter-15 { width: 75%; } .key-meter-16 { width: 80%; } .key-meter-17 { width: 85%; } .key-meter-18 { width: 90%; } .key-meter-19 { width: 95%; }
.key-meter-20 { width: 100%; }
.key-used { display: block; color: var(--text-3); font-size: 12px; line-height: 16px; }
.key-state { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.key-state .sub, .key-expiry .sub { display: block; width: 100%; color: var(--text-3); font-size: 12px; line-height: 16px; }
.key-expiry, .key-created, .key-last-use { color: var(--text-2); font-size: 13px; line-height: 20px; white-space: nowrap; }
.key-expiry time, .key-created time, .key-last-use time { font-variant-numeric: tabular-nums; }
/* The one-line facts of a key on a phone; the table shows them in columns. */
.key-meta { display: none; }

/* The row's actions: 停用 or 启用 at once, then the ⋯ menu. */
.key-row-actions { display: inline-flex; align-items: center; justify-content: flex-end; gap: 4px; vertical-align: middle; }
.keys-table .key-toggle { min-width: 56px; color: var(--gray-700); }
.keys-table .key-toggle:hover { color: var(--text-1); }

/* Row menu: a native disclosure (⋯) with the v9 menu under it. The menu
   floats over the rows below it; the danger item is red. */
.key-menu { position: relative; display: inline-block; text-align: left; }
.key-menu > summary { position: relative; display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: var(--r-6); color: var(--gray-400); list-style: none; cursor: pointer; transition: background-color var(--t-hover) var(--ease), color var(--t-hover) var(--ease); }
/* The ⋯ control answers a 44px square around itself. */
.key-menu > summary::after { content: ""; position: absolute; inset: -8px; }
.key-menu > summary::-webkit-details-marker { display: none; }
.key-menu > summary::before { content: ""; width: 16px; height: 4px; background: radial-gradient(circle, currentColor 1.5px, transparent 1.75px) 0 0 / 6px 4px repeat-x; }
.keys-table tbody tr:hover .key-menu > summary, .key-menu[open] > summary { color: var(--gray-700); }
.key-menu > summary:hover, .key-menu[open] > summary { background: var(--wash-1); }
.key-menu > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.key-menu > .key-actions { position: absolute; top: calc(100% + 4px); right: 0; z-index: var(--z-menu); min-width: 184px; }
/* Each item leads with its glyph, as on the board: a pencil for 修改上限
   and a bin for 删除 (16px outlines of 1.2px strokes, as the eye). */
.glyph.key-glyph-edit, .glyph.key-glyph-delete { width: 16px; height: 16px; }
/* 复制连接信息's 14px copy glyph keeps the menu's 16px column. */
.glyph.key-glyph-copy { margin: 1px; }
.glyph.key-glyph-edit { clip-path: path("M5.3 14.21L0.27 15.73L1.79 10.7L11.06 1.43L11.55 1.06L12.14 0.81L12.79 0.73L13.43 0.81L14.03 1.06L14.54 1.46L14.94 1.97L15.19 2.57L15.27 3.21L15.19 3.86L14.94 4.45L14.57 4.94ZM13.66 4.14L13.89 3.85L14.02 3.54L14.06 3.21L14.02 2.88L13.89 2.58L13.69 2.31L13.42 2.11L13.12 1.98L12.79 1.94L12.46 1.98L12.15 2.11L11.85 2.34L2.85 11.34L2.07 13.93L4.67 13.14ZM9.58 3.76L10.42 2.91L13.09 5.58L12.24 6.42Z"); }
.glyph.key-glyph-delete { clip-path: path("M2 3.4L14 3.4A0.6 0.6 0 0 1 14 4.6L2 4.6A0.6 0.6 0 0 1 2 3.4ZM2.73 4.6L2.73 12.67A1.93 1.93 0 0 0 4.67 14.6L11.33 14.6A1.93 1.93 0 0 0 13.27 12.67L13.27 4.6L12.07 4.6L12.07 12.67A0.73 0.73 0 0 1 11.33 13.4L4.67 13.4A0.73 0.73 0 0 1 3.93 12.67L3.93 4.6ZM5.4 3.4L5.4 2.67A1.27 1.27 0 0 1 6.67 1.4L9.33 1.4A1.27 1.27 0 0 1 10.6 2.67L10.6 3.4L9.4 3.4L9.4 2.67A0.07 0.07 0 0 0 9.33 2.6L6.67 2.6A0.07 0.07 0 0 0 6.6 2.67L6.6 3.4ZM7.27 7.33L7.27 11.33A0.6 0.6 0 0 1 6.07 11.33L6.07 7.33A0.6 0.6 0 0 1 7.27 7.33ZM9.93 7.33L9.93 11.33A0.6 0.6 0 0 1 8.73 11.33L8.73 7.33A0.6 0.6 0 0 1 9.93 7.33Z"); }
.key-actions { display: flex; flex-direction: column; }
.key-actions > .key-action:disabled { color: var(--gray-400); cursor: not-allowed; }
.key-actions > .key-action.is-danger { margin-top: 6px; border-top: 0; }
.key-actions > .key-action.is-danger::before { content: ""; position: absolute; top: -4px; right: -6px; left: -6px; height: 1px; background: var(--line-soft); }
.key-actions > .key-action.is-danger:first-child { margin-top: 0; }
.key-actions > .key-action.is-danger:first-child::before { content: none; }
.key-actions > .key-action { position: relative; }

/* Status lines under the table and in the dialogs */
.keys-status { margin: 0; padding: 10px 20px; border-top: 1px solid var(--line-soft); color: var(--text-2); font-size: 13px; line-height: 20px; }
.keys-status:empty { display: none; }
.keys-dialog-status { padding: 0; border-top: 0; }
/* A copy that worked is only announced: its control shows 已复制. */
.keys-status.is-announced { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; border: 0; clip-path: inset(50%); white-space: nowrap; }

/* The empty list: one centred state with the create action. */
.keys-empty-row td { height: auto; padding: 0; }
.keys-empty-row .empty { padding: 48px 16px; }

/* Access: the request headers and the API address, beside a light code
   sample in four languages with its copy control. */
.keys-access { display: grid; grid-template-columns: minmax(0, 466fr) minmax(0, 532fr); }
.keys-access-text { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 20px; }
.keys-access-intro, .keys-access-note { margin: 0; color: var(--text-2); font-size: 13px; line-height: 20px; }
.keys-access-note { color: var(--text-3); font-size: 12px; line-height: 16px; }
.keys-access-intro .code-inline { white-space: nowrap; }
.keys-endpoint-label { margin: 8px 0 0; color: var(--text-1); font: 500 13px/20px var(--font-sans); }
/* The published API address is the board's snippet with its copy
   control; until the console publishes one, the field links to the
   documentation that names it. */
.keys-snippet .keys-endpoint-copy { position: relative; flex: none; color: var(--text-3); }
.keys-snippet .keys-endpoint-copy:hover { color: var(--text-1); }
.keys-snippet .tooltip { position: absolute; bottom: calc(100% + 6px); left: 50%; z-index: var(--z-tooltip); white-space: nowrap; transform: translateX(-50%); pointer-events: none; }
.keys-snippet .keys-endpoint-copy.is-copied { color: var(--success-fg); }
.keys-snippet .keys-endpoint-copy.is-copied > .key-copied { display: block; }
.keys-endpoint { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 40px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-8); background: var(--gray-25); color: var(--text-2); font-size: 13px; line-height: 20px; text-decoration: none; }
.keys-endpoint:hover { border-color: var(--gray-300); color: var(--text-1); text-decoration: none; }
.keys-endpoint .glyph { color: var(--gray-400); }
.keys-links { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 4px; }
.keys .btn.btn-link.keys-link { font-size: 13px; line-height: 20px; }
.keys-code { border: 0; border-left: 1px solid var(--line-soft); border-radius: 0 var(--r-12) var(--r-12) 0; }
.keys-code .code-head { padding-left: 8px; }
.keys-code-tabs { display: flex; align-items: center; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.keys-code-copy { flex: none; margin-left: auto; }
.keys-code .choice-input:checked + .code-tab { color: var(--text-1); }
.keys-code .choice-input:checked + .code-tab::after { content: ""; position: absolute; right: 12px; bottom: -1px; left: 12px; height: 2px; border-radius: 2px 2px 0 0; background: var(--violet-600); }
.keys-code .choice-input:focus-visible + .code-tab { outline: 2px solid var(--focus); outline-offset: -4px; }
.keys-code .code-panel { display: none; min-height: 132px; margin: 0; padding: 12px 16px; overflow: auto; border: 0; border-radius: 0; background: none; color: var(--text-1); font: 400 13px/20px var(--font-mono); white-space: pre; }
.keys-code:has(#integration-code-curl:checked) .code-panel-curl, .keys-code:has(#integration-code-python:checked) .code-panel-python, .keys-code:has(#integration-code-node:checked) .code-panel-node, .keys-code:has(#integration-code-go:checked) .code-panel-go { display: block; }

/* Dialogs over a blurred backdrop; phones get bottom sheets. */
.keys-layer { position: fixed; inset: 0; z-index: var(--z-overlay); display: grid; place-items: center; padding: 16px; }
.keys-backdrop { position: absolute; inset: 0; background: rgba(16, 22, 31, .48); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.keys-dialog { z-index: 1; gap: 16px; }
.keys-dialog-close { position: absolute; top: 16px; right: 16px; }
.keys-dialog .dialog-title { padding-right: 40px; }
.keys-form { display: flex; flex-direction: column; gap: 16px; }
.keys-dialog .field { margin: 0; }
.keys-dialog p { margin: 0; }
.keys-dialog .dialog-foot { margin-top: 4px; }
.keys-seg { display: flex; width: 100%; }
.keys-seg > .seg-item { flex: 1 1 0; min-width: 0; padding: 0 8px; }
.keys-seg .choice-input:checked + .seg-item { background: var(--gray-0); box-shadow: 0 0 0 1px var(--line-soft), var(--e1); color: var(--text-1); }
.keys-seg .choice-input:focus-visible + .seg-item { outline: 2px solid var(--focus); outline-offset: 1px; }
.keys-seg .choice-input:disabled + .seg-item { color: var(--gray-400); cursor: not-allowed; }
.keys-day { margin-top: 2px; }
/* 消费上限: the 不限额度 switch (on by default) over its note; off, the
   amount field and its note take the note's place. */
.keys-switch { display: inline-flex; align-items: center; gap: 10px; align-self: flex-start; min-height: 24px; color: var(--text-1); font-size: 14px; line-height: 20px; cursor: pointer; }
.keys-switch > .switch:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.keys-limit:has(.switch:not(:checked)) > .keys-unlimited-help { display: none; }
.keys-amount { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
/* What the key used, holds in reserve and has left of its limit, once
   the list carries them: three figures in a light box above the field. */
.keys-usage { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; padding: 12px 16px; border: 1px solid var(--line); border-radius: var(--r-8); background: var(--gray-25); }
.keys-usage dt { color: var(--text-3); font-size: 12px; line-height: 16px; }
.keys-usage dd { margin: 2px 0 0; color: var(--text-1); font: 500 14px/20px var(--font-sans); font-variant-numeric: tabular-nums; white-space: nowrap; }
.keys-created-title { display: flex; align-items: center; gap: 10px; }
.keys-created-mark { position: relative; flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--success-tint); color: var(--success-fg); }
.keys-created-mark::after { content: ""; position: absolute; inset: 5px; background: currentColor; clip-path: path("M1.2 5.3L2.4 4.1L4.1 5.8L7.6 2.3L8.8 3.5L4.1 8.2Z"); }
.keys-secret-box { display: flex; flex-direction: column; gap: 4px; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-8); background: var(--gray-25); }
.keys-secret-name { margin: 0; color: var(--text-2); font-size: 12px; line-height: 16px; }
/* The new key wraps between its twelve-character chunks, as in the row,
   never after its sk-. */
.keys-secret-value { color: var(--text-1); font: 400 13px/20px var(--font-mono); user-select: all; }
/* The delete dialog's consequence and 删除后不能恢复 read as one paragraph,
   as on the board; English puts a space between the two sentences. */
#integration-delete-text:lang(en)::before { content: " "; }
/* The toast's line sits level with its mark and its 撤销. */
.keys-toasts .toast { align-items: center; }
.keys-toasts .toast-text { margin: 0; }

/* Until the page is shown: a skeleton of the head and the table while the
   session check runs (it appears after 200ms), or, once there is something
   to say, one card with the reason and the two ways out (reload, sign out).
   A list read again after a change keeps its rows on screen instead (see
   readKeys), so the skeleton never stands in for a shown list. The frame's
   account menu holds the sign-out while the list shows. */
#integration-page:not([hidden]) ~ .keys-state { display: none; }
.keys-loading { display: flex; flex-direction: column; gap: 16px; animation: keys-skeleton-in 160ms var(--ease) 200ms both; }
.keys-state:has(#integration-status:not(:empty)) > .keys-loading, .keys-state:has(#integration-restricted:not([hidden])) > .keys-loading { display: none; }
@keyframes keys-skeleton-in { from { opacity: 0; } to { opacity: 1; } }
.keys-loading-head { display: flex; flex-direction: column; gap: 10px; margin-bottom: 8px; padding-top: 4px; }
.keys-skel-title { width: 112px; height: 20px; }
.keys-skel-desc { width: min(420px, 80%); height: 12px; }
.keys-loading-card { margin: 0; padding: 0; overflow: hidden; }
.keys-loading-row { display: grid; grid-template-columns: 1.2fr 2fr 1fr 1fr; align-items: center; gap: 24px; height: 56px; padding: 0 20px; border-top: 1px solid var(--line-soft); }
.keys-loading-row.is-head { height: 36px; border-top: 0; }
.keys-loading-row.is-head > .skel { width: 48px; height: 8px; }
.keys-loading-row > .skel:nth-child(1) { width: 70%; }
.keys-loading-row > .skel:nth-child(3) { width: 48px; }
.keys-loading-row > .skel:nth-child(4) { justify-self: end; width: 56px; }
.keys-reason { display: flex; flex-direction: column; align-items: center; gap: 12px; max-width: 560px; margin: 24px auto 0; padding: 40px 24px; text-align: center; }
.keys-state:has(#integration-status:empty):has(#integration-restricted[hidden]) > .keys-reason { display: none; }
.keys-reason-icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: var(--r-8); background: var(--gray-100); color: var(--gray-700); }
#integration-status, #integration-restricted { max-width: 440px; margin: 0; color: var(--text-1); font-size: 14px; line-height: 22px; }
#integration-status:empty { display: none; }
.session-tools { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 8px; }

/* A key card of 880px or more holds the whole table, so the table does not
   clip a row menu that opens past its last row. */
@container (min-width: 880px) {
  .keys-table { overflow: visible; }
}

/* A key card under 640px (phones): one block per key, as on the board:
   the name and its status with 停用 or 启用 and the ⋯ menu, the key, then
   the facts of its limit, expiry and creation date. The status keeps the
   width of its badge (two badges stack) and the buttons theirs (the cells'
   min-width of 0 would let an auto track shrink under them); the name takes
   what is left and wraps, and the facts wrap between two facts. Nothing is
   cut off, nothing overlaps and nothing scrolls sideways; the column cells
   give way to the facts. */
@container (max-width: 639px) {
  .keys-table { overflow: visible; }
  .keys-table .table, .keys-table tbody { display: block; width: 100%; min-width: 0; }
  .keys-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .keys-table tbody tr { display: grid; grid-template-columns: minmax(0, max-content) max-content minmax(0, 1fr) max-content; grid-template-areas: "name status . menu" "key key key key"; align-items: center; gap: 8px; padding: 14px 12px 14px 20px; border-bottom: 1px solid var(--line-soft); }
  .keys-table tbody tr:last-child { border-bottom: 0; }
  .keys-table tbody tr.keys-empty-row { display: block; padding: 0; }
  .keys-table .table td, .keys-table .table tr > :first-child, .keys-table .table tr > :last-child { display: block; width: auto; height: auto; min-width: 0; padding: 0; border: 0; }
  .keys-table td.key-name-cell { grid-area: name; white-space: normal; }
  .keys-table td.key-cell { grid-area: key; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; white-space: normal; }
  .keys-table td.key-state-cell { grid-area: status; }
  .keys-table td.key-limit-cell, .keys-table td.key-expiry-cell, .keys-table td.key-used-cell, .keys-table td.key-created-cell { display: none; }
  .keys-table td.key-actions-cell { position: static; grid-area: menu; width: auto; box-shadow: none; background: transparent; }
  .keys-table tbody tr:hover > td.key-actions-cell { background: transparent; }
  .keys-table td.key-cell .keys-cell-label { display: none; }
  .key-state { flex-direction: column; align-items: flex-start; }
  .key-state .sub { display: none; }
  .key-meta { display: block; color: var(--text-3); font-size: 13px; line-height: 20px; }
  .key-fact { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
  /* A shown key is a light grey box of its own over the facts, 8px out on
     the left and 8px in on the right, as on the board. */
  .keys-table td.key-cell:has(> .key-secret.is-shown) { background: none; }
  .key-secret.is-shown { align-self: stretch; margin: 4px 8px 4px -8px; padding: 8px; border-radius: var(--r-8); background: var(--gray-25); }
  .key-actions { flex-wrap: wrap; }
}

/* A page under 980px (the board's viewports under 1280px): the access
   card's text over the code, so the sample is never cut off. */
@container (max-width: 979px) {
  .keys-access { grid-template-columns: minmax(0, 1fr); }
  .keys-code { border-top: 1px solid var(--line-soft); border-left: 0; border-radius: 0 0 var(--r-12) var(--r-12); }
}

@media (max-width: 767px) {
  .keys > .page-head { margin-bottom: 0; }
  .keys-access-text { padding: 16px; }
  .keys-layer { align-items: end; padding: 0; }
  .key-menu > summary { width: 36px; height: 36px; }
  .key-menu > summary::after { inset: -4px; }
  .keys-table .key-toggle { height: 36px; }
  /* 查看 and 复制 each answer a 44px square; they stand apart enough that
     the two squares never overlap. */
  .key-secret .key-eye ~ .key-copy { margin-left: 18px; }
  .keys .btn.btn-link.keys-link { position: relative; }
  .keys .btn.btn-link.keys-link::before { content: ""; position: absolute; inset: -12px -4px; }
  /* 撤销 is the way back from a one-click 停用: it answers a 44px row. */
  .keys-toasts .toast-action { position: relative; }
  .keys-toasts .toast-action::before { content: ""; position: absolute; inset: -12px -8px; }
  .keys-endpoint, .keys-snippet { min-height: 44px; }
  .keys-switch { min-height: 44px; }
  .keys-usage { gap: 8px; padding: 12px; }
  .keys-loading-row { grid-template-columns: 1fr 1fr; }
  .keys-loading-row > .skel:nth-child(n+3) { display: none; }
  .keys-reason { margin-top: 8px; padding: 32px 16px; }
}

/* An empty list holds the one create action; the head's button gives way,
   and so do the column heads and the access card (the board's empty state:
   one card with the action). */
.keys:has(.keys-empty-row) > .page-head > .keys-create { display: none; }
.keys-table .table:has(.keys-empty-row) > thead { display: none; }
.keys:has(.keys-empty-row) > .keys-access { display: none; }
