/* Clever Checker feature-component styles, split from styles.css to hold the
   <1000-line file rule. Loaded immediately AFTER styles.css (base.html) so
   the cascade is byte-identical to the single sheet it came from. Covers the
   batch table, upload, error pages and the recent-checks list. */

/* ---------- batch: the sorted table (ROADMAP §3.6a) ----------
   Not a grid of dials. The dial answers "how confident on this one", which is
   the wrong question thirty times over; the question here is "which do I read
   first", and the only honest instrument for that is a ranked list you can scan
   without moving your eyes off a column.

   Note what has NO colour ramp: the confidence column is the same amber at 4% as
   at 96%, exactly like the dial (see note 1 at the top of this file). A table
   that turned rows red at the top would be a binary verdict rendered as a
   heatmap, and rendering one is what COMPLIANCE §2 forbids. Only the number and
   the bar length move. */
.batch, .batch-new {
  background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 22px; margin-top: 20px;
}
.batch h1, .batch-new h1 {
  font-size: 27px; line-height: 1.15; letter-spacing: -.035em;
  margin: 0 0 10px; font-weight: 800; text-wrap: balance;
}
.batch .sub, .batch-new .sub { color: var(--ink-2); margin: 0 0 18px; }
.batch-new code {
  font-family: var(--mono); background: var(--surface-3); color: var(--ink);
  border: 1px solid var(--line-2); border-radius: 4px; padding: 1px 6px;
  font-size: .9em;
}

/* The warning. Amber-bordered and full-width because it is not an aside in the
   editorial sense: it is the condition on which the table below it may be used.
   It sits ABOVE the table for the same reason the billing disclosure sits above
   the pay button (COMPLIANCE §1.1): after the fact is not disclosure. */
.warn {
  background: var(--surface-2); border: 1px solid var(--amber);
  border-left: 3px solid var(--ink); border-radius: var(--r-md);
  padding: 16px 18px; margin: 0 0 22px;
}
.warn h2 {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink);
  margin: 0 0 8px;
}
.warn p { color: var(--ink-2); font-size: 14.5px; line-height: 1.6; margin: 0 0 8px; }
.warn p:last-child { margin-bottom: 0; }
.warn strong { color: var(--ink); }

/* A table on a phone is the hard case, and the honest answer is that it should
   not be a table there. At 320px a five-column table gives you two bad options:
   scroll it sideways, in which case the names scroll away from the scores (a
   ranked list of anonymous numbers, which is worse than no table), or crush every
   column to two characters. So, phone-first like the rest of this file: each
   document is a CARD that needs no scrolling and keeps the name and its score in
   the same eyeline, which is the only pairing on this screen that matters. The
   table reappears at 760px, where it fits and is genuinely better to scan.

   The <table> MARKUP stays at every width. The data is tabular, a screen reader
   should hear it announced that way, and `display` doesn't change that. This is
   a layout choice, not a semantic one. */
/* `position: relative` is load-bearing, not habit: the .sr-only span inside this
   table is absolutely positioned, and without a positioned ancestor it resolves
   against the initial containing block, escapes this box, and drags the whole
   PAGE out to the table's full width. Measured: 605px of body on a 320px
   viewport. overflow-x is the safety net for the table layout at >=760px; the
   phone layout is cards and has nothing to scroll. */
.table-wrap { position: relative; overflow-x: auto; }
.batch-table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.batch-table thead { display: none; }
.batch-table tbody, .batch-table tr, .batch-table td, .batch-table th { display: block; }
.batch-table tbody tr {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "seq label open" "seq score flag";
  gap: 8px 10px; align-items: center;
  padding: 14px 2px; border-bottom: 1px solid var(--line);
}
.batch-table tbody tr:last-child { border-bottom: 0; }
.batch-table th, .batch-table td { text-align: left; }
.col-seq   { grid-area: seq; }
.col-label { grid-area: label; }
.col-score { grid-area: score; }
.col-flag  { grid-area: flag; }
.col-open  { grid-area: open; }
/* The column header is hidden in this layout, so the number has to say what it
   counts. Without it "1 / 3" next to a percentage is just a second mystery score. */
