/* The three funnel pages: /start, /checkout and the progress page. They share one
 * two-column shape — the form on the left, the running order summary on the right —
 * so one stylesheet covers all of them. */

/* The vertical padding is written on the inline axis too, as the gutter it already
 * had: `.container` sets `padding: 0 var(--gutter)` and a shorthand here overrode it,
 * so every funnel page's content sat a gutter to the left of the wordmark above it and
 * touched the screen edge on a phone. */
.funnelBody { padding: 56px var(--gutter) var(--section-y); }
.funnelBody__eyebrow { margin-bottom: var(--space-4); }
.funnelBody__heading { margin-bottom: 14px; }
.funnelBody__submit { margin-top: var(--space-15); }

/* ------------------------------------------------------------------- the questions */

.question__foot { font: var(--text-body-sm); color: var(--text-muted); flex-wrap: nowrap; }

/* -------------------------------------------------------------- the invoice block */

/* Two short boxes on one line: a registry number and a VAT number are both a dozen
 * characters, and a full-width box for either says *write a lot here*. It collapses to
 * one column under 420px rather than at a breakpoint, because what decides it is
 * whether two 180px boxes still fit and not what kind of device is asking. */
.buyerPair {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

/* The refused mark for a select, which lives here rather than beside `.input--invalid`
 * in components.css for one reason: the only select on this site is the country box on
 * the page this sheet dresses. It moves to components.css the day a second one exists. */
.select--invalid { border-color: var(--fail-solid); }

/* --------------------------------------------------------------------- the invoice */

.invoiceGrid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.total__label {
  font-family: var(--font-sans);
  font-size: var(--size-md);
  font-weight: var(--weight-semibold);
  line-height: 1.3;
  color: var(--text-strong);
}

.total__value { font-size: var(--size-md); color: var(--text-strong); }

/* -------------------------------------------------------------------- the progress */

/* The progress page is a single centred column, not the two-column funnel shape. */
.progressPage {
  flex: 1;
  background: linear-gradient(180deg, var(--signal-25) 0%, var(--surface-page) 55%);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 72px var(--gutter) var(--section-y);
}

.progressPage__inner { width: 100%; max-width: 620px; display: flex; flex-direction: column; gap: var(--space-5); }
.progressPage__head { text-align: center; display: flex; flex-direction: column; gap: 14px; }
.progressPage__close { text-align: center; }

/* -------------------------------------------------------------------- the delivery */

/* The last page of the funnel: one centred column holding the printed file. No
 * artboard covers it — see the report-delivery entry in src/lib/wip.js. */
.delivery {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.delivery__actions { gap: var(--space-3); flex-wrap: wrap; }

/* The frame fills the page column, the same one the site header's wordmark starts at
 * and the same one every other page on the site uses. It had a column of its own at
 * 860px, narrower than the page it sat on, for the sake of holding a whole A4 sheet in
 * shape: that is a thumbnail of the report rather than the report, and the file is the
 * whole of what this page is for.
 *
 * It stops there. Two wider arrangements were built and rejected: the frame breaking
 * out to the window on its own, which gives a page two left edges, and the header and
 * the step strip moving out with it, which makes these two pages full width while the
 * rest of the site is a centred column.
 *
 * Height is the window's, not the ratio's: at this width a sheet is taller than any
 * screen, so 80vh is what keeps the download button reachable without scrolling and
 * the viewer scrolls the rest. The A4 ratio stays as the floor — on a phone the frame
 * is narrow enough that the sheet is shorter than 80vh, and there it is the shape of
 * the page again. */
.delivery__viewer {
  width: 100%;
  aspect-ratio: 210 / 297;
  max-height: 80vh;
  overflow: hidden;
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  background: var(--surface-card);
}

.delivery__frame { display: block; width: 100%; height: 100%; border: 0; }
.delivery__fallback { text-align: center; }

/* -------------------------------------------------------------- the written pages */

/* The thirteen pages our own report asked for. One column, held to a reading measure,
 * with room between sections rather than rules between them: these are long answers to
 * one question each, and a reader who has arrived from a search result is reading rather
 * than scanning a funnel step. */
.article { max-width: 44rem; }
.article__section { scroll-margin-top: var(--space-8); }
.article__section > .h3 { margin-top: var(--space-4); }

/* A plain list. `.checklist` ticks everything, which is an assertion, so anything that
 * is not a claim about what we do gets this instead. */
.bullets { margin: 0; padding-left: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }
.bullets li { font: var(--text-body-md); color: var(--text-body); text-wrap: pretty; }

/* Term and value. Two columns where there is room and stacked where there is not: the
 * terms here are things like a user-agent string, and squeezing one into a third of a
 * phone's width wraps it into four lines of noise. */
.facts { margin: 0; display: flex; flex-direction: column; gap: var(--space-3); }

.facts__row {
  display: grid;
  grid-template-columns: minmax(11rem, 15rem) 1fr;
  gap: var(--space-2) var(--space-5);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-hairline) solid var(--line-subtle);
}

.facts__row:last-child { border-bottom: 0; padding-bottom: 0; }
.facts__term { font: var(--text-body-md); font-weight: var(--weight-medium); color: var(--text-strong); }
.facts__value { margin: 0; font: var(--text-body-md); color: var(--text-body); text-wrap: pretty; }

@media (max-width: 40rem) {
  .facts__row { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* Something to paste. It scrolls rather than wraps, because a robots.txt rule broken
 * across two lines is a robots.txt rule that does not work. */
.snippet {
  margin: 0;
  padding: var(--space-4);
  background: var(--surface-sunken);
  border: var(--border-hairline) solid var(--line-subtle);
  border-radius: var(--radius-md);
  overflow-x: auto;
}

.snippet code { font: var(--text-data); color: var(--text-strong); white-space: pre; }

/* The pages one crawl read: an address, a title, and a line of facts under it. A list
   rather than a table, because the address and the title are both long and unpredictable,
   and three columns of them at phone width is a table nobody can read. */
.siteList { list-style: none; margin: 0; padding: 0; border-top: var(--border-hairline) solid var(--line-subtle); }
.siteList__row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) 0;
  border-bottom: var(--border-hairline) solid var(--line-subtle);
}
.siteList__title { font: var(--text-body-md); color: var(--text-strong); }

/* What the crawl found, folded under the question it answers. A native disclosure, because
   the product runs without scripts and this is the element that opens without one. */
.found { border-top: var(--border-hairline) solid var(--line-subtle); padding-top: var(--space-3); }
.found__summary { font: var(--text-body-sm); color: var(--text-body); cursor: pointer; }
.found__list {
  margin: var(--space-3) 0;
  padding-left: var(--space-5);
  font: var(--text-body-sm);
  color: var(--text-body);
  columns: 2 16rem;
}

/* The setup form's list editors: one row per item, numbered by a counter rather than by
   the server, so a drag renumbers every row without anybody rewriting it. The row wraps
   at phone width with the buttons under the input. The handle only appears once
   SortableJS has loaded (`.listEditor--sortable` is the class the script adds when it
   finds the library), because a handle that does nothing is a broken control on a page
   that works perfectly well without it. */
.listEditor { margin: 0; padding: 0; border: 0; min-width: 0; }
.listEditor__legend { padding: 0; margin-bottom: var(--space-2); }
.listEditor__items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); counter-reset: listItem; }
.listEditor__items:empty { display: none; }
.listEditor__item { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); counter-increment: listItem; }
.listEditor__item::before { content: counter(listItem) "."; min-width: 1.75em; text-align: right; font: var(--text-data); color: var(--text-muted); }
.listEditor__item--ghost { opacity: 0.4; }

