/*
 * Components of the dashboard redesign «A2 · Redonda» (decision 97; research/15-sistema-de-diseno.md §6). Each block
 * is one component of ComponentsHelper / app/views/components/, and /dashboard/design renders all of them.
 * Only tokens (tokens.css): no colour, radius or size of its own.
 */

/* Product link (product_link): the product's display name in mono, weight from the link rules (98.2, 98.5) */
.product-link { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* Utilities */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.type-page-title { font: 600 var(--font-page-title)/1.2 var(--sans); letter-spacing: -.02em; margin: 0; }
.type-card-title { font: 600 var(--font-card-title)/1.3 var(--sans); letter-spacing: -.01em; margin: 0; }
.icon { flex: none; display: block; }

/* Button: .btn + .btn-primary | .btn-secondary | .btn-ghost, .btn-sm; a link or a <button> (ui_button, btn_classes) */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--btn-h); padding: 0 var(--space-4); margin: 0;
  font: 500 var(--font-sm)/1.2 var(--sans); white-space: nowrap; text-decoration: none; cursor: pointer;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  transition: background-color .12s ease, border-color .12s ease;
}
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-secondary { background: var(--surface); border-color: var(--control-border); color: var(--text); }
.btn-secondary:hover { background: var(--surface-2); }
.btn-ghost { background: transparent; color: var(--text-2); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }
.btn-sm { min-height: var(--btn-h-sm); padding: 0 var(--space-3); font-size: var(--font-xs); }
.btn-icon { padding: 0; width: var(--btn-h-sm); }
.btn .icon { width: 16px; height: 16px; }
summary.btn { list-style: none; }
summary.btn::-webkit-details-marker { display: none; }

/* Badge (ui_badge, status_badge): pill with a dot in the state's colour; neutral has no dot */
.badge {
  display: inline-flex; align-items: center; gap: 6px; min-height: 22px; padding: 0 9px;
  border-radius: var(--radius-pill); font: 500 var(--font-xs)/1.2 var(--sans); white-space: nowrap; vertical-align: 1px;
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.badge-verified { background: var(--verified-bg); color: var(--verified); }
.badge-denied { background: var(--denied-bg); color: var(--denied); }
.badge-pending { background: var(--pending-bg); color: var(--pending); }
.badge-neutral { background: var(--surface-2); color: var(--text-2); }
.badge-neutral::before { display: none; }

/* Status chip (ui_chip; 119, the app's sheets): the capture's «PASOS» chip (CaptureViewController: mono 12, uppercase,
   tracked, a pill with a 5 × 12 inset) in the badge's tones: «Denegada · 1/3 intentos» in --denied on --denied-bg */
.chip {
  display: inline-flex; align-items: center; min-height: 24px; padding: 5px 12px; border-radius: var(--radius-pill);
  font: 500 var(--font-xs)/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
}
.chip-verified { background: var(--verified-bg); color: var(--verified); }
.chip-denied { background: var(--denied-bg); color: var(--denied); }
.chip-pending { background: var(--pending-bg); color: var(--pending); }
.chip-neutral { background: var(--surface-2); color: var(--text-2); }

/* Card (ui_card): 6 px, a border, no heavy shadow; header with title and actions */
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); min-width: 0; margin: 0;
}
.card-h {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-3);
  padding: var(--space-4) 18px; border-bottom: 1px solid var(--border);
}
.card-h h2 { font-size: var(--font-card-title); font-weight: 600; letter-spacing: -.01em; margin: 0; }
.card-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.card-foot { padding: var(--space-3) 18px; border-top: 1px solid var(--border); font-size: var(--font-sm); }
/* A ghost button in the foot keeps its hover box but its text lines up with the cells above (P8) */
.card-foot > .btn-ghost:first-child { margin-left: calc(-1 * var(--space-4)); }
.card-foot > .btn-ghost.btn-sm:first-child { margin-left: calc(-1 * var(--space-3)); }
.card-b { padding: var(--space-4) 18px; }
.card-b > :last-child { margin-bottom: 0; }
.card-flush { padding: 0; }

/* KPI (kpi_card, decision 99) and the row that holds four: icon and label, the figure and, pinned to the bottom
   (margin-top: auto), its chart; the min-height lines the four charts up. Four in a row, two below 1100 px (the
   sidebar is still there), one below 520 px (99.6, replaces the two by two without icon of 98.13). */