.col-flag::after { content: " flagged"; }

.col-seq {
  font-family: var(--mono); color: var(--ink-3); font-size: 12.5px;
  white-space: nowrap;
}
.col-label { font-weight: 500; color: var(--ink); overflow-wrap: anywhere; }
.col-score { display: flex; align-items: center; gap: 10px; }
.col-score .pct {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  color: var(--ink); font-size: 13.5px;
}
.minibar {
  flex: 1; min-width: 60px; height: 5px; border-radius: 1px;
  background: var(--line-2); overflow: hidden;
}
.minibar i { display: block; height: 100%; background: var(--amber); }
.col-flag {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  color: var(--ink-2); font-size: 13px; white-space: nowrap;
}
/* Nothing flagged: recede it. The eye should be pulled by the rows that have
   something in them, and never by colour standing in for a verdict. */
.col-flag.is-zero { color: var(--ink-3); }

/* Wide enough for the real thing. Five columns, scannable down each one, which
   is the point of a table and the reason it comes back the moment it fits. */
@media (min-width: 760px) {
  .batch-table thead { display: table-header-group; }
  .batch-table tbody { display: table-row-group; }
  .batch-table td, .batch-table th { display: table-cell; }
  /* The header row needs restoring too, and forgetting it is worse than it
     sounds: table-cells inside a display:block row get wrapped in an ANONYMOUS
     table of their own, so the headers silently size to their own columns and
     stop lining up with the data underneath. A table whose headings point at the
     wrong columns is a mislabelled score. */
  .batch-table thead tr { display: table-row; }
  /* Selector matched to the phone rule character for character, on purpose. A
     media query adds NO specificity, so a tidier `.batch-table tr` here (0,1,1)
     silently loses to `.batch-table tbody tr` above (0,1,2): the rows stayed grid
     at every width and the cells rendered stacked on top of one another. And the
     areas must be cleared explicitly, since display:table-row does not undo them. */
  .batch-table tbody tr {
    display: table-row; grid-template-areas: none; grid-template-columns: none;
    gap: 0; padding: 0; border-bottom: 0;
  }
  .batch-table th, .batch-table td {
    padding: 12px 10px; border-bottom: 1px solid var(--line); vertical-align: middle;
  }
  .batch-table tbody tr:last-child th, .batch-table tbody tr:last-child td {
    border-bottom: 0;
  }
  .batch-table thead th {
    font-family: var(--mono); font-size: 11px; font-weight: 500;
    letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
    border-bottom: 1px solid var(--line-3); white-space: nowrap;
  }
  .batch-table tbody tr:hover { background: var(--surface-2); }
  .col-flag::after { content: none; }
  .col-seq { width: 1%; }
  .col-label { min-width: 150px; max-width: 340px; }
  .col-score { width: 34%; min-width: 150px; display: table-cell; }
  /* Back to a table cell, so the flex sizing above stops applying and the bar
     can be a plain inline box next to its number again. */
  .col-score .minibar { display: inline-block; width: calc(100% - 52px); }
  .col-score .pct { margin-left: 10px; }
}

.batch-new .upsell {
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-radius: var(--r-md); padding: 18px;
}
.batch-new .upsell p { color: var(--ink-2); margin: 0 0 12px; }
.batch-new .upsell p:last-child { margin-bottom: 0; }

/* Present for screen readers, absent for everyone else. The Open column's header
   would otherwise be an empty th, which a screen reader announces as nothing. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media print {
  .warn { border-color: #000; background: #fff; }
  .warn h2, .warn p, .warn strong { color: #000; }
  .batch { border: 0; background: #fff; }
  .batch-table th, .batch-table td, .col-seq, .col-flag, .col-score .pct { color: #000; }
}

/* ---------- upload (§3.6b) ----------
   A <label> wrapping a hidden <input type=file>, which is what makes the whole
   panel clickable while the control stays a real file input: keyboard reachable,
   announced properly, and working with JS off. A <div onclick> would look the
   same and be none of those things. */
