/* =============================================================================
   MINET BUY ONLINE — storefront
   The purchase journey and the catalogue: hero, products, the trip form,
   compare, documents, payment, confirmation, and the legal pages.
   Built to assets/landing page.pdf.

   ONE OF THREE, LOADED IN THIS ORDER ON EVERY PAGE (layouts/shop.blade.php):
       base.css  →  shop.css  →  portal.css
   Anything the client portal also renders belongs in base.css, not here.

   Every colour, font, size and radius resolves to a token from
   brand/minet-tokens.css (served at /brand/minet-tokens.css). There is not one
   hex literal in this file, by rule — skill: minet-brand.
   ========================================================================== */


/* ---------- Hero ---------- */

.hero { padding-block: var(--space-16) var(--space-12); text-align: center; }
.hero__eyebrow {
    margin: 0 0 var(--space-3);
    color: var(--minet-red);
    font-size: var(--fs-eyebrow);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--tracking-eyebrow);
}
.hero__title {
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-h1);
    line-height: var(--lh-tight);
    color: var(--minet-ink);
}
.hero__lede { margin: 0 auto; max-width: 44ch; color: var(--minet-text); }

/* ---------- Filters ---------- */

/* On the SAME grid as the product cards below — same columns, same gap — so
   the filters run edge to edge and line up with the cards at every width:
   industry over the first card, search across the rest. They used to be two
   fixed widths, centred, whose edges met nothing on the page. */
.filters {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-6);
    margin-top: var(--space-12);
}
.filters__field { display: flex; flex-direction: column; gap: var(--space-2); text-align: left; min-width: 0; }
.filters__field--industry { grid-column: span 1; }
.filters__field--search { grid-column: span 3; }
.filters__label {
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-ink);
}
.filters__control { position: relative; display: flex; }
.filters__control select,
.filters__control input {
    width: 100%;
    height: var(--control-height);
    padding-inline: var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: var(--minet-surface);
    color: var(--minet-text);
    font-family: var(--font-body);
    font-size: var(--fs-body);
    appearance: none;
}
.filters__control input { padding-right: var(--space-12); }
.filters__control select:hover,
.filters__control input:hover { border-color: var(--minet-line); }
.filters__icon {
    position: absolute;
    right: var(--space-4);
    top: 50%;
    transform: translateY(-50%);
    color: var(--minet-muted);
    pointer-events: none;
}

/* ---------- Product grid ---------- */

.products { padding-bottom: var(--space-16); }
.products__grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-6);
    margin: 0;
    padding: 0;
    list-style: none;
}
.products__empty {
    margin-top: var(--space-8);
    padding: var(--space-8);
    background: var(--minet-surface);
    border-radius: var(--radius);
    text-align: center;
    color: var(--minet-muted);
}
.product-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--minet-surface);
    border-radius: var(--radius);
    overflow: hidden;
}
.product-card__media { aspect-ratio: 16 / 10; overflow: hidden; }
.product-card__media img { width: 100%; height: 100%; object-fit: cover; }
.product-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    flex: 1;
    padding: var(--space-4);
}
.product-card__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-card-title);
    line-height: var(--lh-heading);
    color: var(--minet-ink);
}
.product-card__summary { margin: 0; flex: 1; font-size: var(--fs-small); color: var(--minet-muted); }
/* Two equal columns, always side by side: the pair fills the card and lines
   up with every other card's. As wrapping flex items, "Learn More" dropped
   under "Get Quote" whenever a card was narrow, and the two were never the
   same width. The tighter inline padding is what lets the label fit the
   narrowest card (four across, just above 1024px). */
.product-card__actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
.product-card__actions .btn { padding-inline: var(--space-2); }

/* ---------- Next-step page ---------- */

.next-step { padding-block: var(--space-16); }
.next-step__inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-12);
    align-items: center;
}
.next-step__media { border-radius: var(--radius); overflow: hidden; aspect-ratio: 16 / 10; }
.next-step__media img { width: 100%; height: 100%; object-fit: cover; }
.next-step h1 {
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    line-height: var(--lh-heading);
    color: var(--minet-ink);
}
.next-step__note {
    margin: var(--space-6) 0;
    padding: var(--space-4);
    background: var(--minet-surface);
    border-radius: var(--radius);
    font-size: var(--fs-small);
}
.next-step__actions { display: flex; gap: var(--space-3); flex-wrap: wrap; }

/* ---------- Responsive ----------
   Most Kenyan traffic is a phone on mobile data (skill: buyonline-storefront). */

@media (max-width: 1024px) {
    .products__grid { grid-template-columns: repeat(2, 1fr); }
    .filters { grid-template-columns: repeat(2, 1fr); }
    .filters__field--search { grid-column: span 1; }
    .next-step__inner { grid-template-columns: 1fr; }}
@media (max-width: 720px) {

    .hero { padding-block: var(--space-8); }
    .products__grid { grid-template-columns: 1fr; }
    .filters { grid-template-columns: 1fr; }}

/* ---------- Funnel steps ----------
   Added for the travel journey (docs/design/travel-journey.md). Same rule as
   everything above: no literal values, only tokens. */

/* ONE LEFT EDGE. The header was centred over a form that is not: the title
   sat in the middle of the page while every question under it started at the
   left margin, and the stepper floated between the two. Eyebrow, title, lede
   and stepper now start where the questions start, and a rule closes the
   header so what follows reads as the form. */
.step-header {
    margin-bottom: var(--space-8);
    padding-bottom: var(--space-6);
    border-bottom: 1px solid var(--minet-line);
    text-align: left;
}
.step-header__title {
    margin: 0 0 var(--space-3);
    font-family: var(--font-display);
    font-size: var(--fs-h1);
    line-height: var(--lh-tight);
    color: var(--minet-ink);
}
.step-header__lede { margin: 0; color: var(--minet-text); }
/* Where am I, how much is left — UNDER the title, not over it. Above, it was
   the first thing on every step and pushed "what is this page" down the screen
   to make room for "where in the purchase am I"; the page's own name comes
   first, and its place in the sequence follows. */
.steps {
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
    margin: var(--space-6) 0 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-small);
}
.steps__item { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--minet-muted); }
.steps__marker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px; height: 26px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--minet-line);
    font-size: var(--fs-legal);
    font-weight: 700;
}
.steps__item[data-state="current"] { color: var(--minet-ink); font-weight: 700; }
/* "Step 1 of 5", in words. Wide screens name all five steps in the row above
   and do not need it; a phone folds that row down to its numbers, and four bare
   circles do not say how many are left (buyonline/docs/UX_PRINCIPLES.md §4). */
.steps__count {
    display: none;
    margin: var(--space-2) 0 0;
    font-size: var(--fs-small);
    color: var(--minet-muted);
}
.steps__item[data-state="current"] .steps__marker {
    background: var(--minet-red-action);
    border-color: var(--minet-red-action);
    color: var(--minet-white);
}
.steps__item[data-state="done"] { color: var(--minet-text); }
.steps__item[data-state="done"] .steps__marker {
    background: var(--minet-success);
    border-color: var(--minet-success);
    color: var(--minet-white);
}

/* ---------- Forms ---------- */

.field-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-6);
    margin-bottom: var(--space-4);
}
.field-grid .field { margin-bottom: 0; }
/* Direction of travel: a real radio, styled — so it keeps keyboard support and
   announces itself correctly, which a pair of styled <div>s would not. */
/* ---- The trip form, asked as four questions -------------------------------

   The supplied mockup's one good structural idea: a titled question instead of
   a column of bare labels. Headings are INK, not
   the mockup's red — there every heading and every label is red, which leaves
   red meaning nothing by the time it reaches the button that matters. */