/* With the script running every change saves itself, so the Save button is only for a
   page without it; the line beside it says when the last save landed. */
.listEditor--auto .listEditor__save { display: none; }
.listEditor__saved:empty { display: none; }
.listEditor__input { flex: 1 1 12rem; min-width: 0; width: auto; }
.listEditor__moves { display: flex; gap: var(--space-1); }
.listEditor__handle { display: none; color: var(--text-faint); cursor: grab; touch-action: none; }
.listEditor--sortable .listEditor__handle { display: inline-flex; }
.listEditor__add { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* ----------------------------------------------------------------- the app menu */

/* Two columns behind the sign-in: the menu, then the page. `align-items: start` is what
   lets the menu be as short as it is instead of a 14rem column of white stretched to the
   height of a crawl listing. The gutter and the vertical padding stay on `.funnelBody`,
   which this is worn beside, so the left edge of the menu is the left edge every other
   page on the site starts at. */
.appShell { display: grid; gap: var(--space-6); align-items: start; }

/* `minmax(0, 1fr)` and not `1fr`: a grid track's automatic minimum is the widest thing
   in it, and the pages list holds addresses that do not wrap, so a plain `1fr` lets one
   long URL push the whole column past the screen. */
.appShell__main { min-width: 0; }

@media (min-width: 60rem) {
  .appShell { grid-template-columns: 15rem minmax(0, 1fr); gap: var(--space-10); }
}

/* The burger. A `<details>` with nothing in it, because what it opens is its sibling —
   see `appNav` in src/views/pages/app.js for why the panel is beside it rather than
   inside it. The marker is hidden in both spellings and replaced by the three lines,
   which is a character rather than an icon file for the same reason the language menu's
   chevron is. */
.appNav__burger > summary {
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: var(--border-hairline) solid var(--line-subtle);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: var(--text-body-sm);
  font-weight: var(--weight-medium);
  color: var(--text-body);
}

.appNav__burger > summary::-webkit-details-marker { display: none; }
.appNav__burger > summary::before { content: "\2630"; font-size: 1.1em; }
.appNav__burger[open] > summary { border-color: var(--line-strong); }

/* Closed on a phone, open when the burger is, and always open above the breakpoint,
   where the burger itself is gone. */
.appNav { display: none; }
.appNav__burger[open] + .appNav { display: block; }

@media (min-width: 60rem) {
  .appNav__burger { display: none; }
  .appNav { display: block; position: sticky; top: var(--space-6); }
}

.appNav__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-05); }