.dropzone {
  display: block; text-align: center; cursor: pointer;
  background: var(--surface-2); border: 1px dashed var(--line-3);
  border-radius: var(--r); padding: 22px 18px; margin: 0 0 14px;
  transition: border-color .15s ease, background .15s ease;
}
.dropzone:hover, .dropzone.is-over { border-color: var(--ink); background: var(--surface-3); }
.dropzone.has-files { border-style: solid; border-color: var(--amber); }
/* The input is hidden, so the ring has to be drawn by its label or the control
   is invisible to anyone tabbing through the page. */
.dropzone:focus-within { outline: 2px solid var(--ink); outline-offset: 2px; }
.dz-main { display: block; font-size: 15px; color: var(--ink); }
.dz-main u { text-decoration-color: var(--ink); text-underline-offset: 3px; }
.dz-sub {
  /* 11.5px, not 12.5: at 320px this box has about 200px of room, and the line
     has to hold on one. Still above the 11px the section labels use. */
  display: block; margin-top: 5px; font-size: 11.5px; color: var(--ink-3);
  font-family: var(--mono);
}
.dz-picked {
  display: block; margin-top: 10px; font-size: 12.5px; color: var(--ink);
  font-family: var(--mono); overflow-wrap: anywhere;
}
/* The "or" divider, with rules either side. */
.or {
  display: flex; align-items: center; gap: 12px; margin: 0 0 14px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-3);
}
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--line-2); }

/* ---------- error pages ----------
   Same panel as the report, because an error is not a different product: it is
   this product, on a bad day, and a visitor who has just paid should not feel
   like they fell out of the site. */
.error-page {
  background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 22px; margin-top: 20px;
}
.error-page h1 {
  font-size: 27px; line-height: 1.15; letter-spacing: -.035em;
  margin: 0 0 10px; font-weight: 800; text-wrap: balance;
}
.error-page .sub { color: var(--ink-2); margin: 0 0 14px; }
.error-page p { color: var(--ink-2); }
.error-page strong { color: var(--ink); }

/* ---------- recent checks (the retention window, made usable) ---------- */
.account.recent { margin-top: 16px; }
.account.recent h2 {
  font-size: 18px; letter-spacing: -.02em; margin: 0 0 6px; font-weight: 700;
}
.checks { list-style: none; padding: 0; margin: 14px 0 12px; }
.checks li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 12px; align-items: center;
  padding: 11px 2px; border-bottom: 1px solid var(--line);
}
.checks li:last-child { border-bottom: 0; }
/* One line per row, always. The label is the visitor's own first line, so its
   length is not ours to control: clipping it keeps the rows uniform and scannable
   and keeps the no-wrap rule true on a page whose content we don't write. The
   server already cuts it to a heading's worth (batch.label_for). */
.checks a {
  color: var(--ink); text-decoration: none;
  display: block; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.checks a:hover { text-decoration: underline; text-decoration-color: var(--ink); }
/* Same amber at every score, for the same reason as the dial and the batch
   table: a list that reddens at the top is a verdict rendered as a heatmap. */
.checks .pct {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  color: var(--ink); font-size: 13px;
}
.checks .when {
  font-family: var(--mono); color: var(--ink-3); font-size: 12px; white-space: nowrap;
}
@media (max-width: 420px) {
  /* The date is the first thing worth losing: the order already says "recent". */
  .checks .when { display: none; }
}

/* ---------- pricing plan selector (/pricing) ----------
   JustDone-style: three selectable plan cards (radios styled as cards), the billing
   disclosure adjacent to the button, an un-ticked consent box, then Start trial. */
.trial-head { text-align: center; max-width: 660px; margin: 0 auto 26px; }
.trial-head h1 { font-size: clamp(26px, 5.5vw, 36px); letter-spacing: -.02em; margin: 0 0 8px; text-wrap: balance; }
.trial-sub { color: var(--ink-2); margin: 0 0 16px; }
.trust-badges { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 9px; justify-content: center; }
.trust-badges li {
  display: inline-flex; align-items: center; gap: 7px; padding: 8px 13px;
  border: 1px solid var(--line-3); border-radius: 999px; font-size: 13px; color: var(--ink-2);
}
.trust-badges svg { color: var(--accent-ink); flex: none; }

/* One row per plan, each with its own Select button. The most-popular row is
   accent-bordered with a flag tab. */
.plan-rows { display: grid; gap: 12px; max-width: 680px; margin: 0 auto; }
.plan-row {
  position: relative; display: flex; align-items: center; gap: 14px;
  padding: 20px 22px; border: 1.5px solid var(--line-3); border-radius: var(--r);
  background: var(--surface-1);
}
.plan-row.popular { border-color: var(--ink); box-shadow: var(--shadow-pop); }
.plan-flag {
  position: absolute; top: -11px; left: 18px; background: var(--amber); color: var(--on-amber);
  font: 700 10px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  padding: 5px 9px; border-radius: 6px;
}
.plan-name { font-size: 22px; font-weight: 800; letter-spacing: -.02em; }
.plan-right { margin-left: auto; display: flex; align-items: center; gap: 16px; }
.plan-price { text-align: right; }
.plan-today { display: block; font-size: 15px; color: var(--ink-3); white-space: nowrap; }
.plan-today b { font-size: 19px; color: var(--ink); font-weight: 800; }
.plan-mo { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 3px; white-space: nowrap; }
.plan-mo s { text-decoration: line-through; }
.plan-tag { font: 600 10px/1 var(--mono); letter-spacing: .04em; text-transform: uppercase; padding: 3px 6px; border-radius: 5px; font-style: normal; }
.plan-tag.save { color: var(--ok); background: color-mix(in srgb, var(--ok) 15%, transparent); }
/* The alternative plans: same pill, no lane colour and no star. Outlined rather
   than filled, so it reads as "also available" and never as disabled. Every row is
   still entirely clickable; this is emphasis, not permission.
   The asymmetric padding is on ALL of them, and the star's own box is reserved
   below, so every Select is the same width whether it carries the star or not and
   the three labels line up down the column. */
.btn-select {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  background: var(--surface-1); color: var(--ink); border: 1px solid var(--line-3);
  height: var(--cta-h); padding: 0 22px 0 17px; border-radius: var(--cta-r);
  font-weight: 700; font-size: 15px; text-decoration: none;
}
/* The alternatives carry the hollow star, which is what holds their pills to the
   same width as the recommended one: it is the same path in the same box, so the
   two variants are identical geometry and no spacer or min-width is needed. The
   dimming lives with the star itself (styles.css), so Start wears it identically. */
/* Step TWO of the critical path, on the recommended plan only: the header's Try
   pill again, same lane colour, same leading star. Colour ONLY. Padding stays on
   the rule above, or this selector (0,3,0) would outrank the mobile block's
   .btn-select (0,1,0) and keep the desktop padding on the one plan that matters
   at 320px, since a media query adds no specificity of its own. */
.plan-row.popular .btn-select {
  background: var(--lane); color: var(--lane-ink); border-color: var(--lane);
}
.btn-select:hover { text-decoration: none; filter: brightness(1.08); }
/* The whole row IS the link now (see pricing.html); the Select control is a visual
   button inside it. So a click anywhere on the row selects, reliably. */
.plan-row { text-decoration: none; color: inherit; cursor: pointer; transition: border-color .12s ease; }
.plan-row:hover { border-color: var(--ink); }
/* brightness() alone is invisible on the outlined variant (white stays white), so
   the neutral pill answers a hover with its border and the filled one with its fill. */
.plan-row:hover .btn-select { filter: brightness(1.08); border-color: var(--ink); }
.plan-row.popular:hover .btn-select { border-color: var(--lane); }
/* "Everything": the heading holds ONE line at every width (clamped so it never
   wraps to two), then every tool itemised by category plus the platform extras. */
/* .band h2.everything-h2, not just .everything-h2: the base .band h2 rule is
   specificity (0,1,1) and would otherwise win, keeping its larger clamp and
   letting the heading wrap. This (0,1,2) beats it, so nowrap + the smaller clamp
   actually apply and the heading holds one line down to 320px. */
.band h2.everything-h2 {
  white-space: nowrap; font-size: clamp(14px, 4.2vw, 26px);
  letter-spacing: -.03em; margin: 0 0 28px; font-weight: 800; text-align: center;
}
/* "Everything" keeps the ink of the heading and wears the logo's hand-drawn accent:
   a rounded amber underline UNDER the word, never amber text. Amber is the glow in
   this palette, so it carries the mark and not the letters (make_logo.py does the
   same under "Check"). The bar is a pseudo-element so it rides under the whole word
   at any clamp size; position:relative scopes it. */
.ev-accent {
  position: relative; color: inherit; white-space: nowrap;
  padding-bottom: 3px;
}
.ev-accent::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 3px; border-radius: 999px; background: var(--amber);
}
/* The readout hedge on the home page, sitting above the "Next step" cross-sell:
   centered and muted, with room above so it reads as a caption on the score rather
   than a heading, and clear of the readout panel it qualifies. */