.kpis { display: grid; gap: var(--space-4); grid-template-columns: repeat(4, minmax(0, 1fr)); }
.kpi {
  display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-5); min-height: 176px; min-width: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow);
}
.kpi-head { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.kpi-icon {
  width: 32px; height: 32px; flex: none; border-radius: var(--radius-sm); display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-2);
}
.kpi-icon-verified { background: var(--verified-bg); color: var(--verified); }
.kpi-label { font-size: var(--font-sm); color: var(--text-2); }
.kpi-value { font: 700 var(--font-kpi)/1.1 var(--sans); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.kpi-delta { font-size: var(--font-xs); color: var(--muted); }
.kpi-delta strong { color: var(--verified); font-weight: 500; }
.kpi-foot { margin-top: auto; min-width: 0; }
/* kpi_bars: one bar per day on a thin solid baseline (the empty track: a day at 0 draws nothing; a row of 2 px
   stubs read as a broken line, 98.1); a day with any keeps 3 px so it never vanishes */
.kpi-bars { display: flex; align-items: flex-end; gap: 3px; height: 36px; border-bottom: 1px solid var(--border); }
.kpi-bar { flex: 1 1 0; min-height: 3px; background: var(--border); border-radius: var(--radius-xs) var(--radius-xs) 0 0; }
.kpi-bar.is-zero { min-height: 0; }
.kpi-bar.is-last { background: var(--verified); }
/* kpi_ring: 64 px donut from the top, round caps; the figure beside it */
.kpi-ring-row { display: flex; align-items: center; gap: var(--space-4); }
.kpi-ring { width: 64px; height: 64px; flex: none; transform: rotate(-90deg); }
.kpi-ring circle { fill: none; stroke-width: 7; }
.kpi-ring-track { stroke: var(--surface-2); }
.kpi-ring-arc { stroke: var(--verified); stroke-linecap: round; }
/* kpi_split: an 8 px bar split in parts, and its legend */
.kpi-split { display: flex; gap: 2px; height: 8px; border-radius: var(--radius-xs); overflow: hidden; background: var(--surface-2); }
.kpi-seg { flex: 0 1 0; min-width: 4px; }
.kpi-legend {
  display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); margin: var(--space-2) 0 0; padding: 0; list-style: none;
  font-size: var(--font-xs); color: var(--muted);
}
.kpi-legend li { display: flex; align-items: center; gap: 5px; }
.kpi-legend i { width: 8px; height: 8px; flex: none; border-radius: var(--radius-xs); }
.kpi-tone-accent { background: var(--accent); }
.kpi-tone-quiet { background: var(--border); }
.kpi-tone-verified { background: var(--verified); }
.kpi-tone-verified-soft { background: color-mix(in srgb, var(--verified) 40%, var(--surface)); }
@media (max-width: 1100px) { .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) {
  .kpis { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .kpi { min-height: 0; padding: var(--space-4); }
}

/* Table (ui_table / tbl_cell: .tbl inside .tbl-fit inside .tbl-wrap, usually in a flush card). When the card is
   narrower than the table's columns need, each row stacks as a block with the header of each cell in its data-label,
   so nothing scrolls sideways; the explicit ARIA roles keep it a table for screen readers when its display changes,
   and the header row is hidden only visually. */
/* position: relative: the table's .visually-hidden spans (absolute) stay inside its scroll box; without it they hung off the
   page and gave it a horizontal scroll at 761–1100 px (98.4) */
.tbl-wrap { overflow-x: auto; position: relative; container: tbl / inline-size; }
/* 103.5: stacked by the card's width, not the window's (at 761–1279 px the sidebar leaves 455–973 px, and the seven
   columns of certifications_table need about 950 at their narrowest): the card (.tbl-wrap) names .tbl-fit «tbl-stack»
   below what the table needs, and the stacked rules below apply inside a «tbl-stack». Below 680 px of card any table
   (Productos, Enlaces para grabar, Tokens de la API: at most ~600 px); wide (ui_table(wide: true), the seven columns of
   certifications_table), below 940. The chain keeps one copy of the stacked rules for both thresholds. */
.tbl-fit { container-type: inline-size; }
@container tbl (max-width: 679.98px) { .tbl-fit { container-name: tbl-stack; } }
@container tbl (max-width: 939.98px) { .tbl-fit-wide { container-name: tbl-stack; } }
.tbl { width: 100%; border-collapse: collapse; font-size: var(--font-sm); }
/* A header wraps between its words only when its column would not fit otherwise («Enlace certificación» over «Ver»;
   103.5) */
.tbl th {
  text-align: left; font-weight: 500; font-size: var(--font-xs); color: var(--muted);
  padding: 10px 12px; border-bottom: 1px solid var(--border);
}
.tbl td { padding: 10px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
/* 12 px between columns, 18 px at the card's edges (98.6: seven columns fit at 1280 without squeezing a cell) */
.tbl th:first-child, .tbl td:first-child { padding-left: 18px; }
.tbl th:last-child, .tbl td:last-child { padding-right: 18px; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--row-hover); }
.tbl .nowrap { white-space: nowrap; }
.tbl .sub { display: block; color: var(--muted); font-size: var(--font-xs); }
.cell-product { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* A cell of one line (cell_lines, product_cell; 98.6, 101): the datum and, only for a product, its grey label below,
   each ending in an ellipsis past --cell-max (the text stays whole in the DOM and in the title) */
.cell-lines { display: grid; min-width: 0; max-width: var(--cell-max, 12rem); }
/* 103.5: a line that may end in «…» takes its whole text while the table fits and yields to the ellipsis first when it
   does not (its track has no minimum: «Comprobación de Watchtower» in «Detalle» gave the table 30 px more); a fixed
   one never (its date, its WT- id) */
.cell-lines:not(.cell-lines-fixed, .cell-lines-fixed-main) { grid-template-columns: minmax(0, auto); }
/* The clip box grows by the focus ring (2 px + 2 px offset, 97.20) with an equal negative margin, so a link inside
   a line («Qué publico», a product) keeps its whole ring (review Astra P2) */
.cell-lines > * {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  --ring-room: calc(var(--focus-ring) + var(--focus-offset)); padding: var(--ring-room); margin: calc(-1 * var(--ring-room));
}
/* Fixed-length lines (a date, «hasta 25/09/2027»): never cut; one line each while the table fits, and one that does
   not wraps only around its .cell-unit, so the date stays whole («Enlace caducado el» / «24/09/2026 12:28 UTC»):
   stacked since 103.3, in the table too since 103.5 (at 1280 px it was 259 px of «Detalle» and the table scrolled) */
.cell-lines-fixed { max-width: none; }
.cell-lines .sub { font-family: var(--sans); }
.cell-lines-fixed > * { overflow: visible; white-space: normal; }
.cell-lines-fixed-main > .cell-main { overflow: visible; white-space: nowrap; }
/* The part of a fixed line that never breaks (a date and its time; 103.3) */
.cell-unit { white-space: nowrap; }
/* A small action after a cell's text, on its line (with_cell_action: «Reemitir» after an expired link's date). */
.cell-with-action { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.cell-action { margin: 0; flex: none; }
/* A short grey word after the datum, on its line («caducado» after a date; 101) */
.cell-flag { color: var(--muted); font: 400 var(--font-xs) var(--sans); margin-left: var(--space-1); }
/* «Uso» (usage_lines; 101): each count after its icon, on one line */
.usage { display: inline-flex; align-items: center; gap: var(--space-3); white-space: nowrap; }
.usage-item { display: inline-flex; align-items: center; gap: 4px; }
.cell-product .cell-lines { --cell-max: 12rem; }
/* Wide screens: the product column keeps room for a reference, not one word per line (U9); stacked, none */
.tbl .cell-product { min-width: 12rem; }
@container tbl-stack (min-width: 0px) {
  .tbl thead { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); }
  .tbl, .tbl tbody, .tbl tbody tr, .tbl td { display: block; width: 100%; }
  .tbl tr { padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
  .tbl tbody tr:last-child { border-bottom: 0; }
  .tbl td { display: flex; gap: var(--space-3); justify-content: space-between; align-items: baseline; padding: 4px var(--space-4); border: 0; text-align: right; }
  .tbl td > * { min-width: 0; }
  .tbl td[data-label]::before { content: attr(data-label); color: var(--muted); font: 400 var(--font-xs) var(--sans); text-align: left; flex: none; }
  .tbl .cell-product { justify-content: flex-end; text-align: right; min-width: 0; }
  /* 98.6: stacked, a cell's two lines go side by side (one line when they fit) */
  .tbl .cell-lines { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: baseline; column-gap: var(--space-2); max-width: 100%; }
  /* Each line's box is its text plus the ring room on both sides (its negative margin): capped at 100 %, a fixed line
     (a date in «Pedida») overflowed its cell by that room at 320–375 px (102.4) */
  .tbl .cell-lines > * { max-width: calc(100% + 2 * var(--ring-room)); }
  /* A fixed line that does not fit («Enlace caducado el 24/09/2026 12:28 UTC», 56 px over at 320) wraps, only around its
     .cell-unit, so the date stays whole and inside the card (103.3; out of the stack too since 103.5, above) */
  .tbl .cell-lines-fixed-main > .cell-main { white-space: normal; }
  /* The lines' negative margin (ring room) makes their content 8 px narrower than their text, so a short one («BM-88214 ·
     #88214») ended in «…» with room to spare: the cell takes the row's free width instead (98.19, P5) */
  .tbl td > .cell-lines, .tbl td > .cell-product, .tbl .cell-product > .cell-lines { flex: 1 1 auto; }
  .tbl .vp-cell { justify-content: flex-end; }
  /* 98.15: an empty cell (tbl_cell without content, «—») is no line of its own; hidden only visually, so it keeps
     its column's position for screen readers (review Astra P4) */
  .tbl td.cell-empty { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* Field (ui_field), inputs and selects */
.field { display: grid; gap: 6px; margin: 0; min-width: 0; }
.field > label, .seg-field > legend { font-size: var(--font-xs); font-weight: 500; color: var(--text-2); }
.field-optional { color: var(--muted); font-weight: 400; }
.field-hint { font-size: var(--font-xs); color: var(--muted); margin: 0; }
.input, .select {
  font: var(--font-ui)/1.3 var(--sans); color: var(--text); background: var(--surface);
  min-height: var(--control-h); padding: 0 var(--space-3); width: 100%; max-width: 100%;
  border: 1px solid var(--control-border); border-radius: var(--radius-sm);
}
@media (max-width: 760px) { .input, .select { font-size: var(--font-body); } }

/* Segmented control: links (segmented) or radios in a form (segmented_radios) */
/* As wide as its options (102.4): in a grid or a form's fieldset it would stretch to the row, its options crowded at the start */
.seg {
  display: inline-flex; flex-wrap: wrap; padding: 3px; gap: 3px; border-radius: var(--radius-sm); background: var(--surface-2);
  width: fit-content; max-width: 100%;
}
.seg-item {
  display: inline-flex; align-items: center; min-height: var(--btn-h-sm); padding: 0 var(--space-3);
  border-radius: 1px; /* concentric with .seg: 4 px − 3 px padding */ font: 500 var(--font-sm)/1.2 var(--sans); color: var(--text-2);
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.seg-item:hover { color: var(--text); }
/* 100.1: how many rows an option keeps, a small pill after its label; inverted (the primary button's ink) when active */
.seg-item:has(.seg-count) { gap: 6px; }
.seg-count {
  display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 18px; padding: 0 6px;
  border-radius: var(--radius-pill); background: var(--border); color: var(--text-2);
  font: 600 var(--font-xs)/1 var(--sans); font-variant-numeric: tabular-nums;
}
.seg-item.is-active .seg-count { background: var(--accent); color: var(--accent-ink); }
/* 103.4: a list without a filter says its count in the same pill, after its title (table_card(count:)) */
.card-title-count { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* 98.13: on a phone the options go in even columns instead of a ragged wrap (one left alone on the second line) */
@media (max-width: 480px) {
  .seg { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); width: 100%; }
  .seg-item { justify-content: center; }
  .seg:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); } /* 2 + 2, never 3 + 1 */
  .card-actions:has(> .seg) { flex: 1 1 100%; }
}
.seg-item.is-active, .seg-item:has(input:checked) { background: var(--seg-active); color: var(--text); box-shadow: var(--shadow-raised); }
.seg-item input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.seg-item:has(input:focus-visible) { outline: var(--focus-ring) solid var(--focus); outline-offset: var(--focus-offset); }
.seg-field { border: 0; padding: 0; margin: 0; display: grid; gap: 6px; min-width: 0; }
.seg-field > legend { padding: 0; margin-bottom: 6px; }

/* Drawer (drawer): a <dialog> from the right over a scrim */
.drawer {
  position: fixed; inset: var(--space-3) var(--space-3) var(--space-3) auto; margin: 0; padding: 0; border: 0;
  width: var(--drawer-width); max-width: calc(100% - 2 * var(--space-3)); height: auto; max-height: none;
  background: var(--surface); color: var(--text); border-radius: var(--radius-lg); box-shadow: var(--shadow-drawer);
  z-index: 30; overflow: auto;
}
.drawer[open] { display: flex; flex-direction: column; }
.drawer::backdrop { background: var(--scrim); }
/* Open without JavaScript (non-modal): a panel in the page's flow, not an overlay (97.7). */
.drawer[open]:not(:modal) {
  position: static; inset: auto; width: 100%; max-width: 100%; box-shadow: none; border: 1px solid var(--border); z-index: auto;
}
.drawer-h {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4) 18px; border-bottom: 1px solid var(--border);
}
.drawer-h h2 { font-size: var(--font-card-title); margin: 0; }
.drawer-b { padding: var(--space-4) 18px; display: grid; gap: 14px; align-content: start; flex: 1; }
.drawer-b form { display: grid; gap: 14px; margin: 0; }
.drawer-footer {
  display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--space-2);
  padding-top: 14px; border-top: 1px solid var(--border);
}

/* A form of stacked fields (certification_requests/_form) and its buttons outside a drawer */
.form-stack { display: grid; gap: 14px; margin: 0; }
.form-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* The link to a certification's page (/v/) in a table */
.view-link { display: inline-flex; align-items: center; gap: 6px; }

/* A secret shown once (link code, API token): the value to copy and its button */
.secret { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.secret-value {
  font-size: var(--font-sm); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  background: var(--surface-2); overflow-wrap: anywhere; min-width: 0; max-width: 100%;
}
.notice-inline { color: var(--pending); }
/* A checkbox with its text. No sticky save bar: it would hide the focused checkbox under it (review U6). */
.check { display: inline-flex; align-items: center; gap: var(--space-2); }
.wrap-anywhere { overflow-wrap: anywhere; }

/* Pages of a long list (CertificationsController) */
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--space-3); }

/* A certification in a list (the product's page): WT- id and badge, its meta, steps, page and password */

/* Placeholder (placeholder): «Próximamente» once, in its pill (98.22), a tinted inset with a thin solid edge, never a broken line (98.3) */
.ph {
  display: grid; gap: 6px; justify-items: start; padding: var(--space-4);
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--ph-bg); color: var(--muted);
  font-size: var(--font-sm);
}
.ph-title { color: var(--text-2); font-weight: 500; font-size: var(--font-ui); }
.ph-text { margin: 0; }
.ph-compact { padding: var(--space-3); }