/* Setup stands on its own under the domain's name: it is where everything the report reads
   is entered, so it is set apart from the pages that show what came out of it. */
.appNav__setup {
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-hairline) solid var(--line-subtle);
}
.appNav__note { margin: var(--space-1) var(--space-3) 0; font: var(--text-body-sm); font-size: var(--size-2xs); color: var(--text-muted); }


.appNav__group {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: var(--border-hairline) solid var(--line-subtle);
}

/* The domain the second group is about. It is a name somebody typed, so it is allowed to
   break anywhere rather than widen the column. */
.appNav__title {
  display: block;
  margin-bottom: var(--space-2);
  font: var(--text-body-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

/* The switcher: the domain's name as the summary of a `<details>`, opening the account's
   other domains underneath it. See `domainSwitcher` in src/views/pages/app.js for why it
   is a disclosure of links rather than a select. It sits inside the nav, so on a phone it
   is a second disclosure inside the burger's panel and needs nothing of its own there.
   The summary keeps the title's type and gains a chevron that turns when it is open,
   drawn as a character for the same reason the burger's three lines are. */
.appNav__switch { margin-bottom: var(--space-2); }

.appNav__switch > summary.appNav__title {
  list-style: none;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border: var(--border-hairline) solid var(--line-subtle);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.appNav__switch > summary::-webkit-details-marker { display: none; }
.appNav__switch > summary::after { content: "\25BE"; flex: none; color: var(--text-muted); }
.appNav__switch[open] > summary { border-color: var(--line-strong); }
.appNav__switch[open] > summary::after { transform: rotate(180deg); }
.appNav__switch > summary:hover { background: var(--surface-sunken); }

.appNav__domains {
  list-style: none;
  margin: var(--space-1) 0 0;
  padding: var(--space-1);
  border: var(--border-hairline) solid var(--line-subtle);
  border-radius: var(--radius-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-05);
}

.appNav__domain {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font: var(--text-body-sm);
  color: var(--text-body);
  text-decoration: none;
  overflow-wrap: anywhere;
}

a.appNav__domain:hover { background: var(--surface-sunken); color: var(--text-strong); text-decoration: none; }

/* The one you are on, filled like the page you are on in the list below it. */
.appNav__domain[aria-current] {
  background: var(--surface-brand-soft);
  color: var(--text-brand);
  font-weight: var(--weight-semibold);
}

/* A domain with no year running: quieter, and saying so in words underneath, so the
   colour is never the only difference. */
.appNav__domain--inactive { color: var(--text-muted); }
.appNav__domainNote { display: block; font-weight: var(--weight-regular); color: var(--text-muted); }

.appNav__link {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font: var(--text-body-sm);
  color: var(--text-body);
  text-decoration: none;
  text-wrap: pretty;
}

a.appNav__link:hover { background: var(--surface-sunken); color: var(--text-strong); text-decoration: none; }

/* Where you already are: filled rather than underlined, because an underline in a list
   of links reads as the one link that is different rather than as the page you are on. */
.appNav__link[aria-current] {
  background: var(--surface-brand-soft);
  color: var(--text-brand);
  font-weight: var(--weight-semibold);
}

.appNav__out { margin-top: var(--space-5); }

/* --------------------------------------------------------- where a domain stands */

/* The panel at the top of a domain's dashboard: a row each, a mark, a name and a short
   state on one line. A term-and-value shape like `.facts`, and not that class,
   because these terms are links and each row leads with a mark. On a phone the state
   drops under the name rather than squeezing beside it, with the mark still in front of
   the name, because a third of 390px is not room for both. */
.standing { list-style: none; margin: 0; display: flex; flex-direction: column; gap: var(--space-3); }

.standing__row {
  display: grid;
  grid-template-columns: auto minmax(8rem, 12rem) minmax(0, 1fr);
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-hairline) solid var(--line-subtle);
}

.standing__row:last-child { border-bottom: 0; padding-bottom: 0; }

/* The mark. Its shape carries the state (a check, a clock, an exclamation, an empty
   circle, a dot) and the colour only repeats it, so the panel reads the same to somebody
   who cannot tell green from amber; the words a screen reader hears sit beside it as
   visually hidden `.sr-only` text. A neutral row keeps the faint colour every mark starts
   with. `align-self: center` because an SVG has no baseline worth the name. */
.standing__row > .icon { align-self: center; color: var(--text-faint); }
.standing__row--done > .icon { color: var(--pass-solid); }
.standing__row--busy > .icon { color: var(--info-solid); }
.standing__row--warn > .icon { color: var(--warn-solid); }

/* Underlined at rest, in the quiet line colour rather than in the text colour. Three of
   these four names are the only way into their section from this panel, and a name that
   is merely heavier than the line beside it is not telling anybody it can be clicked:
   weight reads as a heading. Hover cannot carry it either, because a phone never hovers,
   and this panel is the first thing a buyer sees on a phone. A chevron after each name
   was the other option the system would have taken, and it lost because four arrows down
   a four row panel read as a menu stuck inside a card. The underline in `--line-strong`
   is quieter than that and still unmistakable, and hover still has somewhere to go: it
   takes the brand colour and brings the underline up to it. Focus needs nothing here,
   because the outline in tokens/base.css already lands on every focusable element. */
.standing__term {
  font: var(--text-body-md);
  font-weight: var(--weight-medium);
  color: var(--text-strong);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 2px;
  text-wrap: pretty;
}

.standing__term:hover { color: var(--text-brand); text-decoration: underline; }

.standing__line { margin: 0; font: var(--text-body-md); color: var(--text-body); text-wrap: pretty; }

/* What the site sells, under the crawl's state and in line with it. One line on a laptop:
   a name the model wrote long is cut with an ellipsis rather than pushing the panel a
   line taller, and the whole sentence is still there for a screen reader and on the
   report page it links to. The padding and the matching negative margin make room inside
   the clip for the focus outline, which sits 2px out and is 2px thick. On a phone it
   wraps like the line above it. */
.standing__aside {
  grid-column: 3;
  margin: calc(-1 * var(--space-1));
  padding: var(--space-1);
  font: var(--text-body-sm);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 40rem) {
  .standing__row { grid-template-columns: auto minmax(0, 1fr); }
  .standing__line { grid-column: 2; }
  .standing__aside { grid-column: 2; white-space: normal; text-wrap: pretty; }
}

/* A box's figure on the report page: "2 of 7 done" as a plain line under the title, in
   the body's weight, because there the list below it is the point rather than the sum. */
.boxSummary { margin: 0; color: var(--text-strong); }

/* A link to a section of the report page lands with the heading clear of the top edge. */
#compliance, #seo, #keywords, #structure { scroll-margin-top: var(--space-6); }

/* The site structure on the report page: one tree of the pages a site has and the pages to
   write under them. Nested lists, each level set in from its parent with a hairline down
   its left edge, so the hierarchy reads without a single icon. A page that exists is drawn
   solid; a page to write, and a new hub, faded, with its state in its badge as well as in
   the colour, so the difference survives a print in black and white. */
.siteTree, .siteTree__list { list-style: none; margin: 0; padding: 0; }
.siteTree__list {
  margin-left: var(--space-2);
  padding-left: var(--space-4);
  border-left: var(--border-hairline) solid var(--line-subtle);
}
.siteTree__node { padding-top: var(--space-1); }
.siteTree__line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font: var(--text-body-md); color: var(--text-strong); }
.siteTree__node--suggested > .siteTree__line,
.siteTree__node--new > .siteTree__line { color: var(--text-muted); }
.siteTree__node--suggested > .siteTree__line > a,
.siteTree__node--new > .siteTree__line > a { color: inherit; text-decoration-color: var(--line-strong); }
.siteTree__node--new > .siteTree__line > a { font-weight: var(--weight-medium); }

/* ------------------------------------------------------------------ the usage meter */

/* How much of this month's usage is gone, under a page's heading: one line of words and a
   thin bar under it. The words are the measure and the link to the packages; the bar is
   decoration beside them, hidden from a screen reader, and takes the warning colour from
   80% and the failing one once the usage is spent, so the state is in its colour as well
   as in the number. Its width is the one inline style the view sets. */
.usageMeter { display: grid; gap: var(--space-1); max-width: 22rem; margin-top: var(--space-3); }
.usageMeter__label { margin: 0; font: var(--text-body-sm); color: var(--text-muted); }
.usageMeter__label a { color: var(--text-strong); text-decoration-color: var(--line-strong); }
.usageMeter__label a:hover { color: var(--text-link-hover); }
.usageMeter__track { height: 4px; border-radius: var(--radius-pill); background: var(--surface-sunken); overflow: hidden; }
.usageMeter__fill { height: 100%; border-radius: inherit; background: var(--pass-solid); }
.usageMeter--high .usageMeter__fill { background: var(--warn-solid); }
.usageMeter--spent .usageMeter__fill { background: var(--fail-solid); }

/* ------------------------------------------------------------------ the package offer */

/* The popup the report page opens when a scan was refused for usage. The page runs with
   no script, so it is a server-drawn `<dialog open>` inside a fixed scrim, closed by a
   link back to the page; the scrim is the dialog translucency components.css allows. */
.planOffer {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--surface-inverse) 45%, transparent);
  overflow-y: auto;
}