/* BETWEEN questions must exceed WITHIN them, or four titled questions read as
   one column. Taking this to --space-3 on its own inverted that: 12px to the
   next question's heading against 32px between two fields of the same one, so
   the date-of-birth rows sat closer to the next question than to the count
   they belong to. The inner gaps came down with it instead — the form is
   still far tighter than the 48px/32px it started at, and the grouping holds. */
.ask { margin: 0 0 var(--space-8); border: 0; padding: 0; min-width: 0; }
.ask__title {
    /* More room above a question than below it, so the heading belongs to the
       answer under it and not to the one it follows. */
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    /* Stated, because two of the five are a <legend> and three an <h2>: left to
       the browser the legends were regular and the headings bold, in one
       column. */
    font-weight: 700;
    /* Headings set their own leading: inheriting the body's is loose enough to
       read as two separate lines once a question wraps on a phone. */
    line-height: 1.2;
    color: var(--minet-ink);
    /* A <legend> is not a grid/flex item and ignores width by default; float
       clears it out of the fieldset's inline box so it behaves like the <h2>
       its sibling sections use. The padding reset matters too — a legend
       carries inline padding by default, which would indent it a few pixels
       past the headings it sits in a column with. */
    float: left;
    width: 100%;
    padding: 0;
}
/* Whatever follows the floated title starts under it, hint or not. */
.ask__title + * { clear: both; }
/* A hint is for something the question does not already say. Three of the five
   only repeated their heading and are gone (buyonline/docs/UX_PRINCIPLES.md §10, question 3). Where
   one stays, the title gives up half its gap so the two read as a pair — done
   on the title, because a cleared element's own negative margin cannot climb
   back over the float it has just cleared. */
.ask__title:has(+ .ask__hint) { margin-bottom: var(--space-2); }
.ask__hint {
    margin: 0 0 var(--space-4);
    font-size: var(--fs-small);
    color: var(--minet-muted);
}
.ask .field:last-child,
.ask .field-grid:last-child { margin-bottom: 0; }
/* An option group with more of the same question under it: the dates of birth
   sat flush against the options they follow. */
.ask .choice-group:not(:last-child) { margin-bottom: var(--space-6); }
/* ---- One question at a time ----------------------------------------------

   js/travel-trip.js marks the questions not yet reached, and they are not shown
   at all: each appears when the one before it is answered. They used to be
   listed as quiet titles under hairlines, which read as a form of empty rows.
   Only the script sets the attribute — with no script, every question is
   simply open, so the form can always be filled in. */
.ask[data-stage="upcoming"] { display: none; }
.choice-group { display: flex; gap: var(--space-4); flex-wrap: wrap; }
.choice { flex: 1 1 260px; cursor: pointer; }
.choice input { position: absolute; opacity: 0; width: 0; height: 0; }
.choice__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4) var(--space-6);
    border: 1px solid var(--minet-control-border);
    border-radius: var(--radius);
    background: var(--minet-white);
}
.choice:hover .choice__body { border-color: var(--minet-ink); }
.choice__label { font-weight: 700; color: var(--minet-ink); }
.choice__hint { font-size: var(--fs-small); color: var(--minet-muted); }
/* Chosen: the edge turns red and doubles, drawn as an inset shadow so the
   option does not grow by a pixel and shove its neighbours when picked. */
.choice input:checked + .choice__body {
    border-color: var(--minet-red-action);
    box-shadow: inset 0 0 0 1px var(--minet-red-action);
}
/* Selection is not signalled by colour alone: the chosen option carries a
   filled marker, the way a radio does. */
.choice__body { position: relative; padding-right: var(--space-12); }
.choice__body::after {
    content: "";
    position: absolute;
    right: var(--space-4);
    top: var(--space-4);
    width: 18px;
    height: 18px;
    border: 1px solid var(--minet-control-border);
    border-radius: 50%;
    background: var(--minet-white);
}
.choice input:checked + .choice__body::after {
    border-color: var(--minet-red-action);
    background: var(--minet-red-action);
    box-shadow: inset 0 0 0 3px var(--minet-white);
}
/* INK, where every other focus ring on the site is red. A chosen option is
   edged in red, so a red ring round an option that is merely focused said
   "chosen" about one that was not. */
.choice input:focus-visible + .choice__body {
    outline: var(--focus-ring);
    outline-color: var(--minet-ink);
    outline-offset: var(--focus-offset);
}
/* ---- Options on the form's grid -------------------------------------------

   Direction of travel and who is travelling: the plain bordered option above,
   laid on the same three columns as the dates and the dates of birth, so every
   box on the form starts and stops on the same lines. They were pills — the
   mockup's shape — and that was a second shape at a second radius for what is
   still "answer here"; the brand is square-edged and so is every field.

   NOTHING is selected until somebody selects it (#4 — a pre-ticked "Inbound"
   misprices every Kenyan outbound trip whose customer does not notice), and
   the chosen option is EDGED in red with a filled marker rather than flooded
   with it: buyonline/docs/UX_PRINCIPLES.md §7 gives a view one filled primary,
   and that is the button the page exists for. */
.choice-group--grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
.choice-group--grid .choice { flex: none; }
.choice-group--grid .choice__body { height: 100%; padding-block: var(--space-3); }
.choice-group--grid .choice__body::after { top: var(--space-3); }
/* ---- Direction of travel, as pills ---------------------------------------

   The mockup's shape, recalled by the team (13 Oct 2026) for this one
   question. TWO columns across the full width, one per answer (TravelType has
   exactly two, by design). Until 14 Oct they sat on the form's three columns
   to line up with the date fields below, which left a third of the row empty
   and squeezed each hint onto two lines; the user chose the room over the
   alignment.

   Chosen is a red FILL with white on it, so --minet-red-action is the only
   correct red here. Unchosen is white with a field's edge: not the mockup's
   second, paler red, and not grey, which read as switched off. */
.choice-group--pills { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-6); }
.choice-group--pills .choice { flex: none; }
.choice-group--pills .choice__body {
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    height: 100%;
    padding: var(--space-3) var(--space-6);
    border-radius: var(--radius-pill);
}
/* The label and its hint stack beside the icon. */
.choice__text { display: flex; flex-direction: column; gap: 2px; }
.choice-group--pills .choice__icon { flex: none; color: var(--minet-muted); }
.choice-group--pills .choice input:checked + .choice__body {
    background: var(--minet-red-action);
    border-color: var(--minet-red-action);
    box-shadow: none;
}
.choice-group--pills .choice input:checked + .choice__body .choice__label,
.choice-group--pills .choice input:checked + .choice__body .choice__hint,
.choice-group--pills .choice input:checked + .choice__body .choice__icon {
    color: var(--minet-white);
}
/* The corner marker the square option draws has no corner to sit in here. On a
   filled pill the fill IS the marker — a change of tone as well as of hue, so
   it survives greyscale — and the icon and wording differ between the two. */
.choice-group--pills .choice__body::after { content: none; }
/* Reason for travel, on the documents step: four short answers, two to a
   row. */
.documents__reason { margin-top: var(--space-8); }
.choice-group--tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-4); }
.choice-group--tiles .choice { flex: none; }
.choice-group--tiles .choice__body { height: 100%; }
@media (max-width: 560px) {
    .choice-group--tiles { grid-template-columns: 1fr; }}
/* The no-JS traveller-count companion. Bottom-aligned so it sits on the same
   line as the select it belongs to rather than floating beside its label. */
