/* =============================================================================
   MINET BUY ONLINE — base
   What the storefront and the client portal BOTH use: the reset, the layout
   chrome every page carries (utility bar, header, footer), buttons, fields,
   notices, the status badge, panels and summary lists.

   ONE OF THREE, LOADED IN THIS ORDER ON EVERY PAGE (layouts/shop.blade.php):
       base.css  →  shop.css  →  portal.css
   A rule belongs here when markup in BOTH products uses it. A rule used by
   only one of them belongs in that product's file.

   MOVING A RULE BETWEEN FILES MOVES IT IN THE CASCADE. Two rules of equal
   specificity that match one element are decided by order, and the order is
   now base, then shop, then portal.

   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.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
body {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    color: var(--minet-text);
    background: var(--minet-white);
    -webkit-font-smoothing: antialiased;
    /* Dates, premiums and phone numbers stand on the line and in columns. The
       fallback face (Corbel) defaults to old-style figures, which set "2026"
       and "KES 1,250" as if they were running text. */
    font-variant-numeric: lining-nums tabular-nums;
}
img { max-width: 100%; display: block; }
.container {
    width: 100%;
    max-width: var(--content-width);
    margin-inline: auto;
    padding-inline: var(--gutter);
}
/* Available to a screen reader, invisible on screen. Used to give repeated
   controls ("Get Quote") a unique accessible name per card. */
/*
 * `hidden` means hidden.
 *
 * The attribute's `display: none` comes from the browser's own stylesheet,
 * which ANY class rule outranks — so a `.btn { display: inline-flex }` left the
 * catalogue filter's no-JS submit button on screen after JavaScript had marked
 * it hidden. Every `hidden` in this app is a state toggled from script; this
 * one line is what makes them all mean what they say.
 */
[hidden] { display: none !important; }
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}
/* Visible on keyboard focus only — the first stop on the keyboard path. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: var(--space-2);
    background: var(--minet-red-action);
    color: var(--minet-white);
    padding: var(--space-3) var(--space-4);
    z-index: 100;
}
.skip-link:focus { left: var(--space-4); }

/* ---------- Utility bar ---------- */

.utility-bar {
    background: var(--minet-black);
    color: var(--minet-white);
    font-size: var(--fs-small);
}
.utility-bar .container {
    min-height: var(--utility-bar-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
}
.utility-bar__group { display: flex; align-items: center; gap: var(--space-6); }
.utility-bar__item {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--minet-white);
    font-weight: 600;
}
.utility-bar__portal {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 34px;
    padding: 0 var(--space-4);
    border: 1px solid var(--minet-grey);
    border-radius: var(--radius);
    color: var(--minet-white);
    text-decoration: none;
    font-weight: 600;
}
.utility-bar__portal:hover { border-color: var(--minet-white); }

/* ---------- Header ---------- */

.site-header {
    background: var(--minet-white);
    border-bottom: var(--border);
    position: sticky;
    top: 0;
    z-index: 50;
}
.site-header .container {
    min-height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
}
.site-header__logo img { height: var(--logo-height); width: auto; }
.site-nav { display: flex; align-items: center; gap: var(--space-6); }
.site-nav__link {
    color: var(--minet-text);
    text-decoration: none;
    font-size: var(--fs-small);
    font-weight: 600;
    padding-block: var(--space-2);
    border-bottom: 2px solid transparent;
    white-space: nowrap;
}
.site-nav__link:hover { color: var(--minet-red-action); }
.site-nav__link[aria-current="page"] {
    color: var(--minet-red-action);
    border-bottom-color: var(--minet-red);
}
/* A chrome destination we have not been given yet: still readable, not a link
   that goes nowhere. */
.site-nav__link--inert { color: var(--minet-muted); cursor: default; }
.header__actions { display: flex; align-items: center; gap: var(--space-4); }

/* ---------- Buttons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: var(--button-height);
    min-width: var(--tap-target-min);
    padding-inline: var(--space-6);
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: var(--fs-small);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s ease;
}
/* --minet-red-action names the intent — white text sits on this fill. It is the
   one brand red, #DA291C, which passes WCAG AA against white at any size. */
.btn--primary { background: var(--minet-red-action); color: var(--minet-white); }
.btn--primary:hover { background: var(--minet-red-hover); }
.btn--secondary { background: var(--minet-black); color: var(--minet-white); }
.btn--secondary:hover { background: var(--minet-ink); }
.btn--ghost {
    background: transparent;
    color: var(--minet-text);
    /* The control edge: on --minet-line (1.26:1) a ghost button beside bordered
       fields read as one that was switched off. */
    border-color: var(--minet-control-border);
}
.btn--ghost:hover { border-color: var(--minet-black); }
.btn--block { width: 100%; }
.icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--tap-target-min);
    height: var(--tap-target-min);
    border: 0;
    background: transparent;
    color: var(--minet-ink);
    cursor: pointer;
    border-radius: var(--radius);
}
.icon-button:hover { color: var(--minet-red-action); }

/* ---------- Footer ---------- */

.site-footer {
    background: var(--minet-black);
    color: var(--minet-grey);
    /* No top padding: the band has to sit flush on the top edge of the black.
       The space it used to give is the band's own bottom margin below. */
    padding-block: 0 var(--space-6);
    font-size: var(--fs-small);
}
/* The tribal band (brand/texture). Centred, so a screen narrower than the
   artwork crops it at both sides as the design does; repeated, so a screen
   wider than it never shows a gap — its two edges meet almost exactly. Scaled
   by height only, so the pattern keeps its proportions at every width. */
.site-footer__band {
    height: var(--texture-band-height);
    margin-bottom: var(--space-12);
    background: var(--minet-white) url('../brand/texture/minet-tribal.png') center / auto 100% repeat-x;
}
.site-footer__top {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1.4fr;
    gap: var(--space-8);
}
.site-footer__logo { display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap; }
.site-footer__mark { height: var(--logo-height-footer); width: auto; }
/* Separated by space alone. The printed letterhead still divides the mark from
   the endorsement with a rule; on screen it no longer does. */
.site-footer__aon {
    height: var(--aon-height-footer);
    width: auto;
    padding-left: var(--space-6);
}
.site-footer__positioning { margin: var(--space-6) 0; max-width: 42ch; color: var(--minet-grey); }
.site-footer__licence {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    color: var(--minet-white);
    font-weight: 600;
}
.site-footer__licence svg { color: var(--minet-red); flex: none; }
.site-footer h2 {
    margin: 0 0 var(--space-4);
    font-family: var(--font-display);
    font-size: var(--fs-body);
    color: var(--minet-white);
}
.site-footer ul { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.site-footer a { color: var(--minet-grey); text-decoration: none; }
.site-footer a:hover { color: var(--minet-white); }
.site-footer__location strong { color: var(--minet-white); font-weight: 600; }
.site-footer__social { display: flex; gap: var(--space-4); margin-top: var(--space-6); }
.site-footer__social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--tap-target-min);
    height: var(--tap-target-min);
    color: var(--minet-grey);
}
.site-footer__social a:hover { color: var(--minet-white); }
.site-footer__bottom {
    display: flex;
    justify-content: space-between;
    gap: var(--space-6);
    flex-wrap: wrap;
    margin-top: var(--space-12);
    padding-top: var(--space-6);
    border-top: 1px solid var(--minet-ink);
    font-size: var(--fs-legal);
}
.site-footer__legal { 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) {
    .site-footer__top { grid-template-columns: 1fr 1fr; }

    /* The header gets its own breakpoint. The logo, seven nav items and the
       advisor button stop fitting on one line at about 1024px, not at 720 —
       between the two the nav was wrapping onto a second row and the header
       grew to nearly twice its height. */
    .site-header .container {
        flex-wrap: wrap;
        min-height: auto;
        padding-block: var(--space-3);
        row-gap: var(--space-2);
    }
    .site-nav {
        order: 3;
        width: 100%;
        overflow-x: auto;
        gap: var(--space-6);
        padding-bottom: var(--space-2);
        -webkit-overflow-scrolling: touch;
    }}
@media (max-width: 720px) {
    :root { --fs-h1: 2rem; --fs-h2: 1.625rem; }

    /* On a phone the header was taking three rows and 28% of the screen before
       any content. Dropping the search icon is enough to get it to two: on the
       shop it linked to a search field visible on the same screen, so it cost
       space and bought nothing. The logo keeps its size. */
    .header__actions .icon-button { display: none; }
    .site-header .container { column-gap: var(--space-3); }
    .site-footer__top { grid-template-columns: 1fr; }}
@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; }}

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

.container--narrow { max-width: 960px; }
.step { padding-block: var(--space-12) var(--space-16); }

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

/* Used on <fieldset> too, which brings 2px side margins and a min-width of
   its own — enough to step a grouped field out of line with its neighbours. */
.field { margin: 0 0 var(--space-4); border: 0; padding: 0; min-width: 0; }
.field__label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-ink);
    /* Used on <legend> as well as <label>; a legend carries inline padding of
       its own, which would indent every grouped question past the ungrouped
       ones it sits in a column with. */
    padding: 0;
}
.field__note { margin: var(--space-2) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }
/* A legend already carries the label's own gap beneath it; with the note's on
   top the explanation drifted away from the heading it explains. */
legend.field__label + .field__note { margin-top: 0; }
.field__error {
    margin: var(--space-2) 0 0;
    font-size: var(--fs-small);
    font-weight: 600;
    color: var(--minet-danger);
}
.control { position: relative; display: flex; }
.control select,
.control input {
    width: 100%;
    /* Not the mockup's 56px: that is a hero height, and a column of eight of
       them reads as padding rather than as controls. Still over the 44px
       touch minimum. */
    height: var(--control-height-form);
    padding-inline: var(--space-3);
    /* WHITE WITH AN EDGE, not a grey fill. A filled grey box is how the web
       draws a field that is switched off, and --minet-surface on white is
       1.12:1 — the field had no boundary anybody could see. Grey is kept for
       what is read back (a recap, a notice, a chosen country); a box with
       this edge is something to answer. */
    border: 1px solid var(--minet-control-border);
    border-radius: var(--radius);
    background: var(--minet-white);
    color: var(--minet-text);
    font-family: var(--font-body);
    font-size: var(--fs-body);
    appearance: none;
}
.control select { padding-right: var(--space-12); }
/* Same clearance for an input that has an icon sitting over it — the search box
   on the compare screen was running its text under the magnifier. */
.control input:has(+ .control__icon) { padding-right: var(--space-12); }
/* Stated, not left to the browser: Chrome's default placeholder grey passes AA
   on white and WebKit's and Firefox's are lighter. opacity because Firefox
   fades a placeholder on top of whatever colour it is given. */
.control input::placeholder,
.control textarea::placeholder { color: var(--minet-muted); opacity: 1; }
.control select:hover,
.control input:hover { border-color: var(--minet-ink); }
/* The brand's ring, as .choice, .multiselect and .dropzone already use. Without
   it these two were the only controls on the form falling back to the browser's
   own, a different colour from their neighbours'. */
.control select:focus-visible,
.control input:focus-visible,
.control textarea:focus-visible {
    outline: var(--focus-ring);
    outline-offset: var(--focus-offset);
}
.control__icon {
    position: absolute;
    right: var(--space-4);
    top: 50%;
    transform: translateY(-50%);
    color: var(--minet-muted);
    pointer-events: none;
}
/* ---- Alerts and notices --------------------------------------------------

   These carried their whole meaning in a coloured left bar. With the bar gone
   an error, a success and a "these figures are invented" disclaimer were three
   identical grey boxes — and the one with role="alert" was the least marked
   thing on the page.

   Two signals instead, neither of them a left border: a MARKER GLYPH, different
   per state, and the box's own outline in the semantic colour. The glyph is the
   part that matters — it survives greyscale, and the brand guide does not allow
   state told by colour alone.

   BACKGROUNDS ARE DELIBERATELY LEFT ALONE. The obvious move is a tint per
   state, and it is a trap: --minet-red-action on --minet-warning-tint measures
   4.29:1 against 4.87:1 on white, so tinting a notice would quietly fail AA for
   every `.linklike` inside one. admin.css already refuses a .status--warn for
   the same arithmetic. */

.alert,
.notice {
    position: relative;
    margin-bottom: var(--space-8);
    /* Room for the marker, which is positioned rather than laid out: a notice
       may hold one paragraph or several, and flexing the box would stand them
       in a row. */
    padding: var(--space-4) var(--space-6) var(--space-4) calc(var(--space-6) + var(--space-8));
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
    background: var(--minet-surface);
}
.alert::before,
.notice::before {
    content: "i";                       /* neutral: a status message */
    position: absolute;
    left: var(--space-4);
    top: var(--space-4);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--minet-info);
    color: var(--minet-white);
    font-size: var(--fs-legal);
    font-weight: 700;
    line-height: 1;
}
/* Something went wrong. The cross is not the close control it resembles
   elsewhere — nothing in a notice is dismissible. */
.alert--error,
.notice--error { border-color: var(--minet-danger); }
.alert--error::before,
.notice--error::before { content: "\2715"; background: var(--minet-danger); }
/* Invented figures. The most consequential disclaimer in the shop and, until
   now, the only modifier with no styling of its own at all. */
.notice--sample { border-color: var(--minet-warning); }
/* Filled with --minet-warning-FILL, not --minet-warning. White on the
   plain amber is 4.24:1 and ink on it is 4.06:1 — measured, both fail AA,
   so there was no way to letter this circle until the darker fill existed. */
.notice--sample::before { content: "!"; background: var(--minet-warning-fill); }

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

.notice p { margin: 0; font-size: var(--fs-small); }
.notice strong { color: var(--minet-ink); }

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

/* A text button still has to be hittable. "Replace this file" and "Change these
   details" were 26px tall, on the screen where someone on mobile data is already
   having the hardest time. The text stays inline; the target does not. */
.linklike {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-target-min);
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    color: var(--minet-red-action);
    text-decoration: underline;
    cursor: pointer;
}

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

.summary-list { margin: 0 0 var(--space-6); display: grid; gap: var(--space-3); }
.summary-list div {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--minet-line);
}
.summary-list div:last-child { border-bottom: 0; padding-bottom: 0; }
.summary-list dt { font-size: var(--fs-small); color: var(--minet-muted); }
.summary-list dd { margin: 0; font-size: var(--fs-small); font-weight: 700; color: var(--minet-ink); text-align: right; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

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

.panel {
    padding: var(--space-6);
    border: 1px solid var(--minet-line);
    border-radius: var(--radius);
}
.panel__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-card-title);
    color: var(--minet-ink);
}
.panel__sub { margin: var(--space-1) 0 var(--space-4); font-size: var(--fs-small); color: var(--minet-muted); }
.panel__note { margin: var(--space-4) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }

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

.documents-out__list { margin: 0 0 var(--space-4); padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.documents-out__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-4);
    background: var(--minet-surface);
    border-radius: var(--radius);
}
.documents-out__name { margin: 0; font-weight: 700; color: var(--minet-ink); }
.documents-out__desc { margin: var(--space-1) 0 0; font-size: var(--fs-small); color: var(--minet-muted); }
.documents-out__pending { font-size: var(--fs-small); color: var(--minet-muted); }
.documents-out__note { margin: 0 0 var(--space-6); font-size: var(--fs-small); color: var(--minet-muted); }
.outcome__actions {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-top: var(--space-12);
}
@media (max-width: 720px) {
    .outcome__actions { flex-direction: column; }
    .outcome__actions .btn { width: 100%; }}

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

/* .notice--good styled only the stripe, so it now styles nothing. */
/* Only the confirmation notice puts a tick beside its text. Left unscoped,
   this turned every other notice's inline <strong> runs into flex items and
   broke the sentence into columns. */
/* The one state whose marker is already in the markup — a real check-circle
   icon beside the text — so it keeps that and suppresses the glyph. */
.notice--good { padding-left: var(--space-6); border-color: var(--minet-success); }
.notice--good::before { content: none; }
.notice--good p { display: flex; align-items: center; gap: var(--space-2); }
.notice--good svg { color: var(--minet-success); flex: none; }

/* ---------- 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. */

.portal-head__eyebrow {
    margin: 0;
    font-size: var(--fs-legal);
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--minet-red);
}
/* Status badges. Text as well as colour, because colour alone is not a status
   to a colour-blind reader or a printed page. */
.status {
    display: inline-block;
    flex: none;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--minet-surface);
    color: var(--minet-text);
    font-size: var(--fs-legal);
    font-weight: 700;
    letter-spacing: .04em;
    white-space: nowrap;
}
.status--good { background: var(--minet-success-tint); color: var(--minet-success); }
/*
 * `--minet-warning` on its own tint measures 3.73:1 — a fail at 12px bold, on
 * the badge that says "Waiting for you", which is the most consequential state
 * a claim can be in. Ink on the tint with the amber as a ring is the same
 * arrangement `.status--good` already uses (`--minet-success` is black on a
 * green tint, deliberately), and the ring clears 3:1 as a non-text boundary.
 * The ring is an inset shadow, not a border, so the pill keeps its height.
 */
.status--warn {
    background: var(--minet-warning-tint);
    color: var(--minet-ink);
    box-shadow: inset 0 0 0 1px var(--minet-warning);
}
.status--danger { background: var(--minet-danger-tint); color: var(--minet-danger); }
.status--info { background: var(--minet-info-tint); color: var(--minet-info); }
.status--muted { background: var(--minet-surface); color: var(--minet-muted); }
.field__optional { font-weight: 400; color: var(--minet-muted); text-transform: none; letter-spacing: 0; }
/* The claim narrative and the advisor note — the only free-text fields in the
   whole application. */
.control textarea {
    width: 100%;
    padding: var(--space-3);
    border: 1px solid var(--minet-control-border);
    border-radius: var(--radius);
    background: var(--minet-white);
    color: var(--minet-text);
    font-family: var(--font-body);
    font-size: var(--fs-body);
    line-height: 1.5;
    resize: vertical;
}
.control textarea:hover { border-color: var(--minet-ink); }
