/* ============================================================================
   PUE overrides on the QF chrome
   Loaded after qf-tokens.css and qf-chrome.css so this is the one place local
   deviations from the design system live. Nothing in qf-tokens.css (verbatim DS
   tokens) or qf-chrome.css (a faithful port of the DS SiteHeader / PueFooter) is
   edited, so both can be refreshed from the design system without losing this.

   Keep this file small, and note why each rule exists.
   ============================================================================ */

:root {
    /* Header lockup height. The DS ships 40px (2.5rem) and treats 36px as the
       floor, below which the Arabic strokes close up — there is no documented
       ceiling, so a larger lockup is a local choice, not a violation.
       rem, so it scales with the reader's root font size like the type does. */
    --pue-header-logo-height: 3.5rem;    /* 56px at the default 16px root */
    --pue-header-logo-height-sm: 2.75rem;/* 44px on narrow screens */

    /* Header text. The DS puts the utility row and the small button at 12px;
       both read as too small next to a 56px lockup, so they come up to the body
       size. The nav was already at body size. */
    --pue-header-nav-size: 1.125rem;     /* 18px, was 1rem */
    --pue-header-utility-size: 1rem;     /* 16px, was 0.875rem */
    --pue-header-button-size: 1rem;      /* 16px, was 0.875rem */

    /* Footer, matched to the header so the two ends of the page agree. The DS
       ships the footer lockup at 46px against a 40px header one; both are now
       the same height. */
    --pue-footer-logo-height: 3.5rem;    /* 56px, was 46px, same as the header */
    --pue-footer-logo-height-sm: 2.75rem;/* 44px on narrow screens */

    /* THE LINKS ARE NOT THE FOOTER. They were raised to 18px with the rest of
       the chrome, which made two words of secondary navigation the biggest type
       in the band and left the 56px lockup reading as decoration beside them.
       Back to the DS sizes: the lockup is the thing, the links sit under it. */
    --pue-footer-link-size: 1rem;        /* 16px, the DS size, was 18px */
    --pue-footer-legal-size: 0.875rem;   /* 14px, was 15px */
    --pue-footer-social-size: 1.25rem;   /* 20px, was 24px */

    /* ---- The PUE highlight pair ----
       The two colours the hub highlights with. Brighter than the Pantone
       secondaries they stand in for: Set B is specified for print, and on a
       screen 338 C reads as a dusty seafoam and 165 C as a brick, neither of
       which carries a hover state or a mark.

       They are NOT written over --qf-mint and --qf-orange. Those name Pantone
       chips and have to keep saying what the printer would hand back; the
       semantic aliases are repointed instead, so anything asking for "an
       accent" gets the screen colour and anything asking for 338 C still gets
       338 C. */
    --pue-highlight: #50e2c3;            /* mint, on ink text */
    --pue-highlight-warm: #ff7547;       /* orange, on white text */

    --accent-highlight: var(--pue-highlight);
    --accent-primary: var(--pue-highlight-warm);
}

/* The handful of places qf-chrome.css names the Pantone token directly rather
   than the alias. Repointed here so the chrome does not end up with two mints
   and two oranges on the same page. */
.qf-page ::selection { background: var(--pue-highlight); color: var(--qf-ink); }
.qf-page .qf-btn--accent {
    background: var(--pue-highlight-warm);
    border-color: var(--pue-highlight-warm);
}
.qf-page .qf-mark-mint { background: var(--pue-highlight); color: var(--qf-ink); }
.qf-page .qf-mark-orange { background: var(--pue-highlight-warm); color: var(--qf-white); }

/* Targets the lockup only: the nav tree glyph (.qf-nav a img) and the footer
   lockup (.pue-footer-lockup) are untouched. */
.qf-page .qf-header-logo img {
    height: var(--pue-header-logo-height);
    width: auto;
}

/* Header text only — page content and forms keep the DS scale. */
.qf-page .qf-nav a { font-size: var(--pue-header-nav-size); }
.qf-page .qf-utility { font-size: var(--pue-header-utility-size); }
.qf-page .qf-header-actions .qf-btn { font-size: var(--pue-header-button-size); }