.recount { display: flex; flex-direction: column; justify-content: flex-end; }
.recount .btn { align-self: flex-start; }
/* The countries field: Select2 draws the control, so the wrapper is a plain
   block rather than the flex row an input and its icon need. */
.control--plain { display: block; }
.traveller-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); margin-top: var(--space-4); }
.traveller-row__label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: var(--fs-small);
    color: var(--minet-muted);
}
.form-actions {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: var(--space-8);
}
/* The buttons that move a purchase on are as tall as the fields above them and
   set in body size: at 44px and 14px the one action the page exists for was
   the smallest control on it. */
.form-actions .btn { min-height: var(--control-height-form); font-size: var(--fs-body); }
.form-actions--centred { justify-content: center; }
/* A date field says what it is: the calendar mark appears only beside the
   enhanced field. With scripting off the browser's own date input draws one of
   its own, and two would sit on top of each other. */
.control__icon--date { display: none; }
.flatpickr-alt + .control__icon--date { display: block; }
.alert__title { margin: 0 0 var(--space-2); font-weight: 700; color: var(--minet-ink); }
.alert ul { margin: 0; padding-left: var(--space-6); font-size: var(--fs-small); }
.alert--error:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* ---------- Compare ---------- */

.trip-recap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    flex-wrap: wrap;
    padding: var(--space-6);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.trip-recap__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-body);
    color: var(--minet-ink);
}
.trip-recap__list { display: flex; gap: var(--space-8); flex-wrap: wrap; margin: 0; }
.trip-recap__list dt { font-size: var(--fs-legal); color: var(--minet-muted); text-transform: uppercase; letter-spacing: var(--tracking-eyebrow); }
.trip-recap__list dd { margin: var(--space-1) 0 0; font-weight: 600; color: var(--minet-ink); }
/* Who would not quote, and why. Sits under the offers rather than beside
   them: it is an explanation, not a plan, and it must never read as one. */
.quotes-declined {
    margin-top: var(--space-8);
    padding: var(--space-6);
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
    background: var(--minet-surface);
}
.quotes-declined h2 { margin: 0 0 var(--space-2); font-size: var(--fs-h3); }
.quotes-declined > p { margin: 0 0 var(--space-4); font-size: var(--fs-small); color: var(--minet-muted); }
.quotes-declined ul { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.quotes-declined li { display: grid; gap: var(--space-1); }
.quotes-declined strong { font-size: var(--fs-small); }
.quotes-declined span { font-size: var(--fs-small); color: var(--minet-muted); }
.quotes-empty {
    margin-top: var(--space-8);
    padding: var(--space-12) var(--space-6);
    border: 1px dashed var(--minet-line);
    border-radius: var(--radius);
    text-align: center;
}
.quotes-empty h2 {
    margin: 0 0 var(--space-3);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.quotes-empty p { margin: 0 auto var(--space-3); max-width: 56ch; color: var(--minet-muted); }
@media (max-width: 1024px) {
    .field-grid { grid-template-columns: repeat(2, 1fr); }
    /* The trip form keeps its three columns to the phone breakpoint, so
       departure, return and "Days travelling" (last, since 14 Oct 2026) stay
       on one row: at two, the days field was left alone on the row below. */
    .trip-form .field-grid { grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
    .choice-group--grid,
    .choice-group--pills,
    .traveller-list { gap: var(--space-4); }}
@media (max-width: 720px) {
    .field-grid,
    .trip-form .field-grid { grid-template-columns: 1fr; }
    .choice-group--grid,
    .choice-group--pills { grid-template-columns: 1fr; gap: var(--space-3); }
    /* Less air above the form on a phone, so the first question AND the list
       of what follows it are on the first screen, above the button bar. */
    .step { padding-top: var(--space-8); }
    .step-header { margin-bottom: var(--space-6); padding-bottom: var(--space-4); }
    .traveller-list { grid-template-columns: 1fr; gap: var(--space-4); }
    .steps { gap: var(--space-3); }
    .steps__label { display: none; }
    .steps__item[data-state="current"] .steps__label { display: inline; }
    .trip-recap { flex-direction: column; align-items: flex-start; }
    .form-actions { flex-direction: column-reverse; }
    .form-actions .btn { width: 100%; }
    /* The one action that leaves the page, kept in the thumb zone for the whole
       length of a long form (buyonline/docs/UX_PRINCIPLES.md §2). Sticky, not fixed: it
       stays inside the form, so it lets go at the footer instead of covering
       it. The way back rides beside it at its own width. */
    .form-actions--sticky {
        position: sticky;
        bottom: 0;
        z-index: 10;
        flex-direction: row;
        flex-wrap: nowrap;
        margin-inline: calc(var(--gutter) * -1);
        padding: var(--space-3) var(--gutter) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--minet-line);
        background: var(--minet-white);
    }
    /* The bar is 44px of button and its padding. Without this, tabbing down
       the form scrolls a field to the viewport's edge — which is now under
       the bar, along with its focus ring. */
    html:has(.form-actions--sticky) {
        scroll-padding-bottom: calc(var(--control-height-form) + var(--space-8) + env(safe-area-inset-bottom, 0px));
    }
    .form-actions--sticky .btn { width: auto; }
    .form-actions--sticky .btn--primary { flex: 1; }
    .steps__count { display: block; }}

/* ---------- Compare quotes ----------
   Tokens only, as everywhere else. */

/* Filters */
.quote-filters {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    flex-wrap: wrap;
    margin-top: var(--space-8);
}
.quote-filters__tiers {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
    border: 0;
    margin: 0;
    padding: 0;
}
.quote-filters__underwriter { flex: 1 1 260px; max-width: 360px; margin-left: auto; }
.quote-filters__search { flex: 1 1 260px; max-width: 360px; }
.quote-board .quote-filters { margin-top: 0; }
/* How many, and how they are arranged — one line under the filters. */
.quote-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin: var(--space-6) 0 var(--space-4);
}
.quote-toolbar .quote-count { margin: 0; }
/* Why these plans and in this order — under the count, as quiet as it is. */
.quote-order { margin: var(--space-1) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }
.quote-group-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap-target-min);
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-ink);
    cursor: pointer;
}
.quote-group-toggle[hidden] { display: none; }
.quote-group-toggle input { width: 18px; height: 18px; accent-color: var(--minet-red-action); }
/* One underwriter's plans: its name, how many, then the same grid. */
.quote-group + .quote-group { margin-top: var(--space-12); }
.quote-group__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    line-height: var(--lh-heading);
    color: var(--minet-ink);
}
.quote-group__count { margin: var(--space-1) 0 var(--space-4); font-size: var(--fs-small); color: var(--minet-muted); }
/* "Show all 18 plans" — under the list it extends, at the left edge the cards
   start from. */
.quote-more { margin: var(--space-6) 0 0; }
.quote-more[hidden] { display: none; }
.pill { cursor: pointer; }
.pill input { position: absolute; opacity: 0; width: 0; height: 0; }
.pill span {
    display: inline-flex;
    align-items: center;
    min-height: var(--button-height);
    padding-inline: var(--space-6);
    /* The control edge: a filter is something to tap, and on --minet-line it
       had no boundary once the grey board behind it was gone. */
    border: 1px solid var(--minet-control-border);
    border-radius: var(--radius-pill);
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-text);
    background: var(--minet-white);
}
.pill input:checked + span {
    background: var(--minet-red-action);
    border-color: var(--minet-red-action);
    color: var(--minet-white);
}
.pill input:focus-visible + span {
    outline: var(--focus-ring);
    outline-offset: var(--focus-offset);
}
.quote-count {
    margin: var(--space-6) 0 var(--space-4);
    font-size: var(--fs-small);
    color: var(--minet-muted);
}
/* The grid stacks on a phone rather than scrolling sideways: a carousel is
   where comparison dies on mobile (docs/design/travel-journey.md #13). */
