/* Defensive, scoped box-sizing reset. Do not rely on the theme's own global
 * reset staying in place -- a 100% inline-size input plus padding and a
 * border, without border-box, is exactly how a form field ends up wider than
 * its narrow-viewport parent (the 625px-in-a-412px-screen incident this
 * project already had once). Costs nothing when the theme already resets it
 * globally; forecloses the bug class when it does not. */
[data-aim-scan-form],
[data-aim-scan-form] *,
[data-aim-scan-form] *::before,
[data-aim-scan-form] *::after {
  box-sizing: border-box;
}

/* hidden means hidden. The browser's own [hidden] { display: none } is a
 * user-agent rule, and ANY author declaration beats it -- origin is decided
 * before specificity is. So a single `section { display: grid }` anywhere in
 * the theme silently shows every screen of this form at once.
 *
 * That is not hypothetical: it shipped. Task 6 hit exactly this on the
 * result page and fixed it there, scoped to .aim-scan-result-page. The form
 * page has its own theme and its own rules, so the same bug arrived again on
 * /bedrijfsscan -- screens 2 and 3, the follow-up round, the waiting message
 * and the lost-link field all stacked on one page, which also made the
 * Verder button look like it did nothing, because the next screen was
 * already on the visitor's screen.
 *
 * !important is the right tool here and almost nowhere else. `hidden` is an
 * absolute statement about whether an element exists for the reader; no
 * layout rule should ever outrank it. Specificity juggling only wins against
 * the rules you have already seen, and the theme is not ours.
 *
 * Page-wide rather than scoped: the invariant is "hidden hides", not "hidden
 * hides inside this one container". Scoping it to the place the bug was
 * found is what let it happen twice. */
[hidden] {
  display: none !important;
}

/* Nothing inside this form may make it wider than the screen.
 *
 * A grid column and a flex item both size to their content by default, and
 * refuse to shrink below it -- so ONE long line anywhere pushes the whole form
 * sideways and the visitor gets a horizontal scrollbar on a phone. That is what
 * happened: a single tick box reading "Klanten emailen met nieuwe promoties"
 * dragged every field on the screen out past the right edge.
 *
 * minmax(0, 1fr) says the column may shrink to nothing, which is what lets the
 * text inside it wrap instead of pushing. Applied to every grid in the form
 * rather than to the one that broke, because the next long line will be
 * somewhere else. Harmless on the elements here that are not grids. */
[data-aim-scan-form],
[data-aim-scan-form] .aim-scan-screen,
[data-aim-scan-form] .aim-scan-field,
[data-aim-scan-form] .aim-scan-fieldset,
[data-aim-scan-form] .aim-scan-choices,
[data-aim-scan-form] .aim-scan-ticks,
[data-aim-scan-form] .aim-scan-tick-item,
[data-aim-scan-form] .aim-scan-tick-drawer,
[data-aim-scan-form] .aim-scan-chips,
[data-aim-scan-form] .aim-scan-chips-details,
[data-aim-scan-form] .aim-scan-chip-groups,
[data-aim-scan-form] .aim-scan-chip-other,
[data-aim-scan-form] .aim-scan-chip-other-row,
[data-aim-scan-form] .aim-scan-hints {
  grid-template-columns: minmax(0, 1fr);
}

[data-aim-scan-form] {
  --aim-scan-gap: var(--space-m, 1.25rem);
  /* No --danger token exists on ainmotion.nl -- confirmed directly against
   * the live compiled automatic.css, which defines --primary/--base/--neutral
   * and their shades but no --secondary/--tertiary/--accent/--success/
   * --warning/--danger. Defined locally here instead of guessing at a token
   * name, per the etch-acss-currency rule: never invent one, fall back to a
   * locally scoped custom property when it can't be confirmed. */
  --aim-scan-danger: #e5484d;
  display: grid;
  gap: var(--aim-scan-gap);
  max-width: 42rem;
}

/* Numbered steps, replacing a filling stripe.
 *
 * A stripe tells you a fraction. It does not tell you where you are, what you
 * just finished, or how much is left -- and for a form whose length you cannot
 * see, the thing that decides whether someone continues is knowing it is
 * finite. Four numbers say that; 40% does not. */