/* The other-language link (header 'langSwitch'), drawn like the accessibility
   button beside it. Hover underlines rather than recolours. */
.qf-page .qf-lang-switch {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 12px;
    border: 1px solid var(--qf-ink);
    color: var(--qf-ink);
    font-size: var(--pue-header-button-size, var(--text-caption));
    font-weight: var(--weight-medium);
    text-decoration: none;
}
.qf-page .qf-lang-switch:hover,
.qf-page .qf-lang-switch:focus-visible { color: var(--qf-ink); text-decoration: underline; text-underline-offset: 3px; }
.qf-page .qf-lang-switch:lang(ar) { font-family: var(--font-arabic); }

/* A page's own call to action (header 'headerCta'), as tall as the controls
   beside it. */
.qf-page .qf-header-cta { min-height: 40px; }

@media (max-width: 700px) {
    .qf-page .qf-lang-switch,
    .qf-page .qf-header-cta { min-height: 44px; }
}

/* ---- Footer (PueFooter), matched to the header ----
   Now QF Cool Gray 11 (team preference, Oct 2026). Originally pure black rather than the DS Sidra green. It is the end of the page and it
   should read as the end of the page; green here repeats the brand colour a
   third time after the header and the buttons, and the white lockup sits
   cleaner on a dark band than on a mid green. */
.qf-page .pue-footer { background: var(--qf-cool-gray-11); }   /* QF gray, not black: team preference */
.qf-page .pue-footer-lockup { height: var(--pue-footer-logo-height); }
.qf-page .pue-footer-link {
    font-size: var(--pue-footer-link-size);
    /* The underline comes down with the type: at 18px solid white it was a rule
       across the band. */
    border-bottom-color: rgba(255, 255, 255, .35);
}
.qf-page .pue-footer-legal .qf-shell { font-size: var(--pue-footer-legal-size); }
.qf-page .pue-credit { font-size: var(--pue-footer-legal-size); }
.qf-page .pue-footer-socials svg {
    width: var(--pue-footer-social-size);
    height: var(--pue-footer-social-size);
}

/* Nav-less header (layout: 'nav' => false): the hairline the nav row used to
   carry moves onto the header itself. */
.qf-page .qf-header--bare { border-bottom: var(--border-hairline); }

/* The DS nav scrolls horizontally with a hidden scrollbar, which on a phone just
   looks like a clipped last item. Wrap instead, so every destination is visible. */
@media (max-width: 700px) {
    .qf-page .qf-nav {
        flex-wrap: wrap;
        overflow-x: visible;
        gap: 0 var(--space-5);
    }
}

@media (max-width: 560px) {
    .qf-page .qf-header-logo img {
        height: var(--pue-header-logo-height-sm);
    }
    .qf-page .pue-footer-lockup {
        height: var(--pue-footer-logo-height-sm);
    }
    /* Full-width so the tap target is not a narrow strip beside the lockup. */
    .qf-page .qf-header-actions { width: 100%; }
    .qf-page .qf-header-actions .qf-btn { flex: 1 1 auto; }
}

/* ---- Sign in / sign out control (PUE hub pages only) ----
   Local addition, not part of the design system chrome — kept here so
   qf-chrome.css stays refreshable from the DS. Sits in the header's action row
   beside the existing buttons. */
.qf-page .qf-auth {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}
.qf-page .qf-auth-who {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    text-align: end;
}
.qf-page .qf-auth-label {
    font-size: var(--text-micro);
    color: var(--text-subtle);
}
.qf-page .qf-auth-name {
    font-size: var(--text-body-sm);
    color: var(--qf-ink);
}
/* How long this sign-in has left. Quiet by default: it is reassurance, and a
   fortnight of it shouting would train people not to see it. .is-soon is the last
   day, where it becomes something to act on. */
/* Its own line under the name, and never a reason for the header to grow: the
   row already carries a name, a Hub link and a sign-out button. nowrap keeps
   "Expires in 14 days renew" from breaking mid-phrase when the name is long. */
.qf-page .qf-auth-left {
    display: block;
    margin-top: 2px;
    font-size: var(--text-micro);
    line-height: 1.3;
    white-space: nowrap;
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}
.qf-page .qf-auth-left.is-soon {
    color: var(--qf-adham);
    font-weight: var(--weight-medium);
}
/* The way out of the countdown, underlined so it reads as the action it is. */
.qf-page .qf-auth-renew {
    margin-inline-start: var(--space-2);
    color: var(--text-link);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.qf-page .qf-auth-left.is-soon .qf-auth-renew { color: var(--qf-adham); }
.qf-page .qf-auth-form { margin: 0; }
.qf-page .qf-auth-link {
    font-size: var(--text-body-sm);
    color: var(--text-link);
    text-decoration: underline;
    text-underline-offset: 3px;
}
/* The sign-out submit has to look like the links beside it without losing the
   button semantics a POST needs. No outline reset: the focus ring stays. */
.qf-page .qf-auth-link--button {
    appearance: none;
    padding: 0;
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
}

@media (max-width: 560px) {
    .qf-page .qf-auth {
        width: 100%;
        justify-content: space-between;
        gap: var(--space-3);
    }
    .qf-page .qf-auth-who { text-align: start; }
    /* The sign-in button is a .qf-btn, which the rule above stretches; the auth
       row manages its own width, so opt back out. */
    .qf-page .qf-header-actions .qf-auth .qf-btn { flex: 0 0 auto; }
}

/* ---- The account menu ----
   One control in the header instead of five. The name is the trigger; the status,
   the countdown, the hub link and the way out are behind it. See the note in
   qf.partials.auth-nav for why this is a <details> and not a scripted dropdown. */
.qf-page .qf-account {
    position: relative;
}

.qf-page .qf-account-button {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm, 4px);
    font-size: var(--text-body-sm);
    color: var(--qf-ink);
    cursor: pointer;
    /* The disclosure triangle is replaced by the caret inside the summary. */
    list-style: none;
}

.qf-page .qf-account-button::-webkit-details-marker {
    display: none;
}

.qf-page .qf-account-button:hover {
    background: var(--surface-subtle, rgba(0, 0, 0, 0.04));
}

.qf-page .qf-account[open] .qf-account-button {
    background: var(--surface-subtle, rgba(0, 0, 0, 0.04));
}

.qf-page .qf-account-name {
    font-weight: var(--weight-medium);
}

/* The one state that cannot wait behind a click: a sign-in about to lapse. */
.qf-page .qf-account-alert {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--qf-adham);
}

.qf-page .qf-account-menu {
    position: absolute;
    inset-inline-end: 0;
    top: calc(100% + var(--space-2));
    z-index: 40;
    min-width: 230px;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4);
    background: var(--surface-page, #fff);
    border: 1px solid var(--border-subtle, rgba(0, 0, 0, 0.12));
    border-radius: var(--radius-sm, 4px);
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);
    text-align: start;
}

.qf-page .qf-account-who {
    display: flex;
    flex-direction: column;
    line-height: 1.35;
}

.qf-page .qf-account-label {
    font-size: var(--text-micro);
    color: var(--text-subtle);
}

.qf-page .qf-account-email {
    font-size: var(--text-body-sm);
    color: var(--qf-ink);
    word-break: break-all;
}

.qf-page .qf-account-left {
    font-size: var(--text-micro);
    line-height: 1.4;
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}

.qf-page .qf-account-left.is-soon {
    color: var(--qf-adham);
    font-weight: var(--weight-medium);
}

/* Its own line since the sentence beside it grew: an inline link after "You will
   be signed out in 14 days." wraps to a second line in this menu anyway, and a
   half-wrapped link is worse than one that always sits under the sentence. */