.quote-grid {
    display: grid;
    /* `min(300px, 100%)`, not a bare 300px: a bare minimum is a FLOOR the
       track cannot go under, so on a narrower screen — or beside a card whose
       content will not shrink — the row grows past the viewport and the whole
       page scrolls sideways. */
    /* auto-FILL at 280px: four across on a desktop, so the four plans shown
       first make one whole row (three across left the fourth alone on a row of
       its own), and a short list keeps its cards at card width instead of
       stretching two of them across the page. */
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: var(--space-6);
    margin: 0;
    padding: 0;
    list-style: none;
    align-items: stretch;
}
.quote-card {
    display: flex;
    flex-direction: column;
    /* A grid item's floor is its min-content width unless it is told
       otherwise, and one unbreakable benefit line was enough to push every
       card wider than the screen. */
    min-width: 0;
    background: var(--minet-white);
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
}
/* The one lifted element on the page: a recommendation, and only ever with the
   reason printed beside it. */
.quote-card__badge {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    margin: 0;
    padding: var(--space-3) var(--space-4);
    background: var(--minet-surface);
    border-bottom: 1px solid var(--minet-line);
    border-radius: var(--radius) var(--radius) 0 0;
}
.quote-card__badge-tag {
    align-self: flex-start;
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    background: var(--minet-success);
    color: var(--minet-white);
    font-size: var(--fs-legal);
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.quote-card__badge-why { font-size: var(--fs-legal); color: var(--minet-muted); line-height: 1.45; }
.quote-card__head { padding: var(--space-4) var(--space-4) 0; }
/* The plan is the card's title: it is what differs from the card beside it. */
.quote-card__plan {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-card-title);
    line-height: var(--lh-heading);
    color: var(--minet-ink);
}
/* Who underwrites it: stated, a step quieter than the plan. */
.quote-card__underwriter {
    margin: var(--space-1) 0 0;
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-text);
}
/* Under its own heading the name would only repeat down the column. */
.quote-group .quote-card__underwriter { display: none; }
.quote-card__region { margin: var(--space-1) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }

/* ---------- The price block, on the card and in the details panel ---------- */

/* Set off by two hairlines, not by a grey box. The card sat on a grey board
   and carried a grey box of its own — grey, white, grey, three deep — and the
   price is the thing on the card that least wants to look recessed. */
.quote-price {
    margin: var(--space-4) var(--space-4) 0;
    padding-block: var(--space-4);
    border-block: 1px solid var(--minet-line);
}
.quote-price__label {
    margin: 0 0 var(--space-1);
    font-size: var(--fs-legal);
    font-weight: 700;
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--minet-muted);
}
.quote-price__amount {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.75rem;
    line-height: 1.15;
    font-weight: 700;
    color: var(--minet-ink);
    font-variant-numeric: tabular-nums;
}
/* The basis travels with the figure, so nobody has to guess what it buys —
   beside it, on the same line, rather than as a line of its own under it. */
.quote-price__basis {
    display: inline;
    margin-left: var(--space-1);
    font-family: var(--font-body);
    font-size: var(--fs-small);
    font-weight: 400;
    color: var(--minet-muted);
}
/* What the customer is charged, in shillings, and the rate that got there —
   under the underwriter's dollar premium, which leads. Small, but in the body
   colour and not the muted one: it is the amount that leaves their phone. */
.quote-price__converted {
    margin: var(--space-2) 0 0;
    font-size: var(--fs-small);
    color: var(--minet-text);
    font-variant-numeric: tabular-nums;
}
/* Premium finance, when there is a real offer. Red as the mockup has it — it
   is the cheaper-looking number, and it should read as the promotional one. */
.quote-price__instalment {
    margin: var(--space-2) 0 0;
    font-size: var(--fs-small);
    font-weight: 700;
    /* On --minet-surface, not on white: --minet-red-action is 4.35:1 there and
       this is small bold text. The brand guide's "red is not body text" rule,
       and the darker red clears it at 5.70:1. */
    color: var(--minet-red-hover);
    font-variant-numeric: tabular-nums;
}
.benefit-table { margin: 0; display: grid; }
.benefit {
    display: grid;
    /* A PROPORTION, not `auto`. Both tracks have to be able to shrink — `auto`
       alone takes the value's min-content width, which for an unwrappable
       sentence is the whole sentence — but a greedy `auto` value column also
       squeezes the benefit's name into three lines beside a value on one. A
       fixed split keeps the rows lining up from card to card, which is the
       whole point of putting them side by side. */
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    gap: var(--space-4);
    align-items: baseline;
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--minet-line);
}
/* Zebra rather than hairlines: a thirty-row schedule read in one panel is
   easier to track across than down, and the mockup draws it that way. */
.benefit:nth-child(odd) { background: var(--minet-surface); }
.benefit { border-bottom: 0; padding: var(--space-3) var(--space-4); }
.benefit dt {
    min-width: 0;
    font-size: var(--fs-small);
    color: var(--minet-text);
    overflow-wrap: break-word;
}
/* NO `white-space: nowrap`. It was there to keep "USD 1,500" on one line, and
   it did — but a schedule imported from a rate card also carries "See
   description and definition in general conditions", and an unbreakable
   sentence in an `auto` track made every card as wide as its longest benefit.
   Measured at 1245px against a 749px viewport: the page scrolled sideways and
   the values were clipped by the card beside them. Numbers keep their own
   integrity through the nbsp the formatter writes; prose wraps. */
.benefit dd {
    min-width: 0;
    margin: 0;
    font-size: var(--fs-small);
    font-weight: 700;
    color: var(--minet-ink);
    text-align: right;
    overflow-wrap: break-word;
    font-variant-numeric: tabular-nums;
}
.benefit__limit--included { font-weight: 600; color: var(--minet-muted); }
/* Listed in order to be excluded: lighter than a benefit that is paid. */
.benefit__limit--excluded { font-weight: 400; }

/* ---------- The confirmation card ---------- */

/* "That worked — and here is what you can do next" (components/toast.blade.php).

   INK, with white on it, as the compare bar is: the storefront's one other
   thing that floats over the page, and drawn the same so the two read as the
   same kind of object. No shadow — the brand is flat — so the dark ground is
   what lifts it off the white page behind.

   In the flow of the page by default, which is all a browser without scripting
   gets. js/toast.js adds --floating. */
.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    margin-bottom: var(--space-8);
    padding: var(--space-4) var(--space-4) var(--space-4) var(--space-6);
    border-radius: var(--radius);
    background: var(--minet-ink);
    color: var(--minet-white);
}
.toast__mark { flex: none; margin-top: 2px; }
.toast__body { flex: 1 1 auto; min-width: 0; }
.toast__title { margin: 0; font-family: var(--font-display); font-size: var(--fs-card-title); line-height: var(--lh-heading); font-weight: 700; }
.toast__text { margin: var(--space-1) 0 0; font-size: var(--fs-small); overflow-wrap: anywhere; }
.toast__actions { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-4); }
/* The outlined button, on a dark ground: white where it is ink on the page. */
.toast .btn--ghost { color: var(--minet-white); border-color: var(--minet-white); }
.toast .btn--ghost:hover { background: var(--minet-white); color: var(--minet-ink); }
.toast :focus-visible { outline-color: var(--minet-white); }
.toast__close {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--tap-target-min);
    height: var(--tap-target-min);
    margin: calc(var(--space-2) * -1) calc(var(--space-2) * -1) 0 0;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--minet-white);
    cursor: pointer;
}
.toast__close[hidden] { display: none; }
/* Lifted into the corner, below the utility bar and the site header so it
   covers neither at the top of a page. At the TOP on a phone as well: the
   bottom of a phone screen already belongs to the cookie notice, the compare
   bar and the form's own action bar, and a confirmation under any of them is
   a confirmation nobody sees. */