/* Empty state (empty_state) */
.empty { padding: var(--space-5) var(--space-4); text-align: center; color: var(--muted); display: grid; gap: var(--space-3); justify-items: center; }
.empty p { margin: 0; }

/* Page header (page_header): crumb, h1, search placeholder and actions */
.page-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-4); }
.page-heading { min-width: 0; }
.crumb { font-size: var(--font-xs); color: var(--muted); margin: 0 0 2px; }
.page-header h1 { font-size: var(--font-page-title); letter-spacing: -.02em; font-weight: 600; margin: 0; }
.page-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.search-ph {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--btn-h); padding: 0 var(--space-3);
  width: 16rem; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface);
  color: var(--muted); font-size: var(--font-sm);
}
@media (max-width: 1100px) { .search-ph { display: none; } }

/* App icon (app_icon, decision 108): the brand's mark on the navy rounded square of the iOS icon; the seal in its
   green with a navy gap and a white tick in both themes, as on the home screen */
.app-icon {
  width: 128px; height: 128px; flex: none; display: grid; place-items: center;
  border-radius: var(--radius-icon); background: var(--hero); color: var(--hero-ink); box-shadow: var(--shadow-icon);
}
.app-icon svg { width: 84px; height: 84px; }
.app-icon .brand-seal { fill: var(--seal); stroke: var(--hero); }
.app-icon .brand-tick { stroke: var(--hero-ink); }