.aim-scan-steps {
  display: flex;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.aim-scan-step {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 0.5rem;
  min-inline-size: 0;
  font-size: var(--text-s, 0.9rem);
  opacity: 0.5;
}

.aim-scan-step.is-current,
.aim-scan-step.is-done {
  opacity: 1;
}

.aim-scan-step-number {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 1.75rem;
  block-size: 1.75rem;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 0.85em;
  font-weight: 600;
}

.aim-scan-step.is-current .aim-scan-step-number {
  border-color: var(--primary, #ff6f5e);
  background: var(--primary, #ff6f5e);
  color: var(--btn-text-color, var(--primary-ultra-light, #fff));
}

.aim-scan-step.is-done .aim-scan-step-number {
  border-color: var(--primary, #ff6f5e);
  color: var(--primary, #ff6f5e);
}

.aim-scan-step-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* On a phone, four labels wrap into a paragraph. Only the current step keeps
 * its visible label -- but the others are hidden the visually-hidden way, not
 * with display: none, so a screen reader still reads "3 Je klanten" instead of
 * a bare number. */
@media (width < 30rem) {
  .aim-scan-step:not(.is-current) .aim-scan-step-label {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

.aim-scan-screen {
  display: grid;
  gap: var(--aim-scan-gap);
}

.aim-scan-field {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 3);
}

.aim-scan-field label,
.aim-scan-field-label {
  font-weight: 600;
}

/* Native fieldset carries its own border/padding/margin by default in every
 * browser -- reset it so a radio group looks identical to how the old plain
 * div did, while keeping the real fieldset/legend semantics. */
.aim-scan-fieldset {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 3);
  margin: 0;
  padding: 0;
  border: none;
  min-inline-size: 0;
}

.aim-scan-fieldset legend {
  padding: 0;
}

.aim-scan-help {
  margin: 0;
  font-size: 0.9em;
  opacity: 0.75;
}

.aim-scan-choices {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 3);
}

.aim-scan-choice {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  padding: 0.7rem 0.9rem;
  border: 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 20%, transparent);
  border-radius: 8px;
  cursor: pointer;
  font-weight: 400;
  min-block-size: 44px;
}

.aim-scan-choice:has(input:checked) {
  border-color: var(--primary, #ff6f5e);
}

[data-aim-scan-form] textarea,
[data-aim-scan-form] input[type="text"],
[data-aim-scan-form] input[type="email"] {
  inline-size: 100%;
  padding: 0.7rem 0.9rem;
  border-radius: 8px;
  font: inherit;
}

.aim-scan-button {
  justify-self: start;
  padding-block: var(--btn-padding-block, 0.75rem);
  padding-inline: var(--btn-padding-inline, 1.75rem);
  border: none;
  border-radius: var(--btn-border-radius, var(--btn-radius, 8px));
  background: var(--btn-background, var(--primary, #ff6f5e));
  color: var(--btn-text-color, var(--primary-ultra-light, #fff));
  font-weight: var(--btn-font-weight, 600);
  font-size: var(--btn-font-size, 1rem);
  min-block-size: 44px;
  min-inline-size: 44px;
  cursor: pointer;
}

.aim-scan-button:hover:not(:disabled) {
  background: var(--btn-background-hover, var(--primary-hover, #ff6f5e));
}

.aim-scan-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* A button waiting on the network. Set alongside disabled, never instead of
 * it: a validation failure disables too, and that must not spin. */
.aim-scan-button[data-aim-busy] {
  opacity: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}

.aim-scan-button[data-aim-busy]::before {
  content: "";
  inline-size: 1em;
  block-size: 1em;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-block-start-color: transparent;
  animation: aim-scan-spin 0.7s linear infinite;
}

@keyframes aim-scan-spin {
  to { transform: rotate(360deg); }
}

/* Someone who has asked their system to stop animating gets a steady ring
 * rather than nothing: the point is "this is working", and that has to
 * survive the preference. */
@media (prefers-reduced-motion: reduce) {
  .aim-scan-button[data-aim-busy]::before {
    animation: none;
    border-block-start-color: currentColor;
    opacity: 0.5;
  }

}

/* -------------------------------------------------------------------------
 * The wait. A minute is a long time to look at one unchanging sentence.
 */
.aim-scan-waiting-bar {
  position: relative;
  block-size: 4px;
  margin-block-start: var(--aim-scan-gap);
  border-radius: 999px;
  background: color-mix(in srgb, var(--text-light, #fafaf8) 15%, transparent);
  overflow: hidden;
}

/* 40% wide, travelling from just off the left edge to just past the right one.
 * translateX resolves against the element's OWN width, so -100% parks it fully
 * out of sight and 250% carries its left edge to the far end of the track. */
.aim-scan-waiting-bar::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inline-size: 40%;
  border-radius: inherit;
  background: var(--primary, #ff6f5e);
  animation: aim-scan-travel 1.6s ease-in-out infinite;
}

@keyframes aim-scan-travel {
  from { transform: translateX(-100%); }
  to   { transform: translateX(250%); }
}

/* Same ruling as the button spinner: someone who asked their system to stop
 * animating still gets to see that something is in progress, so the track
 * fills and holds instead of vanishing. */
@media (prefers-reduced-motion: reduce) {
  .aim-scan-waiting-bar::after {
    animation: none;
    inline-size: 100%;
    opacity: 0.35;
  }
}

.aim-scan-error {
  color: var(--primary, #ff6f5e);
}

/* Where am I, said again at the bottom. The ladder at the top is gone from the
 * screen by the time someone reaches the button, which is exactly the moment
 * the answer matters. */
.aim-scan-step-note {
  margin: 0;
  font-size: var(--text-s, 0.9rem);
  opacity: 0.7;
}

/* -------------------------------------------------------------------------
 * Choosing instead of typing: the chips above the programs question and the
 * tick boxes above "wat blijft er liggen".
 *
 * Both are views of the textarea underneath them (see the invariant in
 * scan.js). Neither is ever the only way to answer, which is why they carry
 * no state of their own and why they ship hidden until JavaScript unhides
 * them.
 */
.aim-scan-chips,
.aim-scan-ticks {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 3);
}

.aim-scan-ticks-label {
  margin: 0;
  font-size: 0.9em;
  opacity: 0.75;
}

.aim-scan-chips-details {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 3);
}

/* A full-width row, in exactly the shape of the category rows it opens.
 *
 * It was a small pill, from a design where the list was a helper above a box
 * you typed in. The list became the way you answer, and a pill reads as a side
 * door -- this is the front one. Same width, same corner, same drawn marker as
 * the rows below it, one step heavier, so it reads as the parent of what it
 * opens rather than as an unrelated button floating over it. Costs no height. */
.aim-scan-chips-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--primary, #ff6f5e);
  border-radius: 8px;
  color: var(--primary, #ff6f5e);
  font-weight: 600;
  min-block-size: 44px;
  cursor: pointer;
  /* Both are needed: the standard property for current browsers and the
   * -webkit- pseudo-element for the older WebKit that ignores it. Without
   * them the default triangle sits inside a pill and looks like a mistake. */
  list-style: none;
}

.aim-scan-chips-toggle::-webkit-details-marker {
  display: none;
}

/* The open/closed marker, drawn rather than typed.
 *
 * It was a text "+" that rotated into an x when open, and Andre read the x as
 * "delete this" -- which is exactly what an x means everywhere else. It has to
 * be a minus. But the minus sign it was before THAT was written as a CSS
 * unicode escape, and that escape never survived being written to disk: it
 * arrived as a stray control byte and the live page rendered a missing-glyph
 * box. It happened twice -- the second time inside this very comment, while
 * describing the first, and the test written after round one caught it.
 *
 * So: two bars painted with gradients. Plus when closed, minus when open, no
 * character anywhere, nothing that depends on the site font and nothing left
 * for an escape to mangle. */
.aim-scan-chips-toggle::after,
.aim-scan-chip-group-toggle::after {
  content: "";
  flex: none;
  inline-size: 0.75rem;
  block-size: 0.75rem;
  background:
    linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat;
}

/* Open: the upright bar goes, leaving the minus.
 *
 * Written against any open <details> whose summary is one of these rows, not
 * against a list of wrapper classes. A third opener was added later and would
 * have kept showing a plus forever, which is the kind of thing you only notice
 * by opening it. */
[data-aim-scan-form] details[open] > .aim-scan-chips-toggle::after,
.aim-scan-chip-group[open] .aim-scan-chip-group-toggle::after {
  background: linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat;
}

.aim-scan-chip-groups {
  display: grid;
  gap: 0.3rem;
}

/* Read, recognise, type it yourself. Nothing in here is clickable, on purpose:
 * see the comment in form.php. */
.aim-scan-hints {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 3);
}

.aim-scan-hint-list {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 0.7rem;
  row-gap: 0.35rem;
  margin: 0;
  padding-inline: 0.9rem;
  font-size: 0.9em;
}

.aim-scan-hint-list dt {
  font-weight: 600;
}

.aim-scan-hint-list dd {
  margin: 0;
  opacity: 0.75;
}

.aim-scan-hints > .aim-scan-help {
  padding-inline: 0.9rem;
}

/* Sits outside the collapsible part on purpose: it is the one thing that has to
 * survive closing the list. */
.aim-scan-chips-summary {
  margin: 0;
  font-size: 0.9em;
  opacity: 0.85;
}

/* Each category is its own row you can open. The row is the visible layer and
 * the products sit under it, because reading "voorraad en verzenden" is what
 * makes someone remember he has a shipping tool at all -- naming your own
 * software cold is the hard part, not picking it off a list. */
.aim-scan-chip-group {
  border: 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 14%, transparent);
  border-radius: 8px;
}

.aim-scan-chip-group[open] {
  border-color: color-mix(in srgb, var(--text-light, #fafaf8) 24%, transparent);
}

.aim-scan-chip-group-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.4rem 0.9rem;
  min-block-size: 44px;
  font-size: 0.95em;
  cursor: pointer;
  list-style: none;
}

.aim-scan-chip-group-toggle::-webkit-details-marker {
  display: none;
}

.aim-scan-chip-group-toggle::after {
  opacity: 0.6;
}

/* The name takes the room, so the count and the marker sit together on the
 * right instead of being spread across the row. */
.aim-scan-chip-group-name {
  margin-inline-end: auto;
}

/* "You have already been here." A closed category holding a choice used to
 * look exactly like one nobody had opened, which is where you lose your place
 * halfway down a long list. */
.aim-scan-chip-group-count {
  flex: none;
  display: inline-grid;
  place-items: center;
  min-inline-size: 1.4rem;
  block-size: 1.4rem;
  padding-inline: 0.35rem;
  border-radius: 999px;
  background: var(--primary, #ff6f5e);
  color: var(--btn-text-color, var(--primary-ultra-light, #fff));
  font-size: 0.75em;
  font-weight: 600;
}

/* The way out of a category reads as a different kind of thing from the names
 * in it: dashed, so it is clearly not a program you can pick.
 *
 * And it carries the same drawn marker as the category rows above it. It was
 * the only opener in this list without one: clicking it a second time closed
 * the box again, but nothing said so, and Andre found that out by guessing.
 * The marker is not a new idea he has to learn -- it is the same plus and minus
 * he has already used twice by the time he gets here. */
.aim-scan-chip--other {
  border-style: dashed;
  gap: 0.5em;
}

.aim-scan-chip--other::after {
  content: "";
  flex: none;
  inline-size: 0.7rem;
  block-size: 0.7rem;
  opacity: 0.6;
  background:
    linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat;
}

.aim-scan-chip--other[aria-expanded="true"]::after {
  background: linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat;
}

.aim-scan-chip-group .aim-scan-chip-row {
  padding: 0 0.9rem 0.7rem;
}

.aim-scan-chip-group .aim-scan-chip-other {
  padding: 0 0.9rem 0.7rem;
}

/* Sits with the categories rather than inside one: it is not a kind of
 * program, it is the way out of the list. */
.aim-scan-chip-other {
  display: grid;
  gap: 0.4rem;
  justify-items: start;
}

.aim-scan-chip-other-row {
  display: grid;
  gap: 0.4rem;
  inline-size: 100%;
}

/* It is a <label> so the input has a real one, but .aim-scan-field label sets
 * 600 for the question labels and would make this shout louder than the help
 * text it sits among. */
.aim-scan-chip-other-row .aim-scan-help {
  margin: 0;
  font-weight: 400;
}

.aim-scan-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* Same 44px target as every other control in this form. A chip is small on a
 * desktop and still has to be tappable with a thumb -- so the height stays and
 * the width is where the tightening happens. Measured at 412px: this and the
 * shorter list took the block from ~900px to about half that. */
.aim-scan-chip {
  display: inline-flex;
  align-items: center;
  max-inline-size: 100%;
  overflow-wrap: anywhere;
  padding: 0.4rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 20%, transparent);
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.85em;
  min-block-size: 44px;
  cursor: pointer;
}

.aim-scan-chip[aria-pressed="true"] {
  border-color: var(--primary, #ff6f5e);
  background: color-mix(in srgb, var(--primary, #ff6f5e) 14%, transparent);
}

.aim-scan-tick {
  display: flex;
  min-inline-size: 0;
  gap: 0.6rem;
  align-items: center;
  padding: 0.5rem 0.9rem;
  border: 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 20%, transparent);
  border-radius: 8px;
  cursor: pointer;
  font-weight: 400;
  min-block-size: 44px;
}

.aim-scan-tick:has(input:checked) {
  border-color: var(--primary, #ff6f5e);
}

/* A long line wraps rather than being cut off. It is his own sentence and he has
 * to be able to read it to decide whether it belongs here, so the row grows
 * taller instead.
 *
 * This used to be nowrap plus an ellipsis, and that was the cause of the whole
 * overflow: a nowrap flex item will not shrink below its content, so one long
 * tick pushed the entire form wider than the phone. The bug was there from the
 * first build and only showed when somebody finally typed a line long enough --
 * "Klanten emailen met nieuwe promoties". */
.aim-scan-tick span {
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

/* The tick and its drawer travel together, so the drawer cannot be mistaken
 * for a control belonging to the row underneath it. */
.aim-scan-tick-item {
  display: grid;
  min-inline-size: 0;
  gap: calc(var(--aim-scan-gap) / 4);
}

/* Indented and quieter than the row above it: this is a question ABOUT that
 * line, not a second question in the list.
 *
 * minmax(0, 1fr) on every column, like every other grid in this form. A grid
 * column is auto-sized to its content by default, and a long option label with
 * nowhere to wrap is what dragged the whole form off a 412px screen once
 * already. */
.aim-scan-tick-drawer {
  display: grid;
  gap: calc(var(--aim-scan-gap) / 5);
  margin-inline-start: 1rem;
  padding-inline-start: 0.9rem;
  border-inline-start: 2px solid color-mix(in srgb, var(--primary, #ff6f5e) 35%, transparent);
}

.aim-scan-tick-question {
  margin: 0;
  font-size: 0.85em;
  opacity: 0.75;
}

/* Full width and stacked, not a row of pills. Three sentences side by side on a
 * phone is the overflow bug waiting to happen again, and these are sentences
 * rather than words on purpose -- the short form is what gets stored, the long
 * one is what gets read. */
/* Scoped to the form root purely for specificity: the theme centres button
 * text, and a centred sentence that wraps to two lines reads as a mistake next
 * to the left-aligned line it belongs to. Measured on the live page at 412px,
 * where the third option wraps every time. */
[data-aim-scan-form] .aim-scan-tick-option {
  display: block;
  inline-size: 100%;
  min-inline-size: 0;
  overflow-wrap: anywhere;
  text-align: start;
  padding: 0.45rem 0.75rem;
  border: 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 20%, transparent);
  border-radius: 8px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.85em;
  min-block-size: 44px;
  cursor: pointer;
}

[data-aim-scan-form] .aim-scan-tick-option[aria-pressed="true"] {
  border-color: var(--primary, #ff6f5e);
  background: color-mix(in srgb, var(--primary, #ff6f5e) 14%, transparent);
}

/* -------------------------------------------------------------------------
 * The line under the step ladder. One per screen, so it can say what the
 * screen is about to ask instead of repeating the step's own name.
 */
.aim-scan-screen-intro {
  margin: 0 0 var(--aim-scan-gap);
  opacity: 0.85;
}

/* -------------------------------------------------------------------------
 * The way back, offered above the form when a saved scan is found.
 */
.aim-scan-resume {
  display: grid;
  gap: 0.6rem;
  padding: 0.9rem 1rem;
  border: 1px solid color-mix(in srgb, var(--primary, #ff6f5e) 45%, transparent);
  border-radius: 8px;
}

.aim-scan-resume p {
  margin: 0;
}

.aim-scan-resume-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* Marks the exact field (or, for a radio group, the fieldset) the visitor
 * left unanswered -- an outline rather than a border/background change so
 * it never touches box-sizing or layout width, only visibility. Cleared by
 * scan.js the moment that specific field is answered. */
.aim-scan-invalid {
  outline: 2px solid var(--aim-scan-danger);
  outline-offset: 2px;
  border-radius: 8px;
}

@media (width < 30rem) {
  [data-aim-scan-form] { --aim-scan-gap: 1rem; }
}

/* -------------------------------------------------------------------------
 * Cloudflare Turnstile (screen 1 of the form).
 *
 * The widget is an iframe Cloudflare sizes itself; nothing here touches its
 * dimensions. This only gives it the same rhythm as the fields above it and
 * keeps it from being flush against the button it gates.
 */
.aim-scan-turnstile {
  margin-block-start: calc(var(--aim-scan-gap) / 2);
}

/* -------------------------------------------------------------------------
 * The lost-link front door, under the form on /bedrijfsscan.
 *
 * These two blocks sit OUTSIDE [data-aim-scan-form], so they inherit
 * neither its box-sizing reset nor its --aim-scan-gap. Both are restated
 * here rather than widened above: the reset is scoped on purpose (see the
 * top of this file) and quietly extending its reach is how a scoped reset
 * stops being scoped.
 *
 * Every custom property below is one this stylesheet already relies on
 * elsewhere and is confirmed present in the live compiled automatic.css.
 * Each keeps a literal fallback, same as the rest of this file, so the
 * block still renders sanely if it is ever loaded on a page without ACSS.
 */
.aim-scan-resend,
.aim-scan-resend * {
  box-sizing: border-box;
}

.aim-scan-lost {
  max-width: 42rem;
  margin-block-start: var(--space-m, 1.25rem);
  font-size: var(--text-s, 0.9rem);
  opacity: 0.85;
}

/* A button, not a link: it performs an action on this page rather than
 * navigating anywhere, which is also why the markup on page 89 carries no
 * href at all. Styled as a link so it still reads as one in the sentence
 * it sits inside. */
.aim-scan-linkbutton {
  padding: 0;
  border: none;
  background: none;
  color: var(--primary, #ff6f5e);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* "Meer over mij en waar dit vandaan komt" used to BE the link, rendered in
 * the same grey as body text while "ik ben mijn link kwijt" a few lines up was
 * orange. One element behaving differently from the rest is enough to cost
 * trust, because the visitor stops knowing what is clickable. The sentence is
 * a sentence now, and the link is its own line, marked the same way every
 * other clickable thing on this page is. */
.aim-scan-textlink {
  color: var(--primary, #ff6f5e);
  text-decoration: underline;
}

.aim-scan-resend {
  display: grid;
  gap: calc(var(--space-m, 1.25rem) / 2);
  justify-items: start;
  max-width: 26rem;
  margin-block-start: var(--space-s, 0.75rem);
}

.aim-scan-resend-label {
  font-size: var(--text-s, 0.9rem);
}

.aim-scan-resend input[type="email"] {
  inline-size: 100%;
  padding: 0.7rem 0.9rem;
  border-radius: 8px;
  font: inherit;
}

/* Quieter than the form's primary action: this is a side door, and it
 * should not compete with "Verder" for the eye. Outline rather than fill,
 * but the same 44px target and the same disabled treatment. */
.aim-scan-button--quiet {
  background: transparent;
  border: 1px solid var(--primary, #ff6f5e);
  color: var(--primary, #ff6f5e);
}

.aim-scan-button--quiet:hover:not(:disabled) {
  background: color-mix(in srgb, var(--primary, #ff6f5e) 12%, transparent);
}

.aim-scan-resend-note {
  margin: 0;
  font-size: var(--text-s, 0.9rem);
}

/* -------------------------------------------------------------------------
 * Result page (/scan/<token>/).
 *
 * The bare page shell (aim_scan_shell() in page.php) has no theme header or
 * nav, only wp_head()/wp_footer() -- so this inherits the site's global
 * Automatic.css defaults (dark body background, light body text, --primary
 * links, responsive heading sizes on h1-h3 -- all confirmed against the live
 * compiled stylesheet at wp-content/uploads/automatic-css/automatic.css) and
 * adds only what that global layer does not already cover.
 *
 * One override is load-bearing: Automatic.css puts a zero-specificity
 * :where(section:not(section section)) rule on every top-level <section>,
 * padding it with --section-padding-block (a marketing-page-sized ~3-5.6rem)
 * plus --gutter inline. Confirmed live in the same stylesheet. Harmless in
 * principle (:where() loses to any class selector with real specificity),
 * but left alone it would turn each block below into a full marketing
 * section instead of a paragraph in one document -- exactly the "our sales
 * page" register this page has to avoid. The rule below neutralises it.
 */
body.aim-scan-result {
  margin: 0;
}

body.aim-scan-result main {
  display: block;
  max-width: 42rem;
  margin-inline: auto;
  padding-block: var(--space-xl, 2.5rem);
  padding-inline: var(--gutter, 1.25rem);
}

.aim-scan-result-page {
  display: grid;
  gap: var(--space-l, 2rem);
}

.aim-scan-result-page section {
  /* Overrides Automatic.css's global section padding -- see the comment
   * above this block. */
  padding: 0;
  display: grid;
  gap: var(--space-s, 1rem);
}

/* Any normal author-stylesheet declaration beats the UA stylesheet's own
 * [hidden] { display: none } regardless of specificity -- origin decides
 * before specificity does. Without this, the display:grid line right above
 * would win over the browser's built-in hidden behaviour and block 7 (empty
 * on every page today, see data-aim-block7 in page.php) would render as a
 * visible, empty box -- the exact mistake this task exists to avoid.
 * Broadened from section[hidden] to plain [hidden]: any element on this
 * page that ever gets a display override of its own, not just <section>,
 * needs the same guard. Still scoped to .aim-scan-result-page rather than
 * a bare, page-wide [hidden] -- a bare attribute selector alone has LOWER
 * specificity (0,1,0) than ".aim-scan-result-page section" (0,1,1) above
 * it and would lose to it regardless of source order; keeping the class
 * prefix (0,2,0) is what makes this reliably win, not just broader. */
.aim-scan-result-page [hidden] {
  display: none;
}

.aim-scan-result-page header {
  display: grid;
  gap: var(--space-xs, 0.5rem);
}

.aim-scan-date {
  margin: 0;
  color: var(--text-light-muted, inherit);
  font-size: var(--text-s);
}

.aim-scan-direction {
  margin: 0;
  font-weight: 600;
}

.aim-scan-task {
  display: grid;
  gap: calc(var(--space-s, 1rem) / 2);
  padding: var(--space-s, 1rem);
  border: var(--border, 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 20%, transparent));
  border-radius: var(--radius, 5px);
}

.aim-scan-task h3 {
  margin: 0;
}

.aim-scan-badge {
  justify-self: start;
  margin: 0;
  padding: 0.3rem 0.8rem;
  border-radius: var(--radius-circle, 999px);
  background: color-mix(in srgb, var(--primary, #ff6f5e) 18%, transparent);
  font-size: var(--text-s);
  font-weight: 600;
}

.aim-scan-starter {
  margin: 0;
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius, 5px);
  background: color-mix(in srgb, var(--text-light, #fafaf8) 8%, transparent);
  white-space: pre-wrap;
  word-break: break-word;
  font: inherit;
}

.aim-scan-copy,
.aim-scan-download,
[data-aim-delete] {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-block: 0.6rem;
  padding-inline: 1.25rem;
  border-radius: var(--radius, 5px);
  border: var(--border, 1px solid color-mix(in srgb, var(--text-light, #fafaf8) 30%, transparent));
  background: transparent;
  color: inherit;
  font-weight: 600;
  font-size: var(--text-s);
  text-decoration: none;
  cursor: pointer;
}

/* The download is the one filled action on the page -- the file he actually
 * leaves with. Copy, the workshop link and the delete control all stay
 * quiet outline controls, so nothing here competes with it for attention. */
.aim-scan-download {
  border: none;
  background: var(--btn-background, var(--primary, #ff6f5e));
  color: var(--btn-text-color, var(--primary-ultra-light, #fff));
}

.aim-scan-download:hover {
  background: var(--btn-background-hover, var(--primary-hover, #ff6f5e));
}

.aim-scan-profile {
  display: grid;
  gap: var(--paragraph-spacing, 1em);
}

.aim-scan-yours {
  padding: var(--space-s, 1rem);
  border-radius: var(--radius, 5px);
  background: color-mix(in srgb, var(--text-light, #fafaf8) 6%, transparent);
}

.aim-scan-yours p {
  margin-block-start: 0;
}

@media (width < 30rem) {
  body.aim-scan-result main { padding-inline: 1rem; }
}