.toast--floating {
    position: fixed;
    top: calc(var(--utility-bar-height) + var(--header-height) + var(--space-4));
    right: var(--gutter);
    z-index: 70;
    width: min(30rem, calc(100vw - 2 * var(--gutter)));
    margin: 0;
}
@media (max-width: 720px) {
    .toast--floating {
        top: var(--space-3);
        left: var(--space-3);
        right: var(--space-3);
        width: auto;
        padding-left: var(--space-4);
    }
    .toast__actions > * { flex: 1 1 auto; }
    .toast__actions .btn { width: 100%; }}

/* ---------- The board the list sits on ---------- */

/* The filters, the count and the grid, on the page's own white. This was one
   grey field, as the compare mockup draws it — and it put a grey panel under
   another grey panel (the trip recap) with a third inside every card. Grey is
   now kept for what is READ BACK, as on the trip form: the recap above is the
   one grey panel on this screen, and the cards are edged rather than floated. */
.quote-board { margin-top: var(--space-8); }

/* ---------- See details ---------- */

/* A DISCLOSURE FIRST. With no JavaScript this opens inside the card and the
   schedule is readable; quote-details.js then lifts the panel into the
   mockup's modal. */
/* The toggle is a 44px line of text now, so it needs no margin of its own to
   stand clear of the price's closing rule. */
.quote-details { margin: var(--space-1) var(--space-4) 0; }
/* A TEXT LINK. It was a pink-tinted pill with an arrow pointing off the page —
   a decorated button for something that opens a panel here. Ink, underlined,
   the way a link in running text is; the underline thickens on hover, so the
   change is not one of colour alone. Still a 44px target. */
.quote-details__toggle {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-target-min);
    color: var(--minet-ink);
    font-size: var(--fs-small);
    font-weight: 600;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.25em;
    cursor: pointer;
    list-style: none;
}
.quote-details__toggle::-webkit-details-marker { display: none; }
.quote-details__toggle:hover { text-decoration-thickness: 2px; }
/* The one plan's own reference and how long its price holds, in the panel. */
.quote-details__ref { margin: var(--space-2) 0 0; font-size: var(--fs-legal); color: var(--minet-muted); }
.quote-details__panel { padding: var(--space-4) 0 0; }
.quote-details__head { display: grid; gap: var(--space-4); }
.quote-details__plan {
    margin: 0;
    /* The display face, as the card sets it. Left to inherit, the same
       insurer name was set in two different typefaces depending on whether
       you were reading the card or the panel. */
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.quote-details__title {
    margin: var(--space-6) 0 var(--space-3);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.quote-details__close { display: none; }

/* ---------- …and the modal it becomes once enhanced ---------- */

/* Only under `.js`, which quote-details.js sets on <html>. Without it every
   rule here is inert and the disclosure stays a disclosure. */
.js .quote-details[open] > .quote-details__panel {
    position: fixed;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    z-index: 60;
    translate: -50% -50%;
    inline-size: min(52rem, calc(100vw - var(--space-8)));
    max-block-size: min(46rem, calc(100vh - var(--space-8)));
    overflow-y: auto;
    padding: var(--space-8);
    background: var(--minet-white);
    border-radius: var(--radius);
    box-shadow: 0 1.5rem 3rem color-mix(in srgb, var(--minet-black) 22%, transparent);
}
.js .quote-details[open]::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 59;
    background: color-mix(in srgb, var(--minet-black) 55%, transparent);
}
.js .quote-details[open] > .quote-details__panel .quote-details__head {
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    align-items: start;
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--minet-line);
}
@media (max-width: 48rem) {
    .js .quote-details[open] > .quote-details__panel { padding: var(--space-6); }
    .js .quote-details[open] > .quote-details__panel .quote-details__head { grid-template-columns: 1fr; }}
/* Inside the panel the price sits beside the plan's name, under a rule the
   head already draws: no margin and no hairlines of its own. */
.quote-details__head .quote-price { margin: 0; padding-block: 0; border: 0; }
.js .quote-details__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    inset-block-start: var(--space-4);
    inset-inline-end: var(--space-4);
    width: var(--tap-target-min);
    height: var(--tap-target-min);
    background: none;
    border: 0;
    border-radius: var(--radius);
    color: var(--minet-ink);
    cursor: pointer;
}
.js .quote-details__close:hover { background: var(--minet-surface); }
.js .quote-details[open] > .quote-details__panel { padding-top: calc(var(--space-8) + var(--tap-target-min)); }
/* The actions repeat inside the panel — somebody who has just read the
   schedule should not have to close it to act on it. On the card itself the
   panel's copy is the only one that shows when the modal is open. */
.quote-details__panel .quote-card__actions { margin-top: var(--space-6); }
/* ONE SET OF ACTIONS AT A TIME. The panel repeats them so somebody who has
   just read the schedule can act on it — but with the panel open and no
   JavaScript to lift it into a modal, the card showed two identical Purchase
   buttons stacked inside it. The footer's copy stands down while the panel is
   open; with JavaScript the panel is a modal and the footer is behind the
   backdrop anyway. */
.quote-details[open] ~ .quote-card__foot .quote-card__actions { display: none; }
/* Pinned to the bottom of the card, so the buttons of three cards in a row
   sit on one line whether an insurer's name runs to one line or two. */
.quote-card__foot { margin-top: auto; padding: var(--space-4); }
.quote-card__meta { margin: 0 0 var(--space-3); font-size: var(--fs-legal); color: var(--minet-muted); }
/* A plan an advisor has to confirm. Stated, not coloured: the condition is
   information, and a customer reading it with the sound off or in greyscale
   has to get the same answer. */
.quote-card__referral {
    margin: 0 0 var(--space-3);
    padding: var(--space-3);
    background: var(--minet-surface);
    font-size: var(--fs-small);
    color: var(--minet-text);
}
.compare-table__referral {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-legal);
    color: var(--minet-muted);
    text-align: left;
}
/* The same condition again, on the form where somebody acts on it. Stated and
   not coloured, for the same reason as the card: a customer reading this in
   greyscale must get the same answer as one who is not. */
.referral-reason {
    display: flex;
    gap: var(--space-3);
    /* Centred rather than nudged down by a fraction of an em: the condition is
       a sentence, and an optical offset here would be the only spacing literal
       in the file that is not a token. */
    align-items: center;
    margin: 0 0 var(--space-6);
    padding: var(--space-4);
    background: var(--minet-surface);
    font-size: var(--fs-small);
    color: var(--minet-text);
}
.referral-reason .icon { flex: none; color: var(--minet-muted); }
/* Purchase, filled, over Generate Quote, outlined — full width, stacked, so
   the pair reads top-down as "the action" and "the other thing you can do".
   The form wrapping Purchase is a grid item like any other. */
.quote-card__actions {
    display: grid;
    gap: var(--space-2);
}
.quote-card__actions > form { display: grid; }
.quote-card__actions .btn { width: 100%; }
.quote-card__wording { margin: var(--space-3) 0 0; font-size: var(--fs-small); }
.quotes-none {
    margin-top: var(--space-8);
    padding: var(--space-8);
    background: var(--minet-surface);
    border-radius: var(--radius);
    text-align: center;
    color: var(--minet-muted);
}
.compare-help {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    flex-wrap: wrap;
    margin-top: var(--space-12);
    padding: var(--space-6);
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
}
.compare-help p { margin: 0; max-width: 60ch; color: var(--minet-muted); font-size: var(--fs-small); }
.next-step__panel { max-width: 60ch; }
.next-step__ref {
    margin: 0 0 var(--space-6);
    font-size: var(--fs-small);
    color: var(--minet-muted);
}
.next-step__ref strong { color: var(--minet-ink); letter-spacing: .04em; }
@media (max-width: 720px) {
    .quote-filters { flex-direction: column; align-items: stretch; }
    /* `flex: 0 0 auto`, not only the width: the filters stack here, so the
       320px basis the search box has on a wide screen became its HEIGHT — a
       280px hole between the search field and the plan count. */
    .quote-filters__search,
    .quote-filters__underwriter { flex: 0 0 auto; max-width: none; margin-left: 0; }
    .quote-grid { grid-template-columns: 1fr; }
    .compare-help { flex-direction: column; align-items: flex-start; }}

/* ---------- Traveller documents ---------- */

.documents {
    display: grid;
    grid-template-columns: 1fr 320px;
    gap: var(--space-12);
    align-items: start;
    margin-top: var(--space-8);
}
.documents__warning {
    padding: var(--space-4) var(--space-6);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.documents__warning p { margin: 0; font-size: var(--fs-small); }
.documents__warning strong { color: var(--minet-ink); }
.documents__progress {
    margin: var(--space-6) 0 var(--space-4);
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-ink);
}
.slots { display: grid; gap: var(--space-6); margin: 0; padding: 0; list-style: none; }
.slot {
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
    padding: var(--space-6);
}
.slot__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
}
.slot__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-card-title);
    color: var(--minet-ink);
}
/* State is carried by a word, never by colour alone. */
.slot__status {
    margin: 0;
    font-size: var(--fs-legal);
    font-weight: 700;
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--minet-muted);
}
.slot[data-state="confirmed"] .slot__status { color: var(--minet-success); }
.slot[data-state="failed"] .slot__status,
.slot[data-state="unreadable"] .slot__status { color: var(--minet-danger); }
.slot[data-state="needs_review"] .slot__status { color: var(--minet-warning); }
.slot__hint { margin: var(--space-2) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }
.dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    margin-top: var(--space-4);
    padding: var(--space-12) var(--space-6);
    border: 1px dashed var(--minet-line-strong, var(--minet-grey));
    border-radius: var(--radius);
    background: var(--minet-surface);
    cursor: pointer;
    text-align: center;
}
.dropzone:hover, .dropzone.is-over {
    border-color: var(--minet-red-action);
    background: var(--minet-white);
}
.dropzone:focus-within { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.dropzone__icon { display: inline-flex; color: var(--minet-red); }
.dropzone__title { font-weight: 700; color: var(--minet-ink); }
.dropzone__meta { font-size: var(--fs-small); color: var(--minet-muted); }
.slot__busy { margin-top: var(--space-4); }
.slot__busy-label { margin: 0 0 var(--space-2); font-size: var(--fs-small); color: var(--minet-muted); }
.progress {
    height: 6px;
    background: var(--minet-surface);
    border-radius: var(--radius-pill);
    overflow: hidden;
}
.progress__bar {
    display: block;
    height: 100%;
    width: 0;
    background: var(--minet-red-action);
    transition: width .2s ease;
}
.slot__file {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.slot__file-name { margin: 0; font-size: var(--fs-small); color: var(--minet-ink); font-weight: 600; }
.slot__file-size { margin-left: var(--space-2); font-weight: 400; color: var(--minet-muted); }
.slot__review { margin-top: var(--space-6); }
.slot__review-lead { margin: 0 0 var(--space-4); font-size: var(--fs-small); color: var(--minet-text); }
.slot__fields {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}
.slot__fields .field { margin-bottom: 0; }
.slot__error { margin: var(--space-3) 0 0; font-size: var(--fs-small); font-weight: 600; color: var(--minet-danger); }
.slot__confirmed {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: var(--space-4);
}
.slot__confirmed-name { margin: 0; font-weight: 700; color: var(--minet-ink); }
/* Set off by a rule above it, not by a grey box. Grey is what has been read
   back to the customer; a consent is something they are being asked, and in a
   grey panel it sat on the page looking like the quote summary above it. */
.consent {
    margin-top: var(--space-8);
    padding-top: var(--space-6);
    border-top: 1px solid var(--minet-line);
}
.consent__check { display: flex; gap: var(--space-3); align-items: flex-start; cursor: pointer; }
.consent__check input { margin-top: 4px; width: 18px; height: 18px; flex: none; accent-color: var(--minet-red-action); }
.consent__check span { font-size: var(--fs-small); color: var(--minet-ink); }
.consent__detail { margin: var(--space-3) 0 0 30px; font-size: var(--fs-legal); color: var(--minet-muted); }
.documents__summary {
    position: sticky;
    top: var(--space-6);
    padding: var(--space-6);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.documents__summary-title {
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-card-title);
    color: var(--minet-ink);
}
.documents__summary-note { margin: 0 0 var(--space-6); font-size: var(--fs-legal); color: var(--minet-muted); }
@media (max-width: 1024px) {
    .documents { grid-template-columns: 1fr; }
    .documents__summary { position: static; order: -1; }}
@media (max-width: 720px) {
    .slot__fields { grid-template-columns: 1fr; }
    .dropzone { padding: var(--space-8) var(--space-4); }}

/* ---------- Payment ---------- */

.payment {
    display: grid;
    grid-template-columns: 1fr 360px;
    gap: var(--space-12);
    align-items: start;
    margin-top: var(--space-8);
}
.payment__main { display: grid; gap: var(--space-6); }
.traveller-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}
.traveller-card {
    padding: var(--space-4);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.traveller-card__name { margin: 0; font-weight: 700; color: var(--minet-ink); }
.traveller-card__meta {
    margin: var(--space-1) 0 0;
    font-size: var(--fs-small);
    color: var(--minet-muted);
    font-variant-numeric: tabular-nums;
}
.payment__side { position: sticky; top: var(--space-6); display: grid; gap: var(--space-4); }
.payment__box {
    padding: var(--space-6);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.payment__total-label {
    margin: 0;
    font-size: var(--fs-legal);
    font-weight: 700;
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--minet-muted);
}
.payment__total {
    margin: var(--space-1) 0 0;
    font-family: var(--font-display);
    font-size: 2rem;
    line-height: 1.1;
    font-weight: 700;
    color: var(--minet-ink);
    font-variant-numeric: tabular-nums;
}
.payment__total-basis {
    display: block;
    font-family: var(--font-body);
    font-size: var(--fs-small);
    font-weight: 400;
    color: var(--minet-muted);
}
.payment__held {
    margin: var(--space-2) 0 var(--space-6);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--minet-line);
    font-size: var(--fs-legal);
    color: var(--minet-muted);
}
.payment__ipf {
    margin: 0 0 var(--space-6);
    padding: var(--space-3) var(--space-4);
    background: var(--minet-white);
    border-radius: var(--radius);
    font-size: var(--fs-small);
    color: var(--minet-text);
}
.payment__reassure { margin: var(--space-4) 0 0; font-size: var(--fs-legal); color: var(--minet-muted); }
.choice--stacked { flex: 1 1 100%; display: block; margin-bottom: var(--space-2); }
/* The wait on the handset. */
.stk { padding-bottom: var(--space-4); }
.stk__title {
    margin: 0 0 var(--space-2);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.stk__body { margin: 0 0 var(--space-4); font-size: var(--fs-small); color: var(--minet-text); }
.stk__timer { margin-bottom: var(--space-4); }
.stk__elapsed {
    margin: var(--space-2) 0 0;
    font-size: var(--fs-legal);
    color: var(--minet-muted);
    font-variant-numeric: tabular-nums;
}
.stk__help { margin: 0; font-size: var(--fs-legal); color: var(--minet-muted); }
.stk__actions { display: grid; gap: var(--space-2); margin-top: var(--space-4); }
.payment__done { padding-bottom: var(--space-4); }
.payment__done-title {
    margin: 0 0 var(--space-2);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-success);
}
.payment__done-ref { margin: 0 0 var(--space-2); font-size: var(--fs-small); }
.payment__done-ref strong { color: var(--minet-ink); letter-spacing: .04em; }
.payment__done-note { margin: 0; font-size: var(--fs-legal); color: var(--minet-muted); }
/* .notice--error styled only the stripe, so it now styles nothing. */

@media (max-width: 1024px) {
    .payment { grid-template-columns: 1fr; }
    .payment__side { position: static; order: -1; }}
.documents__summary-cover {
    margin-bottom: var(--space-6);
    padding: var(--space-4);
    background: var(--minet-white);
    border-radius: var(--radius);
}
.documents__summary-insurer { margin: 0; font-weight: 700; color: var(--minet-ink); }
.documents__summary-plan { margin: var(--space-1) 0 var(--space-3); font-size: var(--fs-small); color: var(--minet-muted); }
.documents__summary-total {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    font-weight: 700;
    color: var(--minet-ink);
    font-variant-numeric: tabular-nums;
}
.documents__summary-total span {
    display: block;
    font-family: var(--font-body);
    font-size: var(--fs-legal);
    font-weight: 400;
    color: var(--minet-muted);
}

/* ---------- Confirmation ---------- */

.outcome { display: grid; gap: var(--space-6); margin-top: var(--space-8); }
.outcome__payment {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-4);
    padding: var(--space-6);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
/* Pushed to the far end on a wide screen; drops onto its own line on a phone,
   where it is full width and stays a comfortable target. */
.outcome__receipt { margin-left: auto; }
@media (max-width: 599px) {
    .outcome__receipt { margin-left: 0; width: 100%; justify-content: center; }}
.outcome__tick {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    flex: none;
    border-radius: 50%;
    background: var(--minet-success);
    color: var(--minet-white);
}
.outcome__payment-title { margin: 0; font-weight: 700; color: var(--minet-ink); }
.outcome__payment-ref { margin: var(--space-1) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }
.outcome__payment-ref strong { color: var(--minet-ink); letter-spacing: .04em; }
.outcome__policy {
    padding: var(--space-6);
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
}
/* Good and bad news now differ in CONTENT alone: the good panel carries the
   policy details, the bad one a payment reference and what to do about it. The
   coloured left bars that also told them apart are gone, so both are drawn
   identically — `--good` and `--warn` remain in the markup and style nothing. */
.outcome__policy-title {
    margin: 0 0 var(--space-2);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.outcome__policy-body { margin: 0 0 var(--space-3); font-size: var(--fs-small); color: var(--minet-text); }
.outcome__policy-body:last-child { margin-bottom: 0; }
.outcome__policy .summary-list { margin: 0; }
.progress--indeterminate { position: relative; overflow: hidden; }
.progress--indeterminate .progress__bar {
    width: 40%;
    animation: slide 1.4s ease-in-out infinite;
}
@keyframes slide {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
    .progress--indeterminate .progress__bar { animation: none; width: 100%; }}
.documents-out {
    margin-top: var(--space-12);
    padding-top: var(--space-8);
    border-top: 1px solid var(--minet-line);
}
.documents-out__title {
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.resend { margin-top: var(--space-6); }
.resend__row { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-2); }
.resend__row .control { flex: 1 1 260px; }
.outcome__portal-note { margin: var(--space-4) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }

/* ---------- Email me this quote ---------- */

.quote-recap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    flex-wrap: wrap;
    margin-bottom: var(--space-8);
    padding: var(--space-6);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
/* The plan is the title and the underwriter the line under it, as on a card.
   (email-comparison uses the same two classes for "3 plans compared" and the
   underwriters' names, which is the same pair of weights.) */
.quote-recap__plan { margin: 0; font-family: var(--font-display); font-size: var(--fs-card-title); font-weight: 700; color: var(--minet-ink); }
.quote-recap__insurer { margin: var(--space-1) 0 0; font-size: var(--fs-small); font-weight: 600; color: var(--minet-text); }
.quote-recap__trip { margin: var(--space-2) 0 0; font-size: var(--fs-small); color: var(--minet-text); }
.quote-recap__price {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    font-weight: 700;
    color: var(--minet-ink);
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.quote-recap__price span {
    display: block;
    font-family: var(--font-body);
    font-size: var(--fs-legal);
    font-weight: 400;
    color: var(--minet-muted);
}
.quote-recap__price .quote-recap__pay { margin-top: var(--space-1); font-size: var(--fs-small); color: var(--minet-text); }
.field-grid--two { grid-template-columns: repeat(2, 1fr); }
/* The optional tick is set apart from the necessary one, so nobody reads them
   as a single block to be cleared. */
.consent__check--optional {
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--minet-line);
}
@media (max-width: 720px) {
    .field-grid--two { grid-template-columns: 1fr; }
    .quote-recap__price { text-align: left; }}

/* ---------- Comparing plans ---------- */

.quote-card__compare {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--minet-line);
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-text);
    cursor: pointer;
    min-height: var(--tap-target-min);
}
.quote-card__compare input { width: 18px; height: 18px; accent-color: var(--minet-red-action); }
.quote-card__compare:hover { color: var(--minet-red-action); }
/* Sits above the fold of the page it belongs to, not over the cards. */
.compare-bar {
    position: sticky;
    bottom: var(--space-4);
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: var(--space-6);
    padding: var(--space-4) var(--space-6);
    background: var(--minet-ink);
    color: var(--minet-white);
    border-radius: var(--radius);
}
.compare-bar__count { margin: 0; font-size: var(--fs-small); font-weight: 600; }
.compare-bar__actions { display: flex; align-items: center; gap: var(--space-4); }
.compare-bar .linklike { color: var(--minet-white); }
/* The one sentence that says how the plans differ. Plain text: it was a grey
   box directly under the grey trip recap, two read-back panels in a row. */
.compare-lead { margin: 0; max-width: 70ch; color: var(--minet-text); }
/* The sentence, and the one thing to do with the whole comparison, on a line
   above the table — the button at the right-hand edge the table ends on. */
.compare-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4) var(--space-6);
    flex-wrap: wrap;
    margin-top: var(--space-8);
}
.compare-toolbar .btn { flex: none; }
/* Wide content scrolls inside its own container on a narrow screen, so the
   page never scrolls sideways. On a wide one there is nothing to scroll, and
   the container is NOT a scroller — which is what lets the table's head stick
   to the top of the window instead of to a box that never moves. */
.compare-scroll { margin-top: var(--space-6); }
/* `separate` with no spacing, not `collapse`: a collapsed border belongs to the
   table and stays behind when a cell sticks, so the head rode down the page
   with no rule under it. */
.compare-table { width: 100%; border-collapse: separate; border-spacing: 0; min-width: 640px; table-layout: fixed; }
.compare-table th, .compare-table td {
    text-align: left;
    vertical-align: top;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--minet-line);
}
/* THE HEAD RIDES DOWN THE PAGE under the site's own header, so which column
   is which plan — and what it costs — is never more than a glance away. */