.planOffer__dialog {
  position: static;
  margin: 0;
  width: 100%;
  max-width: 32rem;
  color: var(--text-body);
  box-shadow: var(--shadow-lg);
}

.planOffer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }

.planOffer__plan {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-hairline) solid var(--line-subtle);
}

.planOffer__plan:last-child { border-bottom: 0; padding-bottom: 0; }
.planOffer__name { font: var(--text-body-md); font-weight: var(--weight-medium); color: var(--text-strong); }

@media print {
  /* The menu is screen furniture, the same way the running chrome in report.css is. It
     is a way of getting to another page, and paper has no other page to get to, so on
     a printed dashboard it is a 15rem column of grey words beside the thing somebody
     actually wanted on the sheet. The burger goes with it rather than printing the word
     "Menu" above a panel it cannot open.

     The track has to go too. Hiding the nav leaves its column behind, because an empty
     grid track is still 15rem wide, and the page would print into the right two thirds
     of the paper with the left third blank. `grid-template-columns: none` is set rather
     than left to the 60rem query missing: an A4 sheet inside its margins is about 39rem,
     so the query usually does not match, but a wider sheet or a scaled print is not
     something this rule should depend on. */
  .appNav, .appNav__burger { display: none; }

  .appShell { grid-template-columns: none; gap: 0; }
}

/* The report box's archive of done items: folded by default under the open list. */
.boxArchive { border-top: var(--border-hairline) solid var(--line-subtle); padding-top: var(--space-3); }
.boxArchive__summary { cursor: pointer; font: var(--text-body-sm); color: var(--text-muted); }
.boxArchive[open] > .boxArchive__summary { margin-bottom: var(--space-3); }

/* A page's draft on its item page (src/views/pages/page-work.js): the body as the owner
   typed it, line breaks kept, when the page is done and the draft is only to read. */
.workDraft { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font: var(--text-body-md); color: var(--text-body); }

/* The draft as HTML, as it reads: the three things draft-text.js renders and nothing more. */
.draftView { display: flex; flex-direction: column; gap: var(--space-3); }
.draftView h1 { font: var(--text-h2); color: var(--text-strong); margin: 0; }
.draftView h2, .draftView h3, .draftView h4, .draftView h5, .draftView h6 { font: var(--text-h3); color: var(--text-strong); margin: 0; }
.draftView p, .draftView li { font: var(--text-body-md); color: var(--text-body); margin: 0; text-wrap: pretty; }
.draftView ul, .draftView ol { margin: 0; padding-left: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }
