/* ------------------------------------------------------------------------------------------
   One stylesheet for every school. The brand colour arrives as a custom property, set per
   request from the tenant config, so a new school never needs its own CSS — which is exactly
   how the three legacy sites ended up with three copies of Bootstrap 3, three sets of inline
   <style> blocks and a hardcoded `style="width: 1000px"` on the main panel.
   ------------------------------------------------------------------------------------------ */

/* Self-hosted rather than loaded from Google's CDN: no third-party request on a page that collects
   passport numbers, no extra DNS and TLS round trip for an applicant on a slow connection abroad,
   and it still works on networks that block outside hosts.

   One variable file covers every weight, and it carries the full latin-ext range — which matters
   here, because Croatian needs č ć š ž đ and the plain latin subset omits them.

   TODO: the same Inter release ships InterVariable.woff2, about a third the size. Drop it beside
   this one and change the two lines below; nothing else needs to move. */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/fonts/InterVariable.ttf") format("truetype-variations");
}

:root {
    --brand: #1f3a5f;
    --accent: #c8a35a;

    /* Cool, slightly blue-shifted neutrals. An admissions form is a long, careful task, so the
       page should recede and let the applicant's own answers be the only thing with contrast. */
    --ink: #101720;
    --ink-soft: #5b6572;
    --ink-faint: #8b949f;
    --line: #e3e7ec;
    --line-strong: #cbd2da;
    --surface: #ffffff;
    --canvas: #f7f8fa;
    --danger: #b3261e;
    --danger-soft: #fdf2f1;
    --success: #14663a;

    --radius: 12px;
    --radius-sm: 8px;

    /* Two shadows only: one for resting surfaces, one for the lifted state. */
    --shadow: 0 1px 2px rgb(16 23 32 / 4%), 0 1px 3px rgb(16 23 32 / 6%);
    --shadow-lift: 0 2px 4px rgb(16 23 32 / 6%), 0 12px 28px rgb(16 23 32 / 10%);

    --measure: 66ch;

    /* Inter for both roles, distinguished by weight and tracking rather than by mixing families.
       The system stack stays behind it so the page is readable in the moment before the font
       arrives, and on the rare machine that refuses it. */
    --sans: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
            Roboto, "Helvetica Neue", Arial, sans-serif;
    --display: "Inter", "Segoe UI Variable Display", "Segoe UI", system-ui, -apple-system,
               Roboto, sans-serif;
    --mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", monospace;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    font-family: var(--sans);
    line-height: 1.6;
    color: var(--ink);
    background: var(--canvas);
}

.wrap {
    width: 100%;
    max-width: 60rem;
    margin-inline: auto;
    padding-inline: 1.25rem;
}

.main { flex: 1; padding-block: 2.5rem 4rem; }

h1, h2, h3 {
    font-family: var(--display);
    font-weight: 600;
    line-height: 1.15;
    /* Ink, not brand colour. Coloured headings on every page made the brand shout on a form the
       applicant has to read twenty times; the colour now appears only where it identifies a school. */
    color: var(--ink);
    margin-block: 0 0.5rem;
    text-wrap: balance;
}

/* Negative tracking at display sizes only — it tightens large type and ruins small type. */
h1 { font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem); letter-spacing: -0.025em; }
h2 { font-size: 1.25rem; letter-spacing: -0.015em; }
h3 { font-size: 1.0625rem; letter-spacing: -0.01em; }

p { margin-block: 0 1rem; max-width: var(--measure); }

.lede { font-size: 1.0625rem; color: var(--ink-soft); }

a { color: var(--brand); }

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

.site-header {
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    /* Sticky so the school's identity and the language switcher stay reachable through a long form. */
    position: sticky;
    top: 0;
    z-index: 10;
}

.header-inner {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    min-height: 4rem;
}

.brand img { display: block; max-height: 2.25rem; width: auto; }

.brand-name {
    font-family: var(--display);
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: -0.01em;
    color: var(--ink);
}

.site-footer {
    border-top: 1px solid var(--line);
    background: var(--surface);
    padding-block: 1.5rem;
    font-size: 0.875rem;
    color: var(--ink-soft);
}

.site-footer p { margin-block-end: 0.25rem; }
.site-footer .policies a { margin-inline-end: 1rem; }

/* ---- School picker ------------------------------------------------------------------------ */

/* The picker is a registry of institutions, not a shop. A short alphabetical list of plates says
   that; a card grid would say "pick a product", and three cards in a row look sparse besides. Rows
   also keep every logo at one optical size and absorb a fourth school without reflowing. */

/* Centred rather than pinned to the top. This page holds one short decision, so a column of
   content with a void beneath it reads as unfinished; centring makes the emptiness deliberate. */
.picker {
    max-width: 44rem;
    min-height: min(60vh, 32rem);
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.school-grid {
    list-style: none;
    margin: 2.25rem 0 0;
    padding: 0;
    display: grid;
    gap: 0.625rem;
}

.school-card {
    --card-brand: var(--brand);

    display: grid;
    /* Wide enough for a stacked wordmark. PSM's logo is three lines of type, so a column sized for
       SSBM's horizontal lockup squeezed it. */
    grid-template-columns: 7rem 1fr 1.25rem;
    align-items: center;
    gap: 1.5rem;
    padding: 1.125rem 1.375rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    /* The school's own colour, as a spine. This is the signature: the only saturated colour on the
       page, and it belongs to the institution rather than to the portal. */
    border-inline-start: 4px solid var(--card-brand);
    box-shadow: var(--shadow);
    text-decoration: none;
    color: var(--ink);
    transition: box-shadow 160ms ease, border-color 160ms ease, transform 160ms ease;
}

.school-card:hover,
.school-card:focus-visible {
    border-color: var(--line-strong);
    border-inline-start-color: var(--card-brand);
    box-shadow: var(--shadow-lift);
    transform: translateY(-1px);
}

.school-logo {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 2.75rem;
}

.school-logo img { max-height: 2.75rem; max-width: 100%; width: auto; }

.school-name {
    font-family: var(--display);
    font-weight: 600;
    font-size: 1.0625rem;
    letter-spacing: -0.01em;
    line-height: 1.3;
    color: var(--ink);
}

/* Chevron drawn in CSS rather than shipped as an icon set for one glyph. It slides on hover: the
   only motion on the page, and it points where the click goes. */
.school-go {
    justify-self: end;
    width: 0.5rem;
    height: 0.5rem;
    border-top: 2px solid var(--ink-faint);
    border-right: 2px solid var(--ink-faint);
    rotate: 45deg;
    transition: translate 160ms ease, border-color 160ms ease;
}

.school-card:hover .school-go,
.school-card:focus-visible .school-go {
    translate: 3px 0;
    border-color: var(--card-brand);
}

@media (max-width: 30rem) {
    .school-card { grid-template-columns: 3.5rem 1fr; gap: 1rem; padding: 1rem; }
    .school-go { display: none; }
}

/* ---- Accessibility ------------------------------------------------------------------------ */

:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
    border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}

/* ---- Panels and forms --------------------------------------------------------------------- */

.two-col {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: 1fr;
    align-items: start;
}

@media (min-width: 52rem) {
    .two-col { grid-template-columns: 1.4fr 1fr; }
}

.panel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.75rem;
}

.panel-muted { background: #fbfcfd; box-shadow: none; }

.panel h2 { margin-block-start: 1.75rem; font-size: 1.125rem; }
.panel h2:first-of-type { margin-block-start: 1.5rem; }

.checklist { margin: 0 0 1.5rem; padding-inline-start: 1.1rem; color: var(--ink-soft); }
.checklist li { margin-block-end: 0.35rem; }

.stack { display: flex; flex-direction: column; gap: 1rem; align-items: flex-start; }

.field { display: flex; flex-direction: column; gap: 0.35rem; width: 100%; }

.field label { font-size: 0.875rem; font-weight: 600; color: var(--ink); }

/* Checkboxes are excluded throughout. They are drawn as a 20px box further down, and every
   property here fights that: min-height clamped them into tall rectangles, the padding pushed the
   tick off centre, and the focus ring landed on top of their own. Narrowing the selector fixes it
   at the source rather than by piling on overrides. */
.field input:not([type="checkbox"]), .field select, .field textarea {
    width: 100%;
    /* 44px tall: a real touch target, and it stops the form feeling cramped on a long page. */
    min-height: 2.75rem;
    padding: 0.5rem 0.75rem;
    font: inherit;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    transition: border-color 120ms ease, box-shadow 120ms ease;
}

.field input:not([type="checkbox"]):hover, .field select:hover, .field textarea:hover { border-color: var(--ink-faint); }

.field input:not([type="checkbox"]):focus, .field select:focus, .field textarea:focus {
    border-color: var(--brand);
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}

/* A field that failed validation is marked on the input itself, not only in the message below it. */
.field .input-validation-error {
    border-color: var(--danger);
    background: var(--danger-soft);
}

.hint { font-size: 0.875rem; color: var(--ink-soft); margin-block-start: 1rem; }

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem;
    padding: 0.5rem 1.25rem;
    font: inherit;
    font-weight: 600;
    letter-spacing: -0.005em;
    /* Secondary buttons are ink on a hairline, not outlined in brand colour. Two brand-coloured
       buttons side by side gave equal weight to "Back" and "Save and continue". */
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-decoration: none;
    transition: background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}