.compare-table thead th {
    position: sticky;
    top: var(--header-height);
    z-index: 2;
    padding-block: var(--space-4);
    border-bottom: 1px solid var(--minet-ink);
    background: var(--minet-white);
}
/* The benefit column stays put while the plans scroll past it — otherwise a
   phone user loses track of which row they are reading. */
.compare-table__row-head {
    position: sticky;
    left: 0;
    z-index: 1;
    width: 260px;
    background: var(--minet-white);
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-ink);
}
.compare-table thead .compare-table__row-head { z-index: 3; }
.compare-table__plan,
.compare-table__underwriter,
.compare-table__region,
.compare-table__amount,
.compare-table__pay { display: block; }
.compare-table__plan {
    font-family: var(--font-display);
    font-size: var(--fs-card-title);
    line-height: var(--lh-heading);
    color: var(--minet-ink);
}
.compare-table__underwriter { margin-top: var(--space-1); font-size: var(--fs-small); font-weight: 600; color: var(--minet-text); }
.compare-table__region { font-size: var(--fs-small); font-weight: 400; color: var(--minet-muted); }
.compare-table__amount {
    margin-top: var(--space-3);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    line-height: var(--lh-tight);
    font-weight: 700;
    color: var(--minet-ink);
    font-variant-numeric: tabular-nums;
}
.compare-table__basis { margin-left: var(--space-1); font-family: var(--font-body); font-size: var(--fs-small); font-weight: 400; color: var(--minet-muted); }
.compare-table__pay { margin-top: var(--space-1); font-size: var(--fs-small); font-weight: 400; color: var(--minet-text); font-variant-numeric: tabular-nums; }
.compare-table__instalment { display: block; margin-top: var(--space-2); font-size: var(--fs-legal); font-weight: 400; color: var(--minet-text); }
.compare-table__limit {
    font-size: var(--fs-small);
    font-weight: 700;
    color: var(--minet-ink);
    font-variant-numeric: tabular-nums;
}
.compare-table__included { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--fs-small); color: var(--minet-text); }
.compare-table__included svg { flex: none; color: var(--minet-success); }
/* Not covered is the answer this screen exists to surface, so it is carried by
   a word and a mark, never by colour alone — and NOT in the danger red it
   used to wear. A plan that leaves something out has not failed; forty red
   cells made a comparison look like a page of errors, and the guide keeps
   that colour for destructive actions and failed states. Quiet grey with a
   cross, against the bold figures of what IS covered. */
.compare-table__absent {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--fs-small);
    color: var(--minet-muted);
}
.compare-table__absent svg { flex: none; }
.compare-table__held td, .compare-table__held th { font-size: var(--fs-small); color: var(--minet-muted); }
.compare-table__actions td { padding-block: var(--space-4); }
/* The buy button in the head, under the price it buys at. */
.compare-table__buy { display: block; margin-top: var(--space-4); }
.compare-table__buy .compare-table__referral { display: block; margin-bottom: var(--space-2); font-weight: 400; }
/* The second set of buy buttons is for screens where the head cannot stick. */
.compare-table__actions--foot { display: none; }
.compare-table tbody tr:last-child th, .compare-table tbody tr:last-child td { border-bottom: 0; }
/* A row under the pointer, so the eye can follow one benefit across. */
.compare-table tbody tr:not(.compare-table__actions):hover > * { background: var(--minet-surface); }
.compare-note { margin-top: var(--space-4); font-size: var(--fs-small); color: var(--minet-muted); }
@media (max-width: 900px) {
    /* Here the table is wider than the screen and scrolls sideways in its
       box; the head cannot stick to the window from inside a scroller, so it
       does not try, and the benefit column gets a rule to show it is fixed. */
    .compare-scroll { overflow-x: auto; }
    .compare-table { table-layout: auto; }
    .compare-table thead th { position: static; }
    .compare-table__actions--foot { display: table-row; }
    .compare-table__row-head { box-shadow: 1px 0 0 var(--minet-line); }}
@media (max-width: 720px) {
    .compare-table__row-head { width: 160px; min-width: 160px; }
    .compare-bar { flex-direction: column; align-items: stretch; }
    .compare-bar__actions { justify-content: space-between; }}
.compare-actions {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: var(--space-8);
}
.compare-actions__note { margin: 0; max-width: 46ch; font-size: var(--fs-small); color: var(--minet-muted); }
.quote-recap--stack { display: block; }

/* ---------- Client portal ----------

   The portal is not the funnel. There is no step, no progress and nothing to
   finish — a customer arrives to answer one question and leave, so the chrome
   is quieter than the journey's and the hierarchy is ordered by what is waiting
   on them rather than by what we have to show. */

/* The catalogue filter's no-JS submit. Hidden by catalogue-filter.js once it
   can submit the form on change instead — never hidden by CSS, which would
   leave someone without JavaScript unable to search at all. */
.filters__submit { flex: none; }
.products__result {
    margin: 0 0 var(--space-6);
    font-size: var(--fs-small);
    color: var(--minet-muted);
}

/* ---------- Legal / notice pages ---------- */

.legal { margin: var(--space-12) 0; }
.legal__title {
    margin: var(--space-2) 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    color: var(--minet-ink);
}
.legal__lede { margin: 0 0 var(--space-8); color: var(--minet-text); }
.legal__heading {
    margin: var(--space-12) 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    color: var(--minet-ink);
}
.legal p { margin: 0 0 var(--space-4); color: var(--minet-text); }
.legal__note { font-size: var(--fs-small); color: var(--minet-muted); }
.legal__list { margin: 0 0 var(--space-4) var(--space-6); padding: 0; color: var(--minet-text); }
.legal__list li { margin-bottom: var(--space-3); }
.legal__table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); }
.legal__table th,
.legal__table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--minet-line);
    text-align: left;
    vertical-align: top;
}
.legal__table thead th {
    font-size: var(--fs-legal);
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--minet-muted);
}
.legal__table tbody th { font-weight: 400; }
.legal__table code { font-size: var(--fs-legal); word-break: break-all; }
.legal__definitions { margin: 0 0 var(--space-4); display: grid; gap: var(--space-4); }
.legal__definitions dt {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-weight: 700;
    color: var(--minet-ink);
}
.legal__definitions dd { margin: var(--space-1) 0 0; font-size: var(--fs-small); color: var(--minet-text); }
/* What the total is made of, on the payment screen. Small, quiet, and above the
   "price held until" line — it answers "why this number?" without competing
   with the number itself. */
.payment__breakdown {
    margin: var(--space-4) 0;
    padding: var(--space-3) 0 0;
    border-top: 1px solid var(--minet-line);
    list-style: none;
    font-size: var(--fs-small);
}
.payment__breakdown li {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-1) 0;
    color: var(--minet-text);
}
/* What moved the TOTAL rather than one traveller's share. Set apart from the
   lines above it, because it is not another person — it is the booking. */
.payment__adjustment { color: var(--minet-muted); font-style: italic; }
/* The line the traveller lines add up to, before anything statutory. */
.payment__subtotal { border-top: 1px solid var(--minet-line); padding-top: var(--space-2); font-weight: 600; }
/* And what the customer actually pays. Stated, not merely implied by the
   figure at the top of the page. */
.payment__total { border-top: 1px solid var(--minet-line); padding-top: var(--space-2); font-weight: 700; color: var(--minet-ink); }
.payment__band { color: var(--minet-muted); }