/* Compact list of certifications (certification_list, 108.3; shown by layout.css on Inicio below 760 px): one link
   per row, the product and its WT- id below in grey, the status badge on the right. Also the app's screen (/app,
   decision 111), at any width: its rows link to the capture. */
.cert-list { list-style: none; margin: 0; padding: 0; }
.cert-list > li + li { border-top: 1px solid var(--border); }
.cert-row {
  display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4); min-width: 0;
  color: var(--text); text-decoration: none;
}
.cert-row:hover { background: var(--row-hover); color: var(--text); }
div.cert-row:hover { background: none; } /* a row with no link (111.10: «Grabadas» with no page /v/ yet) */
.cert-row-hint { color: var(--link); font-weight: 600; } /* 111.10: «Ver certificado», the row's link */
.cert-row-text { display: grid; gap: 2px; flex: 1; min-width: 0; }
.cert-row-title { font: 500 var(--font-body)/1.3 var(--sans); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cert-row-sub { font-size: var(--font-sm); font-weight: 400; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cert-row .badge { flex: none; }

/* Sidebar item (nav_item) */
.nav-item {
  display: flex; align-items: center; gap: 10px; min-height: var(--btn-h); padding: 0 14px;
  border-radius: var(--radius-sm); text-decoration: none; color: var(--nav-ink); font-weight: 500; min-width: 0;
}
.nav-item .icon { opacity: .85; }
.nav-item:hover { background: var(--nav-hover); }
.nav-item.is-active { background: var(--nav-active-bg); color: var(--nav-active-ink); }
.nav-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-soon { margin-left: auto; flex: none; white-space: nowrap; font-size: 11px; color: var(--text-2); } /* the label ellipsizes, «pronto» never breaks (U9) */

/* The /v/ of a certification in a row (view_page_cell; 101, 101.8): «Ver» and a grey «caducada», on one line */
.vp-cell { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--space-2); min-width: 0; max-width: 100%; }
.vp-flag { color: var(--muted); font-size: var(--font-xs); white-space: nowrap; }
/* «Acceso» (access_cell; 101.8–101.11): «Pública» or «Privada» in grey, or the password (view_password), always whole:
   one button that copies it (the toast says so; the row does not change) */
.access-flag { color: var(--muted); font-size: var(--font-xs); white-space: nowrap; }
.pw-mask { width: auto; max-width: 100%; padding: 0 var(--space-2); font-size: var(--font-sm); letter-spacing: .03em; text-align: left; }
/* A long password of the seller (up to 72 characters, from before 101.10) breaks anywhere within 11rem: the column never widens */
.pw-full { display: block; overflow-wrap: anywhere; white-space: normal; max-width: 11rem; min-width: 0; }
/* The dashboard's one toast (#toast, layouts/dashboard; 101.11): fixed at the bottom centre, over everything,
   shown for 2 s by application.js; transparent and empty otherwise, so its live region is always there to speak */
.toast {
  position: fixed; left: 50%; bottom: var(--space-5); z-index: 100; transform: translateX(-50%);
  max-width: calc(100vw - 2 * var(--space-4)); padding: var(--space-2) var(--space-4); border-radius: var(--radius-sm);
  background: var(--text); color: var(--surface); font-size: var(--font-sm); box-shadow: var(--shadow-drawer);
  opacity: 0; pointer-events: none; transition: opacity .15s ease;
}
.toast.is-shown { opacity: 1; }
.pw-label { font-size: var(--font-xs); color: var(--muted); } /* «Contraseña de la página» in «Qué publico» */

/* Verification steps (progress_steps) */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }
.step {
  display: grid; gap: 2px; padding: 10px var(--space-3); border-radius: var(--radius-md);
  background: var(--surface-2); color: var(--text-2); font-size: var(--font-xs);
}
.step-label { font-size: var(--font-sm); font-weight: 500; }
.step-done { background: var(--verified-bg); color: var(--verified); }
.step-current { background: var(--pending-bg); color: var(--pending); }

/* Definition rows (meta of a certification or an account) */
.meta { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) 14px; margin: 0; font-size: var(--font-sm); }
.meta dt { color: var(--muted); }
.meta dd { margin: 0; min-width: 0; }

/* Styleguide (/dashboard/design) */
.sg { display: grid; gap: var(--space-5); }
.sg-row { display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.sg-row > h3 { font-size: var(--font-xs); font-weight: 500; color: var(--muted); margin: 4px 0 0; }
.sg-flex { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.sg-chips { margin-top: var(--space-3); }
/* A note under a sample (102.4: the badges of «Estados» touched it) */
.sg-note { margin: var(--space-2) 0 0; }
.swatches { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); margin: 0; padding: 0; list-style: none; }
.swatch { border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; background: var(--surface); }
.swatch-chip { height: 48px; border-bottom: 1px solid var(--border); }
.swatch-name { display: grid; gap: 2px; padding: var(--space-2) 10px; font-size: var(--font-xs); }
.swatch-name code { background: none; padding: 0; font-size: 11px; color: var(--muted); }
@media (max-width: 760px) { .sg-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); } }