.btn:hover { border-color: var(--ink-faint); background: var(--canvas); }

.btn-primary {
    color: #fff;
    background: var(--brand);
    border-color: var(--brand);
    box-shadow: var(--shadow);
}

.btn-primary:hover {
    background: color-mix(in srgb, var(--brand) 88%, #000);
    border-color: color-mix(in srgb, var(--brand) 88%, #000);
}

.btn:disabled, .btn[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
    box-shadow: none;
}

/* ---- Application forms -------------------------------------------------------------------- */

.form-panel { max-width: 46rem; }

.form-grid {
    display: grid;
    gap: 1.125rem;
    grid-template-columns: 1fr;
    margin-block-start: 1.75rem;
}

@media (min-width: 40rem) {
    .form-grid { grid-template-columns: 1fr 1fr; }
    .field-wide { grid-column: 1 / -1; }
}

.field-hint { font-size: 0.8125rem; color: var(--ink-soft); }

.field-error { font-size: 0.8125rem; color: #b3261e; }
.field-error:empty { display: none; }

.field select[disabled] { background: #f2f4f6; color: var(--ink-soft); cursor: not-allowed; }

.check { display: flex; gap: 0.625rem; align-items: flex-start; font-weight: 400; }
.check input { width: auto; margin-block-start: 0.25rem; flex: none; }
.check span { font-size: 0.9375rem; line-height: 1.5; }
.check a { margin-inline-start: 0.35rem; }

.actions { display: flex; align-items: center; gap: 1.25rem; margin-block-start: 0.5rem; }

.btn-link { color: var(--ink-soft); text-decoration: underline; font-size: 0.9375rem; }

.alert {
    padding: 0.875rem 1rem;
    border-radius: 6px;
    border: 1px solid;
    margin-block-end: 1.25rem;
    font-size: 0.9375rem;
}

.alert:empty, .alert ul:empty { display: none; }

.alert-error { background: #fdf2f1; border-color: #f0c4c0; color: #8c1d18; }
.alert-error ul { margin: 0; padding-inline-start: 1.1rem; }

/* ---- Wizard ------------------------------------------------------------------------------- */

.wizard { display: grid; gap: 1.75rem; grid-template-columns: 1fr; align-items: start; }

@media (min-width: 56rem) {
    .wizard { grid-template-columns: 15rem 1fr; }
}

.progress-rail ol { list-style: none; margin: 0; padding: 0; }

.progress-rail a {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0 0.75rem;
    padding: 0.5rem 0.625rem;
    border-radius: 6px;
    text-decoration: none;
    color: var(--ink);
}

.progress-rail a:hover { background: #eef1f4; }

.progress-rail .marker {
    grid-row: 1 / 3;
    align-self: start;
    margin-block-start: 0.3rem;
    width: 0.75rem; height: 0.75rem;
    border-radius: 50%;
    border: 2px solid var(--line);
    background: var(--surface);
}

.progress-rail .label { font-size: 0.9375rem; font-weight: 600; }
.progress-rail .state { font-size: 0.75rem; color: var(--ink-soft); }

/* Green for done, red for started-but-incomplete. The old blue-for-done said nothing — it was just
   the brand colour — and amber read as an advisory when these are the things blocking submission.
   "Not started" stays a neutral outline: a step the applicant has not reached yet is not a fault,
   and painting the whole rail red on first arrival would be alarming rather than informative. */
.progress-rail .done .marker { background: var(--success); border-color: var(--success); }
.progress-rail .done .state { color: var(--success); }

.progress-rail .partial .marker { background: var(--danger); border-color: var(--danger); }
.progress-rail .partial .state { color: var(--danger); }

.progress-rail .current a { background: #eceff3; }
.progress-rail .current .label { font-weight: 700; }

.rail-note {
    font-size: 0.8125rem;
    color: var(--ink-soft);
    margin-block-start: 1rem;
    padding-inline: 0.625rem;
}

.wizard-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.wizard-head h1 { font-size: 1.625rem; }

.save-state { font-size: 0.8125rem; color: var(--ink-soft); }
.save-state.saved { color: #1b6b3a; }
.save-state.warn { color: #8c1d18; font-weight: 600; }
.save-state.dirty { color: var(--ink-soft); }

.wizard-panel textarea { resize: vertical; font: inherit; }

.alert-warn { background: #fff8e6; border-color: #e6d08a; color: #6b4e00; }

/* ---- Documents ---------------------------------------------------------------------------- */

.doc-list { list-style: none; margin: 1.5rem 0; padding: 0; display: grid; gap: 0.875rem; }

.doc-slot {
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 1rem 1.125rem;
    background: #fcfdfe;
}

.doc-slot.filled { border-color: color-mix(in srgb, var(--brand) 35%, var(--line)); background: var(--surface); }

.doc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.doc-name { font-weight: 600; font-size: 0.875rem; letter-spacing: 0.02em; }
.doc-accept { font-size: 0.75rem; color: var(--ink-soft); }

.req {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--ink-soft);
    text-transform: uppercase;
    margin-inline-start: 0.5rem;
    letter-spacing: 0.04em;
}

.doc-have {
    display: flex; align-items: center; gap: 1rem;
    margin-block: 0.75rem 0.5rem;
    font-size: 0.9375rem;
}

.doc-upload { display: flex; align-items: center; gap: 0.75rem; margin-block-start: 0.75rem; flex-wrap: wrap; }
.doc-upload input[type=file] { font-size: 0.875rem; flex: 1 1 14rem; min-width: 0; }

.doc-list.legacy li {
    display: flex; align-items: center; gap: 1rem;
    padding: 0.5rem 0; font-size: 0.9375rem;
}

.doc-list form { display: inline; margin: 0; }

.btn-link.danger { color: #8c1d18; border: 0; background: none; cursor: pointer; padding: 0; font: inherit; text-decoration: underline; }

.alert-ok { background: #f0f8f2; border-color: #b9dcc4; color: #1b6b3a; }
.alert-info { background: #eef4fb; border-color: #bcd3ea; color: #1c3f66; }

/* ---- Review ------------------------------------------------------------------------------- */

.review-list { list-style: none; margin: 1.5rem 0; padding: 0; display: grid; gap: 0.5rem; }

.review-list li { border: 1px solid var(--line); border-radius: 8px; padding: 0.875rem 1.125rem; }
.review-list li.done { background: #fcfdfe; }

/* Red, not amber. These are the things blocking submission, not advisories — and this is the last
   page before the applicant expects to be finished, so it should read as "fix this", not "note". */
.review-list li.todo {
    border-color: #f0c4c0;
    background: #fdf2f1;
    border-inline-start: 3px solid #b3261e;
}

.review-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.review-step { font-weight: 600; }
.review-list li.todo .review-step { color: #8c1d18; }

.missing { margin: 0.5rem 0 0; padding-inline-start: 1.1rem; font-size: 0.875rem; color: #8c1d18; }

.submit-form { margin-block-start: 1.75rem; }

/* ---- Status ------------------------------------------------------------------------------- */

.summary {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.4rem 1.25rem;
    margin-block: 1.5rem;
    font-size: 0.9375rem;
}

.summary dt { font-weight: 600; color: var(--ink-soft); }
.summary dd { margin: 0; }
.summary code { font-family: ui-monospace, Consolas, monospace; font-size: 0.9375rem; }

/* ---- Contract ----------------------------------------------------------------------------- */

.signature-input {
    font-family: "Segoe Script", "Bradley Hand", "Brush Script MT", cursive;
    font-size: 1.375rem;
    padding-block: 0.5rem;
}

/* The name and the confirmation checkbox produce the same alert box, so the rejected field says
   which one it was rather than making the applicant re-read both. */
.signature-input[aria-invalid="true"] {
    border-color: var(--danger);
    background: var(--danger-soft);
}

/* ---- Tables ------------------------------------------------------------------------------- */

.table { width: 100%; border-collapse: collapse; margin-block: 1rem 1.5rem; font-size: 0.9375rem; }
.table th, .table td { text-align: left; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--line); }
.table th { font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-soft); }

/* ---- Language switcher -------------------------------------------------------------------- */

/* A select rather than a row of links: at five languages the links wrapped under the logo on a
   phone, and the row grew every time a language was added. */

.lang-switch {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

.lang-switch select {
    padding: 0.25rem 1.75rem 0.25rem 0.5rem;
    font: inherit;
    font-size: 0.8125rem;
    color: var(--ink-soft);
    background-color: transparent;
    border: 1px solid transparent;
    border-radius: 4px;
    cursor: pointer;

    /* The caret is drawn here because removing the platform appearance also removes it, and
       without one this reads as a label rather than a control. */
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23667' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.5rem center;
    background-size: 0.625rem;
}

.lang-switch select:hover { background-color: #eef1f4; color: var(--ink); }

.lang-switch select:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 1px;
}

/* Shown only when the enhancement script has not run. */
.lang-switch button {
    padding: 0.25rem 0.5rem;
    font: inherit;
    font-size: 0.8125rem;
    color: var(--ink-soft);
    background: #eef1f4;
    border: 1px solid #d6dbe1;
    border-radius: 4px;
    cursor: pointer;
}

.lang-switch button[hidden] { display: none; }

/* ---- Field widths ------------------------------------------------------------------------- */

/* Its own row, so the fields that belong together can pair on the next one. */
.field-solo { grid-column: 1 / -1; }

/* A control should be about as wide as the value it holds. A title dropdown stretched to half the
   form, and an email box spanning the full width, both read as "type a lot here". */
.control-sm { max-width: 11rem; }
.control-md { max-width: 24rem; }

/* ---- Checkboxes --------------------------------------------------------------------------- */

/* Native checkboxes render at ~13px with no control over the focus ring or the checked colour,
   which is why the two on the registration page sat oddly against 44px-tall inputs. Drawn instead:
   same element, same keyboard behaviour, just sized and coloured to match everything else. */
.check input[type="checkbox"] {
    appearance: none;
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    /* Stated rather than left to default. height alone does not survive a min-height set by a
       broader rule — it clamps rather than loses, so the box silently stretches instead of being
       overridden outright, which is why this looked fine in the CSS and wrong on the page. */
    min-height: 1.25rem;
    padding: 0;
    box-sizing: border-box;
    margin: 0;
    margin-block-start: 0.125rem;
    border: 1px solid var(--line-strong);
    border-radius: 5px;
    background: var(--surface);
    cursor: pointer;
    display: grid;
    place-content: center;
    transition: background-color 120ms ease, border-color 120ms ease;
}

.check input[type="checkbox"]:hover { border-color: var(--ink-faint); }

.check input[type="checkbox"]::before {
    content: "";
    width: 0.625rem;
    height: 0.375rem;
    border-inline-start: 2px solid #fff;
    border-block-end: 2px solid #fff;
    rotate: -45deg;
    translate: 0 -1px;
    opacity: 0;
    transition: opacity 90ms ease;
}

.check input[type="checkbox"]:checked {
    background: var(--brand);
    border-color: var(--brand);
}

.check input[type="checkbox"]:checked::before { opacity: 1; }

.check input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* The whole row is the target, so the label text is clickable rather than the 20px box alone. */
.check { cursor: pointer; align-items: flex-start; }
.check span { cursor: pointer; }

/* ---- Documents ---------------------------------------------------------------------------- */

.checklist-docs { list-style: none; margin: 0.75rem 0 1.75rem; padding: 0; display: grid; gap: 0.5rem; }

.checklist-docs li {
    display: grid;
    grid-template-columns: 1.25rem 1fr auto;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.9375rem;
    color: var(--ink-soft);
}

.checklist-docs .tick {
    width: 1.125rem;
    height: 1.125rem;
    border: 1px solid var(--line-strong);
    border-radius: 50%;
    display: grid;
    place-content: center;
}

.checklist-docs .covered { color: var(--ink); }
.checklist-docs .covered .tick { background: var(--success); border-color: var(--success); }

.checklist-docs .covered .tick::before {
    content: "";
    width: 0.5rem;
    height: 0.3rem;
    border-inline-start: 2px solid #fff;
    border-block-end: 2px solid #fff;
    rotate: -45deg;
    translate: 0 -1px;
}

.upload-form { margin-block-end: 1.75rem; display: grid; gap: 1rem; justify-items: start; }
.upload-form .field { max-width: 26rem; }

.doc-row {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 0;
    border-block-end: 1px solid var(--line);
}

.doc-row:last-child { border-block-end: 0; }
.doc-file { font-size: 0.9375rem; word-break: break-all; }
.doc-relabel select { min-height: 2.25rem; padding-block: 0.25rem; font-size: 0.875rem; }
.doc-row form { margin: 0; }

.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ---- Drop zone ---------------------------------------------------------------------------- */

/* A label wrapping the real file input, so click, keyboard and screen readers work untouched and
   dropping just fills the same control. The legacy AjaxFileUpload did this with a toolkit; a label
   and twenty lines of JavaScript is the whole of it. */
.dropzone {
    display: grid;
    justify-items: center;
    gap: 0.375rem;
    padding: 2rem 1.5rem;
    border: 2px dashed var(--line-strong);
    border-radius: var(--radius);
    background: #fbfcfd;
    cursor: pointer;
    text-align: center;
    transition: border-color 120ms ease, background-color 120ms ease;
}

.dropzone:hover { border-color: var(--ink-faint); background: var(--canvas); }

.dropzone:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}

/* Held while a drag is over the zone, so it is obvious the drop will land. */
.dropzone.is-over {
    border-color: var(--brand);
    border-style: solid;
    background: color-mix(in srgb, var(--brand) 6%, var(--surface));
}

/* The input still receives every click and keystroke; it is only visually replaced. */
.dropzone input[type="file"] {
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* A tray, drawn rather than shipped as an icon file for one glyph. */
.dropzone-icon {
    width: 1.75rem;
    height: 1.25rem;
    border: 2px solid var(--ink-faint);
    border-top-color: transparent;
    border-radius: 0 0 5px 5px;
    position: relative;
}

.dropzone-icon::before {
    content: "";
    position: absolute;
    inset-inline-start: 50%;
    top: -0.75rem;
    width: 2px; height: 0.75rem;
    background: var(--ink-faint);
    translate: -50% 0;
}

.dropzone-icon::after {
    content: "";
    position: absolute;
    inset-inline-start: 50%;
    top: -0.75rem;
    width: 0.5rem; height: 0.5rem;
    border-inline-start: 2px solid var(--ink-faint);
    border-block-end: 2px solid var(--ink-faint);
    rotate: -45deg;
    translate: -50% 0;
}

.dropzone.is-over .dropzone-icon,
.dropzone.is-over .dropzone-icon::before,
.dropzone.is-over .dropzone-icon::after { border-color: var(--brand); background-color: var(--brand); }
.dropzone.is-over .dropzone-icon { background-color: transparent; border-top-color: transparent; }

.dropzone-main { font-weight: 600; font-size: 0.9375rem; }
.dropzone-hint { font-size: 0.8125rem; color: var(--ink-soft); }

.dropzone-chosen {
    list-style: none;
    margin: 0.75rem 0 0;
    padding: 0;
    display: grid;
    gap: 0.25rem;
    font-size: 0.875rem;
    color: var(--ink-soft);
}

.dropzone-chosen li::before { content: "— "; color: var(--ink-faint); }

/* A third weight, between primary and secondary: this action matters on the page but is not the
   way forward. Upload previously looked identical to Continue. */
.btn-accent {
    color: var(--brand);
    background: color-mix(in srgb, var(--brand) 8%, var(--surface));
    border-color: color-mix(in srgb, var(--brand) 30%, var(--line-strong));
}

.btn-accent:hover {
    background: color-mix(in srgb, var(--brand) 14%, var(--surface));
    border-color: var(--brand);
}