.score-note {
  max-width: 640px; margin: 30px auto 6px; text-align: center;
  font-size: 13px; color: var(--ink-3); line-height: 1.5;
}
.every-grid { display: grid; gap: 8px 26px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.every-col { min-width: 0; }
.every-cat {
  font: 500 10px/1.5 var(--mono); letter-spacing: .13em; text-transform: uppercase;
  color: var(--accent-ink); margin: 16px 0 6px;
}
.feature-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 9px; }
.feature-list li { display: flex; gap: 10px; align-items: flex-start; color: var(--ink-2); font-size: 14px; line-height: 1.4; }
.feat-check { flex: none; margin-top: 2px; color: var(--accent-ink); }
/* Mobile: shrink the plan-row text, then re-columnise it. Name + price + Select
   want 332px on one line inside a 265px column at 320px (measured), so they cannot
   all sit side by side and the row used to break the Select pill onto a line of its
   own, under the name. That read as two rows.
   Instead the row becomes a two-column grid: the name and the price stack in the
   text column and the Select pill sits beside them, vertically centred and at a
   full, tappable size. The pill is a grid item in its own right, so .plan-right
   goes display:contents and stops being a box; the whole row is still the link, so
   this changes the shape and not the behaviour. */
@media (max-width: 480px) {
  .plan-row {
    display: grid; grid-template-columns: 1fr auto; align-items: center;
    padding: 15px 14px; column-gap: 12px; row-gap: 3px;
  }
  .plan-name { font-size: 17px; grid-column: 1; grid-row: 1; }
  .plan-right { display: contents; }
  .plan-price { grid-column: 1; grid-row: 2; text-align: left; }
  .plan-today { font-size: 12px; }
  .plan-today b { font-size: 15.5px; }
  .plan-mo { font-size: 10px; margin-top: 2px; }
  .plan-tag { font-size: 8px; padding: 2px 4px; letter-spacing: 0; }
  .btn-select {
    padding: 0 14px 0 11px; font-size: 13.5px; gap: 5px;
    grid-column: 2; grid-row: 1 / span 2; justify-self: end;
  }
}

/* ---------- payment page (/pay/checkout) ----------
   One card: order summary (gray) left, payment (white) right. It sits ON the page
   grid, which on this page runs full height and darkens behind the card and down to
   the footer, so the card and the terms beneath it read as one panel. */
.checkout { padding: 2px 0 44px; position: relative; }
/* Step indicator */
.co-steps {
  list-style: none; display: flex; align-items: center; flex-wrap: wrap;
  justify-content: center; padding: 0; margin: 0 0 18px; font-size: 13.5px; font-weight: 600;
}
.co-steps li { color: var(--ink-3); display: flex; align-items: center; }
.co-steps li::after { content: "\203A"; color: var(--line-3); margin: 0 10px; }
.co-steps li:last-child::after { content: none; }
.co-steps li.done a { color: var(--ink-2); text-decoration: none; }
.co-steps li.done a:hover { color: var(--ink); }
.co-steps li.current { color: var(--ink); }