.qf-page .qf-account-renew {
    display: inline-block;
    margin-top: var(--space-1);
    color: var(--text-link);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.qf-page .qf-account-left.is-soon .qf-account-renew { color: var(--qf-adham); }

.qf-page .qf-account-item {
    font-size: var(--text-body-sm);
    color: var(--text-link);
    text-decoration: none;
    text-align: start;
}

.qf-page .qf-account-item:hover { text-decoration: underline; }

/* The sign-out submit has to look like the link above it without losing the button
   semantics a POST needs. No outline reset: the focus ring stays. */
.qf-page .qf-account-item--button {
    appearance: none;
    padding: 0;
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
}

@media (max-width: 560px) {
    /* Hung off the start edge of the name, not the end of it.
       .qf-auth goes full width at this breakpoint and spaces its children out,
       which puts the name at the start of the row with the theme switch at the
       far end. A 280px panel anchored to the name's end edge therefore begins
       at -69px on a 390px screen: measured on /solutions, the email, the
       countdown and the start of every link sat off the left of the window,
       with no scroll to reach them because content past the start edge is not
       scrollable. Opening from the start edge instead puts it at 24px.

       Capped to the page gutters as well, so a long email or a renew line can
       widen the panel only as far as the other margin. The earlier min-width
       alone could not hold it: nothing bounded the other edge. */
    .qf-page .qf-account-menu {
        inset-inline-start: 0;
        inset-inline-end: auto;
        min-width: min(280px, calc(100vw - var(--space-6) * 2));
        max-width: calc(100vw - var(--space-6) * 2);
    }
}

/* ---- Code sign-in: the header popup and the standalone page ----
   One set of rules for both, since qf.partials.sign-in-form is shared. Square
   corners and hairlines like the rest of the hub; the dialog leans on the
   browser's own backdrop and focus handling rather than reimplementing them. */
.qf-signin-dialog {
    width: min(92vw, 30rem);
    padding: var(--space-8);
    color: var(--qf-ink);
    background: var(--surface-page);
    border: 1px solid var(--qf-ink);
    border-radius: var(--radius-none);
    box-shadow: var(--shadow-overlay);
}
.qf-signin-dialog::backdrop { background: rgba(17, 17, 17, .45); }

.qf-signin-dismiss { display: flex; justify-content: flex-end; margin: 0 0 calc(-1 * var(--space-4)); }
.qf-signin-dismiss button {
    appearance: none;
    padding: 0 var(--space-1);
    font-size: var(--text-title-2);
    line-height: 1;
    color: var(--text-subtle);
    background: none;
    border: 0;
    cursor: pointer;
}
.qf-signin-dismiss button:hover { color: var(--qf-ink); }

.qf-signin-title,
.qf-signin-heading {
    font-family: var(--font-serif-display);
    font-weight: var(--weight-regular);
    font-size: var(--text-title-1);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    margin-bottom: var(--space-5);
}

/* The page variant sits in a reading column rather than filling the shell. */
.qf-signin-page { max-width: 34rem; padding-block: var(--space-8) var(--space-16); }
.qf-signin-eyebrow { font-size: var(--text-body-sm); margin-bottom: var(--space-4); }
.qf-signin-heading { margin-bottom: var(--space-4); }
.qf-signin-lead {
    margin-bottom: var(--space-6);
    font-size: var(--text-body);
    line-height: var(--leading-body);
    color: var(--text-muted);
}

.qf-signin-form { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; }
.qf-signin-label { font-size: var(--text-caption); font-weight: var(--weight-medium); }
.qf-signin-input {
    width: 100%;
    padding: var(--space-3);
    font-family: inherit;
    font-size: var(--text-body);
    color: var(--qf-ink);
    background: var(--surface-page);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-xs);
    outline: none;
}
.qf-signin-input:focus { border-color: var(--qf-ink); }
/* The code is six characters read off a phone: spaced out and large enough to
   check against the notification without squinting. */
.qf-signin-input--code {
    font-size: var(--text-title-2);
    letter-spacing: 0.4em;
    text-align: center;
}
.qf-signin-submit { margin-top: var(--space-3); align-self: flex-start; }
.qf-signin-sent { font-size: var(--text-body-sm); color: var(--text-muted); }
.qf-signin-note {
    margin-top: var(--space-3);
    font-size: var(--text-caption);
    color: var(--text-subtle);
    line-height: var(--leading-body);
}
.qf-signin-status {
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-5);
    font-size: var(--text-body-sm);
    background: var(--surface-tint);
    border-inline-start: 2px solid var(--qf-sidra-green);
}
.qf-signin-error { font-size: var(--text-caption); color: var(--qf-adham); }

/* ---- Waiting on the code ----
   The button is the whole progress indicator. A code request now goes out in the
   background (qf.partials.sign-in-form), so nothing else on the page moves, and
   without a spinner the only sign anything happened is a word change. */
.qf-signin-submit.is-busy,
.qf-signin-textlink.is-busy {
    position: relative;
    padding-inline-end: calc(var(--space-4) + 1.1em);
    cursor: progress;
    opacity: .75;
}
.qf-signin-submit.is-busy::after,
.qf-signin-textlink.is-busy::after {
    content: "";
    position: absolute;
    inset-inline-end: var(--space-3);
    top: 50%;
    width: .9em;
    height: .9em;
    margin-top: -.45em;
    border: 2px solid currentColor;
    border-inline-start-color: transparent;
    border-radius: 50%;
    animation: qf-signin-spin .7s linear infinite;
}
.qf-signin-textlink.is-busy { text-decoration: none; }
.qf-signin-textlink.is-busy::after { inset-inline-end: 0; }

@keyframes qf-signin-spin { to { transform: rotate(360deg); } }

/* Somebody who has asked not to see motion still gets the state, just still. */
@media (prefers-reduced-motion: reduce) {
    .qf-signin-submit.is-busy::after,
    .qf-signin-textlink.is-busy::after { animation: none; opacity: .5; }
}
.qf-signin-resend { margin-top: var(--space-5); }
.qf-signin-textlink {
    appearance: none;
    padding: 0;
    font-family: inherit;
    font-size: var(--text-caption);
    color: var(--text-link);
    background: none;
    border: 0;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}

/* ---- Breadcrumbs (qf.partials.breadcrumbs) ----
   Sits above the page head. Ruled off along its full width: on a margin alone
   the trail read as a line of text floating loose above the <h1> rather than as
   the band of chrome it is. The rule gives it a bottom edge to sit on, and the
   asymmetric padding keeps it closer to that edge than to whatever is above. */
.qf-page .qf-crumbs {
    margin-bottom: var(--space-6);
    padding-bottom: var(--space-3);
    border-bottom: var(--border-hairline);
}
.qf-page .qf-crumbs-list {
    display: flex;
    /* Never wraps into a ladder: the last crumb truncates instead. */
    flex-wrap: nowrap;
    align-items: baseline;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--text-body-sm);
}
.qf-page .qf-crumbs-item { flex: 0 0 auto; color: var(--text-muted); }

/* The separator is generated content on purpose. No browser exposes it to the
   accessibility tree, and you cannot put aria-hidden on a pseudo-element — so
   this is the accessible construction, not a shortcut. "/" rather than a chevron:
   square-first, and direction-neutral for RTL. */
.qf-page .qf-crumbs-item + .qf-crumbs-item::before {
    content: "/";
    margin-inline-end: var(--space-2);
    color: var(--qf-ink-30);
}

.qf-page .qf-crumbs-item a { color: var(--text-muted); text-decoration: none; }
.qf-page .qf-crumbs-item a:hover {
    color: var(--qf-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.qf-page .qf-crumbs-item [aria-current="page"] { color: var(--qf-ink); }

/* The current crumb is the one safe to truncate: it repeats the <h1> directly
   beneath it, so an ellipsis loses nothing. Deliberately NOT hidden on narrow
   screens — that would drop aria-current from the DOM on a phone, so a screen
   reader would hear a different trail depending on viewport width. */
.qf-page .qf-crumbs-item:last-child {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---- "Suggest a feature": the header trigger and its popup ----
   Shown only where the layout passes suggestNav, which today is /solutions.
   Everything here mirrors the code sign-in dialog above, on purpose: they are
   the only two popups in the chrome and a visitor should not have to learn a
   second one. */

/* The trigger is an <a> to #suggestFeature rather than a <button>, so it still
   works with scripting off. qf-btn was written for links already, so the only
   thing needed here is the icon sitting on the text's baseline. */
.qf-suggest-trigger { display: inline-flex; align-items: center; gap: var(--space-2); }
/* Below the point where the header actions start competing, the words go and the
   icon stays. The trigger keeps its accessible name from the markup. */
@media (max-width: 720px) {
    .qf-suggest-trigger span { display: none; }
    .qf-suggest-trigger { padding-inline: var(--space-3); }
}

.qf-suggest-dialog {
    width: min(92vw, 32rem);
    padding: var(--space-8);
    color: var(--qf-ink);
    background: var(--surface-page);
    border: 1px solid var(--qf-ink);
    border-radius: var(--radius-none);
    box-shadow: var(--shadow-overlay);
}
.qf-suggest-dialog::backdrop { background: rgba(17, 17, 17, .45); }
/* Blurred behind "Report a problem", so the popup reads as the thing in front. */
.qf-bug-dialog::backdrop { -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }

/* NO SCRIPTING: the fragment opens it.
   A <dialog> without the open attribute is display:none, so with the script off
   the trigger would be a link to nothing. This rule is what the partial's own
   comment promises. It is not showModal(): there is no top layer, no backdrop
   element and no focus trap, so it is centred by hand and given a shade of its
   own through a fixed ::before. Good enough to read the form, fill it in and
   post it, which is the whole job of the no-JS path.

   :not([open]) so that it never fights the real modal: once the script has taken
   over, the fragment is cleared anyway, but a visitor arriving at
   /solutions#suggestFeature has both conditions true for a moment. */
.qf-suggest-dialog:target:not([open]) {
    display: block;
    position: fixed;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    transform: translate(-50%, -50%);
    z-index: 60;
}
.qf-suggest-dialog:target:not([open])::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background: rgba(17, 17, 17, .45);
}

.qf-suggest-dismiss { display: flex; justify-content: flex-end; margin: 0 0 calc(-1 * var(--space-4)); }
.qf-suggest-dismiss button {
    appearance: none;
    padding: 0 var(--space-1);
    font-size: var(--text-title-2);
    line-height: 1;
    color: var(--text-subtle);
    background: none;
    border: 0;
    cursor: pointer;
}
.qf-suggest-dismiss button:hover { color: var(--qf-ink); }

.qf-suggest-title,
.qf-suggest-sent-title {
    font-family: var(--font-serif-display);
    font-weight: var(--weight-regular);
    font-size: var(--text-title-1);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    margin-bottom: var(--space-4);
}
.qf-suggest-lead {
    margin-bottom: var(--space-6);
    font-size: var(--text-body);
    line-height: var(--leading-body);
    color: var(--text-muted);
}

.qf-suggest-form { display: flex; flex-direction: column; gap: var(--space-5); margin: 0; }
.qf-suggest-field { display: flex; flex-direction: column; gap: var(--space-2); }
.qf-suggest-label { font-size: var(--text-caption); font-weight: var(--weight-medium); }
/* Said in the label rather than left to be discovered by pressing Send, and
   quieter than the label it follows so the two do not read as one phrase. */
.qf-suggest-optional { font-weight: var(--weight-regular); color: var(--text-subtle); }

.qf-suggest-input {
    width: 100%;
    padding: var(--space-3);
    font-family: inherit;
    font-size: var(--text-body);
    line-height: var(--leading-body);
    color: var(--qf-ink);
    background: var(--surface-page);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-xs);
    outline: none;
}
.qf-suggest-input:focus { border-color: var(--qf-ink); }
/* Four lines to start with, and resizable down the page only: a textarea that
   can be dragged wider breaks out of a 32rem panel. */
.qf-suggest-textarea { min-height: 7rem; resize: vertical; }

.qf-suggest-note {
    font-size: var(--text-caption);
    line-height: var(--leading-body);
    color: var(--text-subtle);
}
.qf-suggest-submit { align-self: flex-start; }

/* The validation summary, above the fields it is about. Left rule rather than a
   red fill: the hub says everything else in hairlines, and a panel of colour for
   a missing title is out of proportion to a missing title. */
.qf-suggest-errors {
    margin-bottom: var(--space-5);
    padding: var(--space-3) var(--space-4);
    list-style: none;
    font-size: var(--text-body-sm);
    line-height: var(--leading-body);
    color: var(--qf-ink);
    background: var(--surface-tint);
    border-inline-start: 2px solid var(--qf-adham);
}
.qf-suggest-errors li + li { margin-top: var(--space-2); }

.qf-suggest-sent {
    font-size: var(--text-body);
    line-height: var(--leading-body);
    color: var(--text-muted);
}

/* THE HONEYPOT, REPEATED HERE ON PURPOSE.
   It is styled in qf-forms.css, and qf.layouts.page does not load that file:
   the chrome ships tokens, chrome, these overrides and the dark theme, and
   nothing else. Without this rule the trap field is a visible text input in the
   middle of the popup labelled "Website", which is both confusing and useless.
   Clipped rather than display:none, because a bot that skips hidden fields is a
   bot the trap never catches. */
.qf-honeypot {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------------------
   "Report a problem": the corner button and its popup. See
   qf.partials.bug-report. The popup reuses the .qf-suggest-* classes above and
   only adds what the picture needs.
   ------------------------------------------------------------------------- */

/* Bottom corner rather than the header: on a long form the header has scrolled
   away by the time something goes wrong. Small and quiet, so it sits over a form
   without competing with its Submit button; the label drops on a phone. */
.qf-bug-trigger {
    position: fixed;
    inset-block-end: var(--space-4);
    inset-inline-end: var(--space-4);
    z-index: 40;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-caption);
    font-weight: var(--weight-medium);
    line-height: 1;
    color: var(--qf-ink);
    text-decoration: none;
    background: var(--surface-page);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow-overlay);
    opacity: .85;
}
.qf-page a.qf-bug-trigger { color: var(--qf-ink); text-decoration: none; }
.qf-bug-trigger:hover,
.qf-bug-trigger:focus-visible { opacity: 1; border-color: var(--qf-ink); }
.qf-bug-trigger[aria-busy="true"] { cursor: progress; opacity: 1; }
@media (max-width: 640px) {
    .qf-bug-trigger { padding: var(--space-3); }
    .qf-bug-trigger-label { display: none; }
    .qf-bug-trigger[aria-busy="true"] .qf-bug-trigger-label { display: inline; }
}
@media print { .qf-bug-trigger { display: none; } }

/* Wider than the suggestion popup: it carries a picture of a whole screen. */
.qf-bug-dialog { width: min(94vw, 46rem); max-height: 92vh; overflow-y: auto; }

.qf-bug-shot { display: flex; flex-direction: column; gap: var(--space-2); }
.qf-bug-shot[hidden] { display: none; }
.qf-bug-hint { font-size: var(--text-caption); line-height: var(--leading-body); color: var(--text-subtle); }
.qf-bug-canvas-wrap { border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; }
/* touch-action none, or a finger drawing a box scrolls the popup instead. */
.qf-bug-canvas { display: block; width: 100%; height: auto; cursor: crosshair; touch-action: none; }
.qf-bug-shot-actions { display: flex; gap: var(--space-4); }
.qf-bug-link {
    appearance: none;
    padding: 0;
    font: inherit;
    font-size: var(--text-caption);
    color: var(--text-muted);
    text-decoration: underline;
    background: none;
    border: 0;
    cursor: pointer;
}
.qf-bug-link:hover { color: var(--qf-ink); }
.qf-bug-file { font-size: var(--text-caption); color: var(--text-muted); }

/* ---- Phone header: centred lockup, hamburger at its side ----
   Under 560px the top row becomes a three-column grid: the menu button, the
   lockup centred between two equal gutters, and the actions on a row of their
   own below. A page without the menu still centres, the empty column holding
   the lockup in the middle. The lockup is not a link here (qf-logo.js). */
.qf-page .qf-menu { display: none; }

@media (max-width: 560px) {
    .qf-page .qf-header-top {
        display: grid;
        grid-template-columns: 44px minmax(0, 1fr) 44px;
        align-items: center;
        row-gap: var(--space-3);
    }
    .qf-page .qf-header-logo { grid-column: 2; grid-row: 1; justify-self: center; }
    .qf-page .qf-header-actions { grid-column: 1 / -1; grid-row: 2; flex-wrap: wrap; }
    .qf-page .qf-menu { display: block; grid-column: 1; grid-row: 1; }
    /* Moved into the menu. */
    .qf-page .qf-header-actions .qf-suggest-trigger { display: none; }
}

.qf-page .qf-menu-button {
    display: grid; place-items: center;
    width: 44px; height: 44px;
    margin-inline-start: -10px;
    list-style: none; cursor: pointer;
    color: var(--qf-ink);
    border-radius: 6px;
}
.qf-page .qf-menu-button::-webkit-details-marker { display: none; }
.qf-page .qf-menu-button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.qf-page .qf-menu .qf-menu-close,
.qf-page .qf-menu[open] .qf-menu-open { display: none; }
.qf-page .qf-menu[open] .qf-menu-close { display: block; }

/* Hangs from the sticky header (the nearest positioned box), full width under
   it, and scrolls on its own when the list is longer than the screen. */
.qf-page .qf-menu-panel {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    z-index: 40;
    max-height: calc(100dvh - 140px);
    overflow-y: auto;
    padding: var(--space-4) 16px var(--space-6);
    background: var(--surface-page);
    border-block: var(--border-hairline);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
}
/* Two levels that must not look alike. A section name is a caption: small
   capitals in the brand green behind a short bar, sitting outside its card
   with more air above than below, so it binds to the group under it. The
   tools are the things to tap: full-width rows inside a tinted card, body
   size, each ending in a chevron and 48px tall. */
.qf-page .qf-menu-heading {
    display: flex; align-items: center; gap: var(--space-2);
    margin: var(--space-6) 0 var(--space-2);
    padding-inline: 4px;
    font-size: 11px; font-weight: 700; line-height: 1.2;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--text-brand);
}
.qf-page .qf-menu-heading::before {
    content: ""; flex: none;
    width: 3px; height: 12px; border-radius: 2px;
    background: currentColor;
}
.qf-page .qf-menu-heading:first-child { margin-top: var(--space-2); }

.qf-page .qf-menu-list {
    list-style: none; margin: 0; padding: 0;
    background: var(--surface-tint);
    border-radius: 10px;
    overflow: hidden;
}
.qf-page .qf-menu-list li + li { border-top: var(--border-hairline); }
.qf-page .qf-menu-list a {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-3);
    min-height: 48px;
    padding: 12px 14px;
    font-size: 16px; font-weight: 500; line-height: 1.3;
    color: var(--qf-ink);
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 150ms ease-out;
}
.qf-page .qf-menu-list a::after {
    content: ""; flex: none;
    width: 7px; height: 7px;
    border-block-start: 1.5px solid currentColor;
    border-inline-end: 1.5px solid currentColor;
    transform: rotate(45deg);
    opacity: 0.45;
}
[dir="rtl"] .qf-page .qf-menu-list a::after { transform: rotate(-45deg); }
.qf-page .qf-menu-list a:active { background: var(--border-subtle); }
.qf-page .qf-menu-list a:focus-visible { outline: 2px solid currentColor; outline-offset: -2px; }
.qf-page .qf-menu-suggest {
    display: flex; justify-content: center; align-items: center; gap: var(--space-2);
    width: 100%;
    margin-top: var(--space-5);
}