/* The card. No separate grid box: the page grid behind it does that job now. */
.co-card {
  position: relative; display: grid; border-radius: var(--r-lg); overflow: hidden;
  background: var(--surface-1); box-shadow: var(--shadow-pop);
  border: 1px solid var(--line-2);
}

/* LEFT: gray order-summary side. Collapsible on mobile (a "Show order summary" bar
   with the struck total + due-today), a fixed open panel on desktop. */
.co-side { background: var(--surface-3); border-bottom: 1px solid var(--line-2); }
.co-summary > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center;
  justify-content: space-between; gap: 12px; padding: 16px 18px;
}
.co-summary > summary::-webkit-details-marker { display: none; }
.co-sum-label { font-weight: 700; font-size: 14px; }
.co-sum-label::before { content: "Show order summary"; }
.co-summary[open] .co-sum-label::before { content: "Hide order summary"; }
.co-sum-label::after { content: "\25BE"; color: var(--ink-3); font-size: 10px; margin-left: 7px; }
.co-summary[open] .co-sum-label::after { content: "\25B4"; }
.co-sum-total { text-align: right; line-height: 1.15; }
.co-sum-total s { color: var(--ink-3); font-size: 12.5px; }
.co-sum-total b { color: var(--ink); font-size: 15.5px; margin-left: 6px; }
.co-sum-body { padding: 0 18px 18px; }
.co-lines { margin: 0; }
.co-lines > div { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line-2); font-size: 14px; color: var(--ink-3); }
.co-lines dt, .co-lines dd { margin: 0; }
.co-lines dd { color: var(--ink); font-weight: 600; text-align: right; }
.co-lines .co-due { border-bottom: 0; padding-bottom: 4px; }
.co-lines .co-due dt { color: var(--ink); font-weight: 700; }
.co-lines .co-due dd { color: var(--ink); font-weight: 800; font-size: 15.5px; }
/* The recurring charge, right-aligned under the due-today figure. */
.co-renew { text-align: right; margin: 0; font-size: 13px; font-weight: 400; color: var(--ink-2); }
.co-renew-note { text-align: right; margin: 2px 0 0; font-size: 12px; color: var(--ink-3); }
/* Trial timeline: today / reminder / renewal on a rail. */
.co-tl-title { font-weight: 700; font-size: 14px; margin: 20px 0 8px; }
.co-timeline { list-style: none; padding: 0; margin: 0; }
.co-timeline li { position: relative; padding: 0 0 14px 22px; }
.co-timeline li::before { content: ""; position: absolute; left: 3px; top: 4px; width: 9px; height: 9px; border-radius: 50%; background: var(--ink); }
.co-timeline li::after { content: ""; position: absolute; left: 7px; top: 13px; bottom: 0; width: 1.5px; background: var(--line-3); }
.co-timeline li:last-child { padding-bottom: 0; }
.co-timeline li:last-child::after { content: none; }
.co-timeline b { display: block; font-size: 13.5px; }
.co-timeline span { font-size: 12.5px; color: var(--ink-2); line-height: 1.4; }

/* RIGHT: white pay side. */
.co-pay { background: var(--surface-1); padding: 22px 20px; }
/* Sized to hold "Last Tap To Start Pro" on ONE line inside the 325px column. */
.co-pay h1 { font-size: clamp(18px, 5.2vw, 20px); letter-spacing: -.02em; margin: 0 0 14px; white-space: nowrap; }
/* The Payment Element (Stripe's own cross-origin iframe) renders all its own chrome:
   the wallet buttons, the card fields, the PayPal option. We only give it room. */
#payment-el { min-height: 44px; }
/* stub facade (dev / no key): one plain field standing in for the Element. */
.co-stub-field {
  width: 100%; box-sizing: border-box; height: 44px; padding: 0 14px;
  border: 1px solid var(--line-3); border-radius: 12px; background: var(--surface-1);
  font-size: 15px; color: var(--ink); -webkit-appearance: none; appearance: none;
}
.co-stub-field:focus { outline: none; border-color: var(--ink); }
.co-stub[hidden] { display: none; }
/* The general error (decline, network) is NOT reserved: it only appears AFTER the pay
   click, so it takes its space then rather than sitting empty above the CTA. */
.co-error { color: #b3261e; font-size: 14px; line-height: 1.4; margin: 8px 0 0; }
/* Cap the payment column to a chunky, centred, ChatGPT-login-width column so the Payment
   Element and pay button share one tidy width. Desktop is already 325px, so a no-op. */
.co-pay > * { max-width: 320px; margin-left: auto; margin-right: auto; }
/* The pay button: the PRIMARY submit for the card / PayPal chosen in the Payment Element
   above (the element's own wallet buttons confirm themselves). A filled black CTA
   (--lane), the same black every CTA wears, with the shared swipe (styles.css). */
.co-start {
  width: 100%; max-width: 320px; margin: 14px auto 0;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  height: var(--cta-h); padding: 0 20px; border: 1px solid var(--lane);
  border-radius: var(--cta-r); background: var(--lane); color: var(--lane-ink);
  font: 700 16.5px/1 var(--sans); cursor: pointer;
  transition: box-shadow .15s ease, transform .15s ease;
}
.co-start:hover { box-shadow: inset 0 0 0 999px rgba(255, 255, 255, .14), var(--shadow-md);
  transform: translateY(-1px); }
.co-start:active { transform: translateY(0); box-shadow: none; }
/* Reassurance line under the pay button: the reminder promise plus the cancel note. */
.co-reassure { margin: 10px 0 0; text-align: center; font-size: 13px; color: var(--ink-3); line-height: 1.5; }
/* Billing disclosure below the card. A full paragraph now, so left-aligned in a
   centered measure for readability. */
.co-fine { max-width: 620px; margin: 16px auto 0; text-align: left; font-size: 12px; color: var(--ink-3); line-height: 1.55; }
.co-fine b { color: var(--ink-2); }

/* The page grid on the checkout page: full height (no under-the-fold fade), fuller
   toward the bottom of the view, plus a soft dark wash that deepens to the footer,
   so the card and the terms beneath it sit on a subtly darker panel. */
body.co-page::before {
  opacity: .6;
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,.3) 0, rgba(0,0,0,.3) 10%, #000 55%, #000 100%);
  mask-image: linear-gradient(to bottom, rgba(0,0,0,.3) 0, rgba(0,0,0,.3) 10%, #000 55%, #000 100%);
}
body.co-page::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(to bottom, transparent 30%, color-mix(in srgb, var(--ink) 7%, transparent) 100%);
}

@media (min-width: 820px) {
  /* A compact card, centered: a fixed summary column and a payment column capped so
     the inputs and wallet buttons stay a sensible card width, not stretched across
     the panel. */
  .co-card { grid-template-columns: 340px 325px; width: max-content; max-width: 100%; margin: 0 auto; }
  .co-side { border-bottom: 0; border-right: 1px solid var(--line-2); }
  /* A fixed open panel, no toggle: force the content visible and drop the collapse UI. */
  .co-summary > summary { cursor: default; padding: 30px 28px 4px; }
  .co-sum-label::before,
  .co-summary[open] .co-sum-label::before { content: "Order summary"; }
  .co-sum-label::after, .co-sum-total { display: none; }
  .co-summary::details-content { content-visibility: visible; block-size: auto; }
  .co-sum-body { padding: 6px 28px 30px; }
  .co-pay { padding: 28px 22px; max-width: 325px; }
}

/* --- Browser-extension store badges + footer -------------------------------- */
/* One badge component (app-store style): the browser glyph, then a small "Add to"
   line over the browser name. Rendered by _extension.html's badge() and reused by
   the footer, the sales bands and the Download page, so the look is single-sourced.
   Light pill (surface + hairline) so it sits on the page like the cards, with the
   coloured logo doing the work. */
.storebadge {
  display: inline-flex; align-items: center; gap: 9px; text-decoration: none;
  background: var(--surface-1); color: var(--ink); border: 1px solid var(--line-3);
  border-radius: var(--r); line-height: 1; white-space: nowrap;
  box-shadow: var(--shadow-sm);
}
.storebadge:hover { text-decoration: none; border-color: var(--ink-3); background: var(--surface-2); }
/* The mark is the vendored browser logo (an <img>); block so its box is exact and
   the size rules below (and the Download card's 44px) drive the display size. */
.bmark { display: block; }
.storebadge-mark { display: inline-flex; }
.storebadge-txt { display: inline-flex; flex-direction: column; gap: 2px; text-align: left; }
.storebadge-sm { font-size: 10px; letter-spacing: .02em; color: var(--ink-3); }
.storebadge-lg { font-size: 15px; font-weight: 600; color: var(--ink); }
/* Two sizes: sm for the footer and the in-page bands, lg for the Download cards. */
.storebadge.storebadge-sm { padding: 7px 12px; }
.storebadge.storebadge-sm .bmark { width: 22px; height: 22px; }
.storebadge.storebadge-lg { padding: 11px 18px; border-radius: var(--r-lg); }
.storebadge.storebadge-lg .bmark { width: 28px; height: 28px; }

/* The in-band badge row (tools hub + home extension band).
   EQUAL WIDTHS, and with no pixel value for anyone to maintain: `1fr` columns
   inside a `max-content` container all settle on the WIDEST item's width, so
   "Add to Edge" (93px on its own) matches "Add to Firefox" (110px), and adding a
   browser re-measures the set instead of going stale against a typed number.
   Worth doing because four near-identical buttons at four different widths read
   as four different controls rather than as one row of choices. */
.hub-badges {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  width: max-content; max-width: 100%; gap: 10px; margin-top: 4px;
}
/* The badge is now WIDER than its own content, so the content has to be told
   where to sit. Left-aligned artwork inside a stretched button is what makes a
   padded row look accidental. */
.hub-badges .storebadge { justify-content: center; }
@media (max-width: 720px) {
  /* Four of these cannot share a phone row without shrinking below their own
     labels (white-space: nowrap, so they would spill rather than wrap). Two
     columns instead, which is still equal widths, just fewer per line. */
  .hub-badges {
    grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); width: 100%;
  }
  /* Five badges (the visitor is on a browser outside the four primaries, so their
     own is prepended) leave an orphan in a two-up grid. The leader IS their own
     browser, so give it the full row and let the other four pair off under it.
     `:first-child:nth-last-child(odd)` is how CSS counts the set: for the first
     child, nth-last-child counts back to the total. */
  .hub-badges .storebadge:first-child:nth-last-child(odd) { grid-column: 1 / -1; }
}

/* Footer block: one lead link, then the three badges. Centred like the rest of the
   footer, sitting above the primary nav row with a hairline divider under it. */
.foot-ext {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding-bottom: 20px; margin-bottom: 18px; border-bottom: 1px solid var(--line);
}
.foot-ext-lead {
  font-size: 13.5px; font-weight: 600; color: var(--ink-2); text-decoration: none;
}
.foot-ext-lead:hover { color: var(--ink); text-decoration: underline; }
.foot-badges { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }

/* Accepted payment methods: a centred row of the vendored pay marks. Every mark comes
   from ONE set and already draws its own tile (white card, hairline border, brand
   artwork inside) at one 38x24 ratio, so the row needs no chip and no padding.
   It does need ONE ring, drawn here rather than in the artwork: three of the six
   tiles are white, and their own 7% hairline all but vanishes against paper, so
   those three read as loose logos while the colour-filled three read as tiles.
   The ring gives all six the same edge, at the radius the artwork already uses. */
.foot-pay { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px; margin: 10px 0 22px; }
.foot-pay img {
  height: 24px; width: auto; display: block;
  border-radius: 3px; box-shadow: 0 0 0 1px rgba(15,27,45,.14);
}

/* Bottom bar: language control, then the two fine-print lines, under a hairline. The
   lines are separate paragraphs so they get real space between them (they were one
   paragraph split by a <br>, which set them a single leading apart and read as one
   run-on sentence). */
.foot-bottom { padding-top: 18px; border-top: 1px solid var(--line); }
.foot-bottom .copyright { margin: 0 0 8px; }
.foot-bottom .copyright:last-child { margin-bottom: 0; }
