/* ============================================================
   CV Builder — /cv-builder/
   Split layout: form (left) + live A4 preview (right).
   Preview is a true 210x297mm page so print output is exact.
   ============================================================ */

.cvb-wrap .lede { max-width: 62ch; margin-bottom: 1.6rem; }

/* ---- mobile tabs (hidden on desktop, where both panes show) ---- */
.cvb-tabs { display: flex; gap: .4rem; margin-bottom: 1.4rem; }
.cvb-tabs button {
  flex: 1; padding: .7rem 1rem; font: inherit; font-size: .9rem; font-weight: 600;
  border: 1px solid var(--line-light); background: var(--paper); color: var(--t-on-paper-mut);
  border-radius: var(--radius); cursor: pointer; transition: background .25s, color .25s, border-color .25s;
}
.cvb-tabs button.on { background: var(--ink); color: var(--t-on-ink); border-color: var(--ink); }

.cvb-split { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 2rem; align-items: start; }

/* ---- form side ---- */
.cvb-sec { padding-top: 1.5rem; margin-top: 1.5rem; border-top: 1px solid var(--line-light); }
.cvb-sec:first-of-type { padding-top: 0; margin-top: 0; border-top: 0; }
/* Numbered form-section labels ("06 — Your passport") carry no leading rule.
   The site eyebrow draws a 26px ::before line and spaces it with a flex `gap`, but this
   rule sets display:block, and `gap` only exists in flex and grid. So the line sat flush
   against the digits and read as a stray "__06" (Abhi, 2026-09-12). The number and its
   em dash already separate the label, so the line is dropped here rather than re-spaced.
   Scoped to .cvb-sec, which only /cv-maker uses: the hero eyebrow keeps its rule, and
   /apply's centred step headings are a different selector entirely. */
.cvb-sec > .eyebrow { display: block; margin-bottom: 1rem; }
.cvb-sec > .eyebrow::before { display: none; }
.cvb-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.1rem; }
.cvb-form .f.full, .cvb-grid .f.full { grid-column: 1 / -1; }
.cvb-form label { display: block; font-size: .84rem; font-weight: 600; color: var(--ink); margin-bottom: .35rem; }
.cvb-form label .opt { font-weight: 400; color: var(--t-on-paper-mut); }
.cvb-form input, .cvb-form textarea {
  width: 100%; padding: .75rem .9rem; border: 1px solid var(--line-light); border-radius: var(--radius);
  font: inherit; font-size: .93rem; color: var(--ink); background: var(--paper);
}
.cvb-form input:focus, .cvb-form textarea:focus { outline: none; border-color: var(--brass); background: var(--white); }
.cvb-form textarea { resize: vertical; }
.cvb-form .hint { font-size: .78rem; color: var(--t-on-paper-mut); margin-top: .35rem; }

.cvb-photo-row { display: flex; gap: 1.1rem; align-items: center; margin-bottom: 1.1rem; }
.cvb-photo-prev {
  width: 84px; height: 84px; flex: none; border-radius: 50%; overflow: hidden;
  border: 2px dashed var(--line-light); background: var(--paper);
  display: grid; place-items: center; font-size: .7rem; color: var(--t-on-paper-mut); text-align: center;
}
.cvb-photo-prev img { width: 100%; height: 100%; object-fit: cover; }
.cvb-photo-prev.has { border-style: solid; border-color: var(--green-deep); }
/* /cv-maker paints the thumbnail with background-image rather than an <img>, so it
   can mirror the same crop the candidate drags on the CV itself. Without cover/no-repeat
   the photo tiled at its natural size inside the circle. */
.cvb-photo-prev { background-repeat: no-repeat; background-position: center; }

/* zoom controls under the photo (/cv-maker) */
/* The native file input renders as "Choose File / No file chosen", which looks nothing
   like the rest of the site. Hide it and drive it from a styled <label for>, which keeps
   the control keyboard reachable and screen-reader correct (a display:none input is not
   focusable, so .visually-hidden must keep it in the layer tree). */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.visually-hidden:focus-visible + .uploadbtn, .visually-hidden:focus + .uploadbtn {
  outline: 2px solid var(--brass); outline-offset: 2px; }
.cvb-lbl { display: block; font-size: .84rem; font-weight: 600; color: var(--ink); margin-bottom: .45rem; }

.cvb-zoom { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.cvb-zoom span { font-size: .82rem; font-weight: 700; color: var(--ink); min-width: 3.4em; }
.btn-sm { padding: .42rem .8rem; font-size: .82rem; }

/* On a phone the two panes are tabs, so the preview must be free to size itself; the
   inline height scalePreview() reserves is for the desktop split only. */
@media (max-width: 1100px) {
  .cvb-split { grid-template-columns: 1fr; }
  .cvb-preview[hidden], .cvb-form[hidden] { display: none !important; }
}
@media (min-width: 1101px) {
  .cvb-tabs { display: none; }
  .cvb-preview { position: sticky; top: 88px; }
}
.uploadbtn {
  display: inline-block; padding: .6rem 1rem; border: 1px solid var(--line-light); border-radius: var(--radius);
  background: var(--paper); font-size: .88rem; font-weight: 600; cursor: pointer;
}
.uploadbtn:hover { border-color: var(--brass); background: var(--white); }

/* The helper line above these repeaters carries no bottom margin (.why is
   `margin: .35rem 0 0`), so the first row sat flush against the sentence explaining
   it. The gap belongs on the container, not on .why, because .why is also used
   directly above inputs that already have their own spacing. */
#expRows, #eduRows { margin-top: .7rem; }
#expRows:empty, #eduRows:empty { margin-top: 0; }

/* Same reason as #expRows above: .why has no bottom margin, so the tick list and the
   free-text input both sat flush under the sentence explaining them. Only one of the
   two is ever visible, and #interestsBox is display:none in free-text mode, so the
   wrap's gap lands under the hint there and under the list in tick mode. */
#interestsBox, #interestOtherWrap { margin-top: .7rem; }
/* .choice-group sets display:flex, which outranks the UA's [hidden] rule — so in
   free-text mode the emptied tick list stayed in flow and contributed its margin. */
#interestsBox[hidden] { display: none; }

.rowline { display: grid; grid-template-columns: 1fr auto; gap: .5rem; margin-bottom: .5rem; }
.rowline input { font-size: .9rem; }
/* Structured education / experience entries: one row of columns per entry, with
   the inline grid-template-columns set per row in apply-flow.js (ROW_COLS). */
.rowline-cols { align-items: start; gap: .4rem; margin-bottom: .55rem; }
.rowline-cols input { min-width: 0; }            /* let columns actually shrink */
@media (max-width: 900px) {
  /* Five columns stop being readable well before phone width: stack them into a
     labelled block per entry so each entry still reads as one thing. */
  .rowline-cols { grid-template-columns: 1fr 1fr auto !important; }
  .rowline-cols input:nth-child(1) { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .rowline-cols { grid-template-columns: 1fr auto !important; }
  .rowline-cols input { grid-column: 1 / 2; }
  .rowline-cols input:nth-child(1) { grid-column: 1 / -1; }
  .rowline-cols button { grid-row: 1; grid-column: 2; }
}
.rowline button {
  border: 1px solid var(--line-light); background: var(--paper); border-radius: var(--radius);
  width: 38px; cursor: pointer; color: #b3402a; font-size: 1.1rem; line-height: 1;
}
.addrow {
  border: 1px dashed var(--line-light); background: transparent; border-radius: var(--radius);
  padding: .5rem .9rem; font: inherit; font-size: .84rem; font-weight: 600;
  color: var(--brass-ink); cursor: pointer;
}
.addrow:hover { border-color: var(--brass); background: var(--brass-soft); }

.cvb-actions { display: flex; gap: .7rem; flex-wrap: wrap; margin-top: 1.8rem; }
.cvb-actions .btn { flex: 1 1 auto; justify-content: center; }
.btn-line { border: 1px solid var(--ink); color: var(--ink); background: transparent; }
.btn-line:hover { background: var(--ink); color: var(--t-on-ink); }

/* ---- preview side: a real A4 page ---- */
/* The CV document sets its OWN type. Fraunces (site display face) is a serif
   with optical sizing — wrong for a utilitarian CV read by employers and visa
   staff. The whole document uses the grotesk, with hierarchy carried by weight,
   size and tracking instead of by typeface. */
.cvb-preview { position: sticky; top: 90px; }
.cv-page {
  width: 210mm; min-height: 297mm; transform-origin: top left;
  background: #fff; color: #2b3642;
  font-family: "Hanken Grotesk", system-ui, sans-serif;
  font-size: 10.1pt; line-height: 1.5; font-weight: 400;
  -webkit-font-smoothing: antialiased;
  box-shadow: 0 10px 40px rgba(13,27,42,.16);
}

/* band */
.cv-band { background: #8c3b4a; color: #fff; display: flex; align-items: center;
  gap: 12mm; padding: 9mm 12mm 9mm 0; min-height: 44mm; }
.cv-photo { width: 40mm; height: 40mm; flex: none; margin-left: 11mm; border-radius: 50%;
  background: #f3f0ea center/cover no-repeat; box-shadow: 0 0 0 2.6mm #fff; }
/* Was an <h1>. The CV preview is a picture of a different document, so it must not
   be a second <h1> on the application page. Styling is unchanged. */
.cv-band-txt .cv-doc-t { font-family: inherit; font-size: 22.1pt; font-weight: 700;
  letter-spacing: .06em; margin: 0; color: #fff; line-height: 1.1; }
.cv-band-txt p { font-size: 14.2pt; font-weight: 400; letter-spacing: .01em;
  margin: 2.5mm 0 0; color: rgba(255,255,255,.95); line-height: 1.2; }

/* columns */
.cv-body { display: grid; grid-template-columns: 58mm 1fr; gap: 9mm; padding: 9mm 12mm 3mm; }
.cv-page h2 { font-family: inherit; font-size: 11pt; font-weight: 700;
  color: #8c3b4a; margin: 0 0 1.8mm; letter-spacing: .1em; text-transform: uppercase; }
.cv-left section, .cv-right section { margin-bottom: 6.5mm; }
.cv-page h2::after { content: ""; display: block; width: 17mm; height: .9mm;
  background: #8c3b4a; margin: 1.6mm 0 3mm; }

/* left rail */
.cv-left p { margin: 0; font-weight: 600; font-size: 10.1pt; color: #2b3642; }
.cv-left dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 2.2mm 3mm; align-items: baseline; }
.cv-left dt { font-weight: 700; font-size: 9pt; letter-spacing: .01em; color: #3a4552; }
.cv-left dd { margin: 0; font-size: 9.5pt; color: #2b3642; }

/* right column */
.cv-obj { margin: 0; font-size: 9.9pt; line-height: 1.6; color: #3a4552; }
.cv-pd { margin: 0; display: grid; grid-template-columns: 32mm 1fr; gap: 2.6mm 4mm; align-items: baseline; }
.cv-pd dt { font-weight: 700; font-size: 9.2pt; letter-spacing: .01em; color: #3a4552; position: relative; }
.cv-pd dt::after { content: ":"; position: absolute; right: -2.5mm; font-weight: 400; color: #93a0ad; }
.cv-pd dd { margin: 0; font-size: 9.9pt; white-space: pre-line; color: #2b3642; }

/* declaration */
.cv-decl { padding: 2mm 12mm 10mm; }
.cv-decl p { margin: 0; font-size: 9.5pt; line-height: 1.55; color: #3a4552; }
.cv-sign { display: flex; justify-content: space-between; align-items: flex-end;
  margin-top: 14mm; font-size: 9.5pt; font-weight: 600; color: #2b3642; }
.cv-sign b { font-weight: 400; color: #3a4552; }
.cv-sign .sig { border-top: .3mm solid #c3ccd4; padding-top: 1.6mm; min-width: 46mm; text-align: center; }

/* ---- responsive: stack + tabs under 1100px ---- */
@media (max-width: 1100px) {
  .cvb-split { grid-template-columns: 1fr; }
  .cvb-preview { position: static; overflow-x: auto; }
  .cvb-split > .cvb-form[hidden], .cvb-split > .cvb-preview[hidden] { display: none; }
}
@media (min-width: 1101px) { .cvb-tabs { display: none; } }
@media (max-width: 620px) { .cvb-grid { grid-template-columns: 1fr; } }

/* ---- print: the CV page only, at exact A4 ---- */
/* (old .cvb-wrap-scoped print block removed — it hid the CV on /apply/) */

/* ============================================================
   Timeline flow on /apply/  (rail + step panels + photo tools)
   ============================================================ */
.tl-rail { list-style: none; display: flex; margin: 0 0 2rem; padding: 0; counter-reset: s; }
.tl-rail li { flex: 1; position: relative; text-align: center; cursor: pointer; padding-top: 2.4rem; }
.tl-rail li::before { content: ""; position: absolute; top: 1.05rem; left: 0; right: 0;
  height: 2px; background: var(--line-light); }
.tl-rail li:first-child::before { left: 50%; }
.tl-rail li:last-child::before { right: 50%; }
.tl-rail .dot { position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 2.1rem; height: 2.1rem; border-radius: 50%; display: grid; place-items: center;
  background: var(--paper); border: 2px solid var(--line-light);
  font-size: .82rem; font-weight: 700; color: var(--t-on-paper-mut); transition: all .3s; }
.tl-rail .lb { font-size: .76rem; font-weight: 600; color: var(--t-on-paper-mut); letter-spacing: .01em; }
.tl-rail li.done .dot { background: var(--green-deep); border-color: var(--green-deep); color: #fff; }
.tl-rail li.done .lb { color: var(--t-on-paper); }
.tl-rail li.on .dot { background: var(--ink); border-color: var(--ink); color: var(--t-on-ink); transform: translateX(-50%) scale(1.12); }
.tl-rail li.on .lb { color: var(--ink); font-weight: 700; }

.tl-nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin-top: 2rem; padding-top: 1.4rem; border-top: 1px solid var(--line-light); }
.tl-count { font-size: .82rem; font-weight: 600; color: var(--t-on-paper-mut); }
.step-panel[hidden] { display: none; }
.form-field label .opt { font-weight: 400; color: var(--t-on-paper-mut); }

/* photo controls */
.cv-photo-ctl { display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; margin-bottom: 1.3rem; }
.cvb-photo-prev { background-repeat: no-repeat; }
.cv-photo-tools { flex: 1 1 240px; }
.zoomrow { display: flex; align-items: center; gap: .5rem; margin-top: .7rem; }
.zoomrow label { margin: 0; font-size: .8rem; }
.zoomrow input[type=range] { flex: 1; accent-color: var(--brass-ink); }
.zbtn { width: 30px; height: 30px; border: 1px solid var(--line-light); background: var(--paper);
  border-radius: var(--radius); font-size: 1rem; line-height: 1; cursor: pointer; color: var(--ink); }
.zbtn:hover { border-color: var(--brass); background: var(--white); }
.cv-photo.draggable { cursor: grab; }
.cv-photo.draggable:active { cursor: grabbing; }

@media (max-width: 620px) {
  .tl-rail .lb { display: none; }
  .tl-rail li { padding-top: 2.2rem; }
}

/* ---- fixes: .hint was scoped to .cvb-form; this form is .apply-card ------- */
.apply-card .hint,
.cv-photo-tools .hint { font-size: .8rem; line-height: 1.45; color: var(--t-on-paper-mut); margin: .4rem 0 0; }
.step-panel > .hint { margin: -.3rem 0 1.4rem; max-width: 58ch; }

/* ---- photo control: one tidy panel, not four loose parts ---------------- */
.cv-photo-ctl {
  display: flex; gap: 1.1rem; align-items: center; flex-wrap: nowrap;
  padding: 1rem 1.1rem; margin-bottom: 1.4rem;
  border: 1px solid var(--line-light); border-radius: var(--radius); background: var(--paper);
}
.cv-photo-ctl .cvb-photo-prev { width: 72px; height: 72px; }
.cv-photo-tools { flex: 1 1 auto; min-width: 0; }
.cv-photo-tools .uploadbtn { display: inline-block; padding: .5rem .9rem; font-size: .85rem; }
.zoomrow { display: flex; align-items: center; gap: .5rem; margin-top: .6rem; }
.zoomrow label { margin: 0; font-size: .78rem; font-weight: 600; color: var(--t-on-paper-mut); flex: none; }
.zoomrow input[type=range] { flex: 1 1 auto; min-width: 0; height: 4px; accent-color: var(--brass-ink); }
.zbtn { flex: none; width: 28px; height: 28px; display: grid; place-items: center; }
@media (max-width: 620px) {
  .cv-photo-ctl { flex-wrap: wrap; }
  .cv-photo-tools { flex: 1 1 100%; }
}

/* ---- address block --------------------------------------------------- */
.addr-block {
  margin-top: 1.3rem; padding: 1.2rem 1.2rem 1.3rem;
  border: 1px solid var(--line-light); border-radius: var(--radius); background: var(--paper);
}
.addr-h {
  display: block; margin-bottom: 1rem; font-size: .72rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--brass-ink);
}
.addr-block input[readonly] { background: var(--paper-2); color: var(--t-on-paper-mut); cursor: default; }
/* #age becomes readonly once a date of birth is entered (it is derived from it).
   Same treatment as the readonly address fields so it reads as "filled for you"
   rather than broken. (2026-08-08) */
.apply-card #age[readonly] { background: var(--paper-2); color: var(--t-on-paper-mut); cursor: default; }
.addr-block .form-field select { width: 100%; }

/* ============================================================
   UX pass — reassurance, rhythm, touch targets, feedback
   ============================================================ */

/* intro: set expectations before the first field (time + privacy) */
.apply-intro { display: flex; flex-wrap: wrap; gap: .5rem 1.6rem; align-items: center;
  margin: 0 0 1.8rem; padding: .9rem 1.1rem; border-radius: var(--radius);
  background: var(--paper-2); }
.apply-intro span { display: inline-flex; align-items: center; gap: .45rem;
  font-size: .84rem; font-weight: 600; color: var(--t-on-paper); }
.apply-intro svg { width: 15px; height: 15px; stroke: var(--green-deep); fill: none; stroke-width: 2; flex: none; }

/* saved-progress toast */
.save-note { position: fixed; left: 50%; bottom: 1.2rem; transform: translate(-50%, 1.5rem);
  background: var(--ink); color: var(--t-on-ink); font-size: .8rem; font-weight: 600;
  padding: .55rem 1rem; border-radius: 999px; opacity: 0; pointer-events: none;
  transition: opacity .3s, transform .3s; z-index: 60; }
.save-note.on { opacity: 1; transform: translate(-50%, 0); }

/* rail: completion is earned, not implied */
.tl-rail li.done .dot::after { content: "✓"; font-size: .9rem; }
.tl-rail li.done .dot { font-size: 0; }
.tl-rail li:not(.on):not(.done) .dot { background: var(--white); }

/* generous field rhythm + real touch targets (44px min) */
.step-panel .form-grid { gap: 1.35rem 1.3rem; }
/* Checkboxes and radios are excluded: a 48px touch-target min-height is meant for
   text fields, and on a checkbox it inflates the BOX to 48px while the glyph stays
   17px and centres inside it — which pushed the pack confirmations 17px below their
   own first line of text. The label around a checkbox is the touch target, not the
   box itself. */
.apply-card .form-field input:not([type="checkbox"]):not([type="radio"]),
.apply-card .form-field select,
.apply-card .form-field textarea { padding: .85rem 1rem; font-size: 1rem; min-height: 48px; }
.apply-card .form-field label { font-size: .8rem; letter-spacing: .01em; margin-bottom: .45rem; }

/* Open <select> popups are drawn by the OS on macOS and iOS, so these rules only land
   on Firefox, Windows and Android. Anything STRUCTURAL has to be done in the markup:
   that is why "Other / role not listed" sits inside its own <optgroup> at the end of
   #role rather than as a bare trailing <option>, which rendered flush-left at
   optgroup-LABEL depth and read as a heading rather than a choice. */
.apply-card .form-field select optgroup {
  font-family: var(--body); font-style: normal; font-weight: 700;
  color: var(--t-on-paper); background: var(--white); }
.apply-card .form-field select option {
  font-weight: 400; color: var(--t-on-paper); background: var(--white); padding: .35rem .5rem; }
.apply-card .form-field select option:checked { font-weight: 600; }
.apply-card .form-field textarea { min-height: 92px; }

/* inline validity: quiet success, loud failure */
.form-field.ok input, .form-field.ok select { border-color: rgba(53,122,31,.5); }
.form-field.err input, .form-field.err select, .form-field.err textarea { border-color: #b3402a; background: #fdf6f4; }
.form-field .err-msg { font-weight: 600; }

/* helper text that answers "why are you asking?" */
.why { font-size: .78rem; color: var(--t-on-paper-mut); margin: .35rem 0 0; }

/* step nav: sticky on mobile so Continue is always reachable */
.tl-nav .btn { min-height: 48px; padding-inline: 1.4rem; }

/* photo: dropzone first, controls only once there is something to control */
.cv-photo-ctl { display: block; padding: 0; border: 0; background: none; margin-bottom: 1.4rem; }
.cv-adjust { padding: 1rem 1.1rem; border: 1px solid var(--line-light);
  border-radius: var(--radius); background: var(--paper); }
.cv-adjust[hidden] { display: none; }
.cv-adjust-top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .8rem; }
.cv-adjust-t { font-size: .84rem; font-weight: 700; color: var(--ink); }
.linkbtn { border: 0; background: none; padding: 0; font: inherit; font-size: .82rem;
  font-weight: 600; color: var(--brass-ink); text-decoration: underline;
  text-underline-offset: 2px; cursor: pointer; }
.zoomrow { display: flex; align-items: center; gap: .7rem; margin: 0; }
.zbtn { width: 34px; height: 34px; font-size: 1.05rem; }

/* ============================================================
   Desktop width + CV document refinement
   A4 at 96dpi = 794px. The card was 760px, so the CV was always
   scaled DOWN and could never be read. Card now clears 794px of
   inner width, so fit() lands on scale 1.0 and the CV renders
   at true size.
   ============================================================ */
@media (min-width: 940px) {
  .apply-card { max-width: 1080px; padding: 3rem 3.2rem; }
  .cvb-wrap .wrap, .sec .wrap { max-width: 1160px; }
}
@media (min-width: 1240px) {
  .apply-card { max-width: 1140px; }
}

/* photo ring: 2.6mm was a thick white collar. Hairline instead. */
.cv-photo { box-shadow: 0 0 0 1mm rgba(255,255,255,.92); }

/* ---- CV document: proportion, rhythm, restraint ---------------------- */
.cv-page { font-size: 10.3pt; line-height: 1.52; color: #2f3a46; }

/* band: shallower, better balanced, name given room to breathe */
.cv-band { min-height: 40mm; padding: 8mm 12mm 8mm 0; gap: 11mm; align-items: center; }
.cv-photo { width: 36mm; height: 36mm; margin-left: 12mm; }
.cv-band-txt .cv-doc-t { font-size: 19.9pt; font-weight: 600; letter-spacing: .14em; }
.cv-band-txt p { font-size: 14.7pt; font-weight: 500; margin-top: 3mm; letter-spacing: 0; }

/* two columns: wider rail, cleaner gutter, hairline divider between them */
.cv-body { grid-template-columns: 56mm 1fr; gap: 11mm; padding: 10mm 12mm 4mm; position: relative; }
.cv-right { border-left: .25mm solid #e6e2db; padding-left: 10mm; margin-left: -1mm; }

/* headings: smaller, wider tracking, shorter rule. Restraint over shout. */
.cv-page h2 { font-size: 9.9pt; font-weight: 700; letter-spacing: .16em; color: #8c3b4a; margin-bottom: 0; }
.cv-page h2::after { width: 11mm; height: .6mm; margin: 1.8mm 0 3.4mm; opacity: .85; }
.cv-left section, .cv-right section { margin-bottom: 7.5mm; }
.cv-left section:last-child, .cv-right section:last-child { margin-bottom: 0; }

/* left rail values sit quieter than their labels */
.cv-left p { font-size: 10.5pt; font-weight: 600; color: #1f2933; }
.cv-left dl { gap: 2.6mm 3mm; }
.cv-left dt { font-size: 8.6pt; font-weight: 600; color: #6b7681; letter-spacing: .02em; }
.cv-left dd { font-size: 9.7pt; font-weight: 500; color: #1f2933; }

/* personal details: aligned colon column, generous leading */
.cv-pd { grid-template-columns: 30mm 1fr; gap: 3mm 5mm; }
.cv-pd dt { font-size: 8.8pt; font-weight: 600; color: #6b7681; letter-spacing: .02em; }
.cv-pd dt::after { right: -3mm; color: #c2cad2; }
.cv-pd dd { font-size: 9.9pt; color: #1f2933; line-height: 1.5; }
.cv-obj { font-size: 9.9pt; line-height: 1.65; color: #46525e; }

/* declaration: separated by space, not by a box */
.cv-decl { padding: 6mm 12mm 11mm; }
.cv-decl h2 { margin-bottom: 0; }
.cv-decl p { font-size: 9.2pt; line-height: 1.6; color: #46525e; max-width: 165mm; }
.cv-sign { margin-top: 15mm; font-size: 9.2pt; }
.cv-sign .sig { border-top: .25mm solid #c2cad2; padding-top: 2mm; min-width: 52mm; font-weight: 600; }

/* ============================================================
   FIX: preview container inside the step flow
   `position:sticky` was a leftover from the old side-by-side
   builder. Inside a step panel it detached the page from normal
   flow, so the A4 sheet overflowed right and the Download button
   rode up beside it. Preview is now a plain, centred block.
   ============================================================ */
.step-panel .cvb-preview {
  position: static;
  display: flex; justify-content: center;
  width: 100%; overflow: hidden;
  background: var(--paper-2);
  border: 1px solid var(--line-light); border-radius: var(--radius);
  padding: 1.6rem;
}
.step-panel .cvb-preview .cv-page {
  transform-origin: top center;
  box-shadow: 0 6px 28px -10px rgba(13,27,42,.28), 0 0 0 1px rgba(13,27,42,.06);
  flex: none;
}
/* the sheet is a true A4 page: keep the proportion, lose the dead void by
   letting short CVs end naturally while still printing full-page */
.step-panel .cv-page { min-height: 0; }

/* download sits below the sheet, never beside it */
#btnPdf { display: block; clear: both; }

/* ---- documents step: one column, clear grouping ---------------------- */
.doc-group { margin-top: 1.5rem; }
.doc-group > label { display: block; font-size: .84rem; font-weight: 700; color: var(--ink); margin-bottom: .5rem; }
.doc-group .why { margin-top: .5rem; }
.doc-help { margin-top: 1.5rem; border: 1px solid var(--line-light); border-radius: var(--radius); background: var(--paper); }
.doc-help > summary { cursor: pointer; padding: .85rem 1.1rem; font-size: .86rem; font-weight: 600; color: var(--ink); list-style: none; }
.doc-help > summary::-webkit-details-marker { display: none; }
.doc-help > summary::after { content: "+"; float: right; color: var(--brass-ink); font-size: 1.1rem; line-height: 1; }
.doc-help[open] > summary::after { content: "−"; }
.doc-help-body { padding: 0 1.1rem 1.1rem; }
.doc-help-body .file-drop { margin-top: .8rem; }

/* ---- terms & conditions disclosure (step 5) — long legal text stays
   collapsed until opened, then scrolls in place instead of stretching the page ---- */
.terms-details { margin-top: 1rem; }
.terms-body { max-height: 320px; overflow-y: auto; font-size: .82rem; line-height: 1.6; color: var(--t-on-paper-mut); border-top: 1px solid var(--line-light); padding-top: .9rem; }
.terms-body h3 { margin: 0 0 .7rem; font-family: var(--display); font-size: 1rem; font-weight: 600; color: var(--ink); }
.terms-body p { margin: 0 0 .85rem; }
.terms-body p:last-child { margin-bottom: 0; }
.terms-body b { color: var(--ink); }

/* ============================================================
   CV palette + masthead hierarchy
   Maroon came from the reference template, not the brand. Navy
   (--ink) with a turmeric rule is the Disha palette. And the
   NAME is the subject of the document, so it leads: the words
   "Curriculum Vitae" are only a label and now behave like one.
   ============================================================ */
.cv-band { background: #0d1b2a; }
.cv-page h2 { color: #0d1b2a; }
.cv-page h2::after { background: #d99b23; opacity: 1; }

/* masthead: label small and quiet, name large and dominant */
.cv-band-txt .cv-doc-t {
  font-size: 8.6pt; font-weight: 600; letter-spacing: .32em;
  text-transform: uppercase; color: rgba(243,238,228,.62);
  margin: 0 0 3.5mm; line-height: 1;
}
.cv-band-txt p {
  font-size: 25pt; font-weight: 600; letter-spacing: -.005em;
  line-height: 1.08; margin: 0; color: #fff;
}

/* turmeric hairline tying the name to the brand accent */
.cv-band-txt { position: relative; padding-bottom: 1mm; }
.cv-band-txt::after {
  content: ""; display: block; width: 16mm; height: .7mm;
  background: #d99b23; margin-top: 4mm;
}

/* photo ring reads against navy rather than maroon */
.cv-photo { box-shadow: 0 0 0 .9mm rgba(243,238,228,.85); }

/* ---- section headings: no rule. Space and weight do the separating. ---- */
.cv-page h2::after { content: none; }
.cv-page h2 { margin: 0 0 2.6mm; }
.cv-left section, .cv-right section { margin-bottom: 8mm; }
.cv-decl h2 { margin-bottom: 2.2mm; }

/* ---- signature pad ---------------------------------------------------- */
.sig-ctl { margin-top: 1.1rem; padding: 1rem 1.1rem; border: 1px solid var(--line-light);
  border-radius: var(--radius); background: var(--paper); }
/* baseline put the <button> and the <label> on different lines - they are the
   same control to a candidate, so they centre on each other instead. */
.sig-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-bottom: .7rem; }
.sig-actions { display: flex; align-items: center; gap: 1rem; line-height: 1; }
/* The <label> picked up the form's label font-size and bottom margin, so it sat a
   few pixels above the <button> beside it. Same size, no margin, both centred. */
.sig-head .sig-actions .linkbtn { font-size: .82rem; line-height: 1; margin: 0; padding: 0; }
#sigPad { display: block; width: 100%; height: 120px; background: var(--white);
  border: 1px dashed var(--line-light); border-radius: var(--radius);
  cursor: crosshair; touch-action: none; }
#sigPad.has { border-style: solid; border-color: var(--green-deep); }
.sig-ctl .why { margin-top: .6rem; }

/* signature on the CV: image sits ON the rule, label beneath */
.cv-sign .sig { display: flex; flex-direction: column; align-items: center;
  border-top: 0; padding-top: 0; min-width: 52mm; }
.cv-sign .sig #cvSigImg { display: block; max-width: 46mm; max-height: 13mm;
  object-fit: contain; margin-bottom: 1mm; }
.cv-sign .sig #cvSigImg[hidden] { display: none; }
.cv-sign .sig-lb { border-top: .25mm solid #c2cad2; padding-top: 2mm;
  width: 100%; text-align: center; font-weight: 600; }

/* err-msg outside a .form-field would render always-on at body size.
   Belt-and-braces so no future block repeats that. */
.step-panel .err-msg { font-size: .78rem; font-weight: 600; color: #b3402a; margin-top: .35rem; }
.step-panel .form-field:not(.err) > .err-msg { display: none; }
.doc-group > label { margin-bottom: .5rem; }

/* form fills the same measure as the header nav (site --maxw 1280) */
@media (min-width: 940px) {
  .apply-card { max-width: none; padding: 3rem 3.4rem; }
  .cvb-wrap .wrap, .sec .wrap { max-width: var(--maxw); }
}
@media (min-width: 1240px) { .apply-card { max-width: none; } }

/* scan instructions: visible, two-up, not buried in a disclosure */
.scan-how { margin-top: 1.4rem; padding: 1.1rem 1.2rem; border: 1px solid var(--line-light);
  border-radius: var(--radius); background: var(--paper); }
.scan-how-t { display: block; font-size: .84rem; font-weight: 700; color: var(--ink); margin-bottom: .8rem; }
.scan-how-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.6rem; }
.scan-how-grid b { font-size: .82rem; color: var(--ink); }
.scan-how-grid .why { margin-top: .25rem; }
.scan-how > .why { margin-top: .9rem; padding-top: .8rem; border-top: 1px solid var(--line-light); }
@media (max-width: 620px) { .scan-how-grid { grid-template-columns: 1fr; } }

/* ---- step headings centred, with the rule balanced on both sides ------- */
.step-panel > .form-section > .eyebrow {
  display: flex; align-items: center; justify-content: center;
  gap: .8rem; text-align: center; margin-bottom: 1.4rem;
}
.step-panel > .form-section > .eyebrow::before,
.step-panel > .form-section > .eyebrow::after {
  content: ""; width: 26px; height: 1px; background: currentColor; opacity: .45; flex: none;
}
/* the intro line under a centred heading reads better centred too */
.step-panel > .form-section > .hint { text-align: center; margin-inline: auto; }
.sig-ctl .err-msg { display: none; }
.sig-ctl.err .err-msg { display: block; }
.sig-ctl.err #sigPad { border-color: #b3402a; border-style: solid; background: #fdf6f4; }

/* ============================================================
   PRINT — rewritten for /apply/
   The previous block scoped to .cvb-wrap/.cvb-split, which only
   existed on the retired /cv-builder/ page. On /apply/ that rule
   hid every top-level element, so printing produced a blank page.
   visibility (not display) keeps layout intact while showing only
   the CV, and works regardless of surrounding page structure.
   ============================================================ */
@media print {
  /* Page 1 keeps margin 0 so the maroon band bleeds to the sheet edge, which is the whole
     look of the document. Pages after it are continuation pages with no band, and under
     margin:0 their text began flush against the paper edge, where most physical printers
     clip. They get real margins instead. fitNote() uses the same numbers so the page count
     on screen matches what comes out of the printer. */
  @page { size: A4; margin: 12mm 0 10mm; }
  @page :first { margin: 0; }
  html, body { background: #fff !important; margin: 0 !important; padding: 0 !important; }
  /* `visibility:hidden` hides paint but KEEPS layout space, so every form step,
     the timeline rail and the nav were still occupying full height - and
     `.step-panel[hidden]{display:block}` below forced all 5 steps to lay out at
     once. The CV printed on page 1 and all that invisible height became trailing
     BLANK PAGES. Remove them from layout instead, walking the known ancestor
     chain: section.section > .wrap > #applyForm > .step-panel > .form-section >
     #cvbPreview > #cvPage. */
  /* Generalised 2026-09-11 for /cv-maker. The chain above was hardcoded to
     /apply's ancestors (section.section > .wrap > #applyForm > .step-panel >
     .form-section > #cvbPreview > #cvPage) and printed nothing on any other page.
     One rule now says the same thing structurally: hide every element that is not
     #cvPage, not inside it, and not an ancestor of it. Ancestors survive because
     they match :has(#cvPage). Verified to leave /apply's output byte-comparable and
     still one page. */
  body *:not(:has(#cvPage)):not(#cvPage):not(#cvPage *) { display: none !important; }
  /* An ancestor may carry [hidden] (on /apply the CV's own step does), and the UA
     sheet's [hidden]{display:none} still applies after the rule above spares it. */
  body :has(#cvPage) { display: block !important; }
  /* `display: revert` reverts to the USER-AGENT default, which is `block` for a div —
     so this flattened every flex and grid inside the CV: the hero stopped being a row
     (photo above the name instead of beside it) and the two-column body collapsed into
     one, leaving the right-hand half of every printed page empty. The hiding rules above
     only ever touch ANCESTORS of #cvPage, so its descendants never needed reviving —
     they need to stay visible, nothing more. */
  #cvPage * { visibility: visible !important; }
  #cvPage { display: block !important; visibility: visible !important; }
  #cvPage {
    position: absolute !important; left: 0 !important; top: 0 !important;
    width: 210mm !important; min-height: 297mm !important;
    margin: 0 !important; transform: none !important;
    box-shadow: none !important; border-radius: 0 !important;
  }
  .cvb-preview { position: static !important; padding: 0 !important; border: 0 !important;
    background: none !important; height: auto !important; overflow: visible !important; }
  .step-panel[hidden]:has(#cvPage) { display: block !important; }  /* only the CV's own step */
  .cv-band { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }

  .cv-page { background-image: none !important; }  /* the screen-only page guides */

  /* Pagination. A section must be ALLOWED to split: with break-inside:avoid on
     `.cv-right section`, the personal-details table became one unbreakable ~250mm block,
     so page 1 printed the band alone, the body landed on page 2 and the declaration on
     page 3 (measured 2026-09-12). Keep only the small units whole. */
  .cv-left section, .cv-right section, .cv-pd, .cv-left dl,
  .cv-skills { break-inside: auto; page-break-inside: auto; }
  .cv-page h2 { break-after: avoid; page-break-after: avoid; }
  .cv-decl { break-inside: avoid; page-break-inside: avoid; }
  .cv-pd dt, .cv-pd dd, .cv-left dt, .cv-left dd { break-inside: avoid; page-break-inside: avoid; }
  .cv-decl { break-before: auto; page-break-before: auto; }
  .cv-sign { break-inside: avoid; page-break-inside: avoid; }
  .cv-band { break-after: avoid; page-break-after: avoid; }
  /* a page 2 starts flush at the sheet edge under margin:0 — give it air */
  .cv-body { padding-top: 10mm; }
}

/* optional CV sections: summary paragraph reuses .cv-obj, competencies are a list */
/* Single column: this list sits in the 56mm left rail, under the passport details
   (Abhi, 2026-09-13). Two columns there would be ~24mm each and wrap every skill onto
   three lines. Sized to match the rail's other values. */
.cv-skills { margin: 0; padding: 0; list-style: none;
  font-size: 9.7pt; font-weight: 500; color: #1f2933; }
.cv-skills li { position: relative; padding-left: 4.4mm; margin: 0 0 1.6mm;
  break-inside: avoid; page-break-inside: avoid; }
.cv-skills li::before { content: ""; position: absolute; left: 0; top: 1.8mm;
  width: 1.7mm; height: 1.7mm; border-radius: 50%; background: #8c3b4a; }

/* the toggles that switch those sections on, in the form */
.cvb-toggle { display: flex; align-items: center; gap: .6rem; cursor: pointer;
  margin: .2rem 0 .55rem; font-weight: 600; color: var(--t-on-paper); }
.cvb-toggle input { flex: none; width: 1.05rem; height: 1.05rem; accent-color: var(--green-deep); }
.cvb-opt { margin: 0 0 1.1rem; padding-left: 1.65rem; }
.cvb-opt textarea { width: 100%; font: inherit; font-size: .95rem; color: inherit;
  background: var(--white); border: 1px solid var(--line-light); border-radius: var(--radius);
  padding: .7rem .8rem; resize: vertical; min-height: 5.5rem; }
.cvb-opt textarea:focus-visible { outline: 2px solid var(--brass); outline-offset: 1px; }

/* one line per entry, kept as typed */
.cv-lines { margin: 0; white-space: pre-line; font-size: 9.9pt; color: #2b3642; }

/* A long CV runs onto further sheets, so show where the paper will split. Two layers,
   because the sheets are not all the same height: page 1 prints edge to edge, and every
   page after it loses 22mm to the margins in the @page rules below. Screen only. */
.cv-page {
  background-image:
    linear-gradient(to bottom, rgba(140,59,74,.22) 0 100%),
    linear-gradient(to bottom, transparent 0 274.2mm, rgba(140,59,74,.22) 274.2mm 275mm);
  background-position: 0 296.2mm, 0 297mm;
  background-size: 100% .8mm, 100% 275mm;
  background-repeat: no-repeat, repeat-y;
}

/* one-page fit indicator (screen only) */
.cv-fit { display: flex; align-items: center; gap: .5rem; margin-top: .8rem;
  font-size: .8rem; font-weight: 600; }
.cv-fit.ok { color: var(--green-deep); }
.cv-fit.over { color: #b3402a; }
.cv-fit .why { margin: 0; font-weight: 400; color: var(--t-on-paper-mut); }

/* upload icon: .file-drop centres its text but the SVG had no auto margins,
   so it sat pinned to the left while the labels centred under it. */
.file-drop svg { display: block; margin-inline: auto; margin-bottom: .55rem; }
.file-drop { display: flex; flex-direction: column; align-items: center; justify-content: center; }
.file-drop .fd-main, .file-drop .fd-sub { width: 100%; }

/* ============================================================
   FIX: step nav must stay INSIDE the card
   The earlier sticky rule used margin-inline:-gut to go full-bleed,
   which tore the nav out of the white .apply-card and left it
   floating on the paper background with Continue past the card
   edge. It now stays within the card at every width.
   ============================================================ */
.tl-nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin: 2rem 0 0; padding-top: 1.4rem;
  border-top: 1px solid var(--line-light); background: transparent;
  position: static; box-shadow: none; inset: auto;
}
.tl-nav .btn { flex: 0 0 auto; }
.tl-count { flex: 1 1 auto; text-align: center; }

@media (max-width: 420px) {
  .tl-count { display: none; }   /* rail already shows position; keep buttons roomy */
}


/* ============================================================
   FINAL: step nav is a plain in-flow row inside the card.
   Sticky positioning made it look detached from the card on
   narrow windows, so it is gone. Predictable at every width.
   ============================================================ */
.tl-nav {
  position: static !important;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; width: 100%;
  margin: 2.2rem 0 0; padding: 1.4rem 0 0;
  border-top: 1px solid var(--line-light);
  background: transparent; box-shadow: none;
}
.tl-nav .btn { flex: 0 0 auto; min-width: 108px; justify-content: center; }
.tl-nav .tl-count { flex: 1 1 auto; text-align: center; white-space: nowrap; }
@media (max-width: 480px) {
  .tl-nav { gap: .6rem; }
  .tl-nav .btn { min-width: 0; padding-inline: 1rem; }
  .tl-nav .tl-count { font-size: .74rem; }
}

/* ---- breathing room between form rows -------------------------------- */
/* Fields carry helper text of differing lengths, so a flat grid gap leaves
   some rows looking cramped. Give each field a floor of its own. */
.step-panel .form-grid { gap: 1.7rem 1.4rem; }
.step-panel .form-field { display: flex; flex-direction: column; }
.step-panel .form-field .why { margin-top: .45rem; }
.step-panel .form-field + .form-field { margin-top: 0; }
/* the extras grid sits under the main grid inside a section */
.step-panel .form-grid + .form-grid { margin-top: 1.7rem; }

/* Fields that sit OUTSIDE a .form-grid (e.g. Key skills, which follows the
   grid as a standalone block) get no row-gap from the grid, so they need an
   explicit margin. Without this they butt against the previous row's helper. */
/* Only fields OUTSIDE a grid need a margin. Applying it to any adjacent
   .form-field also hit grid cells, pushing every column after the first
   downward and breaking row alignment. */
.step-panel .form-section > .form-grid + .form-field,
.step-panel .form-section > .form-field + .form-field,
.step-panel .form-section > .form-grid + .addr-block,
.step-panel .form-section > .form-field + .form-grid { margin-top: 1.7rem; }
/* grid cells must never carry a stray top margin */
.step-panel .form-grid > .form-field { margin-top: 0; align-self: start; }

/* ---- cautionary note (originals reminder) ---------------------------- */
.doc-note {
  margin-top: 1.6rem; padding: 1rem 1.15rem;
  border: 1px solid var(--brass); border-left-width: 1px;
  border-radius: var(--radius); background: var(--brass-soft);
}
.doc-note-t {
  display: block; font-size: .84rem; font-weight: 700;
  color: var(--brass-ink); margin-bottom: .4rem;
}
.doc-note p { margin: 0; font-size: .84rem; line-height: 1.55; color: var(--t-on-paper); }

/* Photo is required (2026-08-12). The step-4 photo is the submitted passport-size
   photo, so a missing one has to be as visible as any other required field. */
.cv-photo-ctl.err .file-drop { border-color: #b3402a; background: #fdf3f1; }
.cv-photo-ctl.err .fd-main { color: #b3402a; }

/* Guidance under the passport upload. Sits outside .file-drop so clicking it
   does not re-open the file picker mid-read. */
.fd-note {
  margin-top: .7rem; font-size: .82rem; line-height: 1.55;
  color: var(--t-on-paper-mut); max-width: 62ch;
}
.fd-note strong { color: var(--t-on-paper); font-weight: 700; }


/* Date of birth: three selects instead of a native date input.
   The native picker opened on the MAX allowed date (twenty years ago) while the
   field still displayed the current year, and reaching a birth year meant paging
   back through decades one month at a time. Three selects remove the navigation
   entirely, and because the year list only contains the recruitable band, an
   out-of-range birth date cannot be chosen at all rather than being rejected
   after the fact. */
.dob-row { display: grid; grid-template-columns: 1fr 1.4fr 1fr; gap: .5rem; }
.dob-row select { width: 100%; min-width: 0; }
@media (max-width: 420px) { .dob-row { grid-template-columns: 1fr 1fr; } .dob-row select:last-child { grid-column: 1 / -1; } }


/* Step heading: the eyebrow alone told you which number you were on but not what
   the step was for. A name plus one line of contents sets expectations before the
   candidate starts filling, which is what makes a long form feel finishable. */
.step-title {
  font-family: var(--display); font-size: 1.5rem; line-height: 1.2;
  color: var(--ink); margin: .35rem 0 .2rem; font-weight: 600;
}
.step-sub { margin: 0 0 1.4rem; color: var(--t-on-paper-mut); font-size: .97rem; }
@media (max-width: 600px) { .step-title { font-size: 1.3rem; } }

/* Current eligibility notice. A candidate who is over the work-permit ceiling should
   learn it BEFORE filling five steps, not from a validation error at the end, so it
   sits at the top of step 1. Amber rather than red: they are not doing anything
   wrong, and the roles being processed can change. */
.elig-note {
  display: flex; gap: .75rem; align-items: flex-start;
  margin: 0 0 1.5rem; padding: .95rem 1.1rem;
  background: #fdf6e8; border: 1px solid #e8d5a8; border-radius: var(--radius);
}
.elig-note svg { width: 20px; height: 20px; flex: none; color: var(--brass-ink); margin-top: .1rem; }
.elig-note b { display: block; color: var(--ink); font-size: .9rem; margin-bottom: .3rem; }
.elig-note p { margin: 0 0 .4rem; font-size: .85rem; line-height: 1.6; color: var(--t-on-paper-mut); }
.elig-note p:last-child { margin-bottom: 0; }
.elig-note p b { display: inline; color: var(--ink); }
/* The WhatsApp route out of the age notice has to be findable — a link that reads as
   body text is a dead end for the 42-44 candidate it exists for. */
.elig-note a { color: var(--brass-ink); text-decoration: underline; text-underline-offset: 2px; font-weight: 700; }
.elig-note a:hover { color: var(--ink); }
/* The 42-44 route is the one actionable thing in this box for the people it applies to,
   so it is separated by a rule and set in the same weight as the heading rather than
   trailing off as a third body paragraph. */
.elig-note .elig-alt {
  margin-top: .9rem; padding-top: .9rem;
  border-top: 1px solid rgba(138, 93, 14, .22);
  font-weight: 600; color: var(--ink);
}

/* Error summary: a NAMED list of what is missing, grouped by step.
   The old summary said only "Please fix the 31 highlighted fields", and on a
   five-step form the offending field is usually on a step the candidate cannot
   see — so they re-checked the step in front of them, found nothing, and gave up.
   Every entry here is a button that opens its step and focuses the field. */
.form-error-summary .es-step { margin-top: .7rem; }
.form-error-summary .es-step-h {
  display: block; font-size: .78rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--brass-ink); margin-bottom: .25rem;
}
.form-error-summary ul { margin: 0; padding-left: 1.05rem; }
.form-error-summary li { margin: .12rem 0; }
.form-error-summary .es-jump {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: #b3402a; text-decoration: underline; text-underline-offset: 2px; text-align: left;
}
.form-error-summary .es-jump:hover { color: var(--ink); }
.form-error-summary .es-note { margin: .7rem 0 0; font-size: .86rem; }

/* The CV intro is instructions, not a caption. Centred it read as decorative and the
   photo rules inside it were being skimmed past; left-aligned at a readable measure
   it reads as something to follow. */
/* Specificity note: `.step-panel > .form-section > .hint` centres every step intro at
   (0,3,0), so a lone .cv-intro at (0,1,0) never took effect. Match that scope, and
   leave the other steps centred. */
/* Full section width, single column. A ch-based cap stopped the text at roughly
   half the section on desktop, leaving the right half empty — which read as a
   two-column layout rather than as one paragraph. It now runs the same width as
   the form fields below it. */
.step-panel > .form-section > .hint.cv-intro { text-align: left; max-width: none; margin-inline: 0; }

/* ── Submission-failure modal (2026-08-18) ────────────────────────────────────
   Candidates were shown one sentence for every kind of failure and had no way
   to tell whether their application had been saved. This dialog names the
   cause, says whether the application exists, and gives the next step. */
.apply-err-modal {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem; overflow-y: auto;
  background: rgba(13, 27, 42, .6);
  animation: apply-err-fade .16s ease-out;
}
.apply-err-card {
  width: 100%; max-width: 480px; margin: auto;
  background: var(--white); color: var(--t-on-paper);
  border-radius: 16px; padding: 1.6rem 1.5rem 1.35rem;
  box-shadow: 0 24px 60px rgba(13, 27, 42, .3);
  animation: apply-err-rise .2s cubic-bezier(.22, 1, .36, 1);
}
.apply-err-icon {
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  display: grid; place-items: center; margin-bottom: .9rem;
  background: #fdecea; color: #96201a; font-size: 1.4rem; font-weight: 700; line-height: 1;
}
.apply-err-card h3 { margin: 0 0 .5rem; font-family: var(--display); font-size: 1.25rem; line-height: 1.25; }
.apply-err-what { margin: 0 0 .8rem; line-height: 1.6; }
.apply-err-saved,
.apply-err-kept {
  margin: 0 0 1rem; padding: .7rem .85rem; border-radius: 10px;
  font-size: .93rem; line-height: 1.55;
}
.apply-err-saved { background: #eaf6e6; color: var(--green-deep); font-weight: 600; }
.apply-err-kept  { background: var(--paper-2); color: var(--t-on-paper-mut); }
.apply-err-lead {
  margin: 0 0 .4rem; font-size: .78rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--brass-ink); font-weight: 700;
}
.apply-err-steps { margin: 0 0 1.2rem; padding-left: 1.15rem; }
.apply-err-steps li { margin-bottom: .35rem; line-height: 1.55; }
.apply-err-actions { display: grid; gap: .55rem; }
.apply-err-actions .btn { width: 100%; text-align: center; justify-content: center; }
.apply-err-actions .btn-wa { background: #25d366; color: #0b2e13; border: 0; font-weight: 700; }
.apply-err-actions .btn-ghost {
  background: transparent; color: var(--t-on-paper-mut);
  border: 1px solid rgba(13, 27, 42, .18);
}
.apply-err-code {
  margin: 1rem 0 0; text-align: center;
  font-size: .84rem; color: var(--t-on-paper-mut);
}
@keyframes apply-err-fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes apply-err-rise { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }
@media (prefers-reduced-motion: reduce) {
  .apply-err-modal, .apply-err-card { animation: none; }
}

/* Draft notice — shown only when typing was recovered after a reload. */
.draft-note {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  margin: 0 0 1.1rem; padding: .75rem .9rem;
  background: var(--paper-2); border-radius: 10px;
  font-size: .93rem; line-height: 1.5; color: var(--t-on-paper);
}
.draft-note button {
  font: inherit; font-weight: 600; cursor: pointer;
  padding: .35rem .8rem; border-radius: 8px;
  border: 1px solid rgba(13, 27, 42, .2); background: var(--white); color: var(--t-on-paper);
}
.draft-note button:hover { background: var(--paper); }
.draft-note #draftClear { border: 0; background: none; text-decoration: underline; color: var(--t-on-paper-mut); }

/* Upload progress on /apply — several documents, so it names the file too. */
.apply-progress { display: none; margin: 0 0 1rem; }
.apply-progress.show { display: block; }
.apply-progress-track {
  height: 8px; border-radius: 99px; overflow: hidden;
  background: rgba(13, 27, 42, .12);
}
.apply-progress-fill {
  height: 100%; width: 0; border-radius: 99px;
  background: var(--green); transition: width .18s linear;
}
.apply-progress-text {
  margin: .45rem 0 0; font-size: .9rem; color: var(--t-on-paper-mut);
}

/* Remove-file control, top-right inside the upload box. Only shown once a file
   is attached, so an empty box stays as plain as it was. */
.file-drop { position: relative; }
.file-drop .fd-clear { display: none; }
.file-drop.has-file .fd-clear {
  display: grid; place-items: center;
  position: absolute; top: .5rem; right: .5rem;
  width: 30px; height: 30px; padding: 0;
  font: inherit; font-size: 1.15rem; line-height: 1; cursor: pointer;
  color: var(--t-on-paper-mut);
  background: var(--white);
  border: 1px solid rgba(13, 27, 42, .18); border-radius: 50%;
}
.file-drop.has-file .fd-clear:hover { color: #96201a; border-color: #d8b4ae; background: #fdf3f1; }
.file-drop.has-file .fd-clear:focus-visible { outline: 2px solid var(--brass); outline-offset: 1px; }

/* ── Photo + signature, end of step 3 ─────────────────────────────────────────
   Both are things the candidate produces once, and both feed the CV on the next
   step, so they are asked for together instead of being buried in the preview.
   The photo box is shaped like the passport photograph it wants (35x45mm), which
   tells the candidate the crop before the file picker opens; the signature keeps
   the wide pad a signature actually needs. */
.ps-row {
  display: grid; grid-template-columns: 190px minmax(0, 1fr);
  gap: 1.3rem; align-items: start; margin-top: .7rem;
}
.ps-row .cv-photo-ctl { margin: 0; }
.ps-row #cvPhotoDrop {
  aspect-ratio: 35 / 45; width: 100%; margin: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 1rem .75rem; text-align: center;
}
.ps-row #cvPhotoDrop .fd-sub { line-height: 1.45; }
.ps-row .sig-ctl { margin: 0; }
.ps-row .sig-ctl #sigPad { height: 190px; }
.ps-field > .cv-adjust { margin-top: 1rem; }
@media (max-width: 640px) {
  .ps-row { grid-template-columns: 1fr; gap: 1.1rem; }
  .ps-row #cvPhotoDrop { max-width: 200px; }
}


/* The chosen photo, shown in the frame it will be cropped to. Painted by paint()
   with the same background-size/position as the CV, so what the candidate lines up
   here is exactly what prints. */
.file-drop .fd-photo {
  position: absolute; inset: 0; border-radius: inherit;
  background-repeat: no-repeat; background-position: 50% 50%;
  opacity: 0; pointer-events: none; transition: opacity .12s ease;
}
.file-drop.has-photo .fd-photo { opacity: 1; pointer-events: auto; cursor: grab; }
.file-drop.has-photo .fd-photo:active { cursor: grabbing; }
/* with a photo in it, the frame is the photo - the prompt would only obscure it */
.file-drop.has-photo > svg,
.file-drop.has-photo .fd-main,
.file-drop.has-photo .fd-sub { visibility: hidden; }
.photo-change { display: block; margin: .6rem auto 0; }
.photo-change[hidden] { display: none; }
.zoomrow .zoomlevel {
  min-width: 3.4rem; text-align: center; font-size: .84rem;
  font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums;
}
.zoomrow .zoomreset { margin-left: .4rem; }

/* ── Custom dropdown (see assets/js/select-dd.js for why the native one can't be
   styled). The native <select> stays in the DOM as the source of truth; it is
   moved off-screen rather than display:none so it still submits and so any code
   that measures it does not get zeroes. Everything below draws the replacement. */
.dd { position: relative; }
.dd .dd-native {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  border: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; }

.dd-btn {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  width: 100%; min-height: 48px; padding: .85rem 1rem; text-align: left;
  font: inherit; font-size: 1rem; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line-light);
  border-radius: var(--radius); cursor: pointer;
  transition: border-color .18s cubic-bezier(.22,1,.36,1), background-color .18s cubic-bezier(.22,1,.36,1); }
.dd-btn::after {
  content: ""; flex: none; width: 11px; height: 7px; margin-left: auto;
  background: var(--brass-ink);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transition: transform .18s cubic-bezier(.22,1,.36,1); }
.dd-btn:hover { border-color: rgba(13,27,42,.28); }
.dd-btn:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.dd.is-open .dd-btn { border-color: var(--brass); background: var(--white); }
.dd.is-open .dd-btn::after { transform: rotate(180deg); }
.dd-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-val.is-ph { color: var(--t-on-paper-mut); }

/* The panel is anchored to the field and pushes nothing around — it is a dropdown,
   not an overlay: no backdrop, no page lock, no centring. */
.dd-panel {
  position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; right: 0;
  max-height: 19rem; overflow: hidden auto; overscroll-behavior: contain;
  background: var(--white); border: 1px solid var(--line-light);
  border-radius: var(--radius);
  box-shadow: 0 24px 48px -20px rgba(13,27,42,.32), 0 2px 6px rgba(13,27,42,.06); }
.dd.dd-up .dd-panel { top: auto; bottom: calc(100% + 6px); }
@media (prefers-reduced-motion: no-preference) {
  .dd.is-open .dd-panel { animation: dd-in .16s cubic-bezier(.22,1,.36,1); }
  @keyframes dd-in { from { opacity: 0; transform: translateY(-4px); } }
}

.dd-search { position: sticky; top: 0; z-index: 1; padding: .5rem; background: var(--white);
  border-bottom: 1px solid var(--line-light); }
.dd-search input {
  width: 100%; min-height: 38px; padding: .45rem .65rem; font: inherit; font-size: .9rem;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--line-light); border-radius: var(--radius); }
.dd-search input:focus { outline: none; border-color: var(--brass); background: var(--white); }

.dd-list { padding: .3rem 0; }
.dd-group + .dd-group { border-top: 1px solid rgba(13,27,42,.07); margin-top: .3rem; padding-top: .3rem; }
.dd-group-l {
  display: block; padding: .5rem 1rem .3rem; font-family: var(--body);
  font-size: .68rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--brass-ink); }
.dd-opt {
  position: relative; padding: .6rem 1rem .6rem 2.2rem; font-size: .95rem;
  color: var(--t-on-paper); cursor: pointer; scroll-margin: .5rem; }
.dd-opt.is-on { background: var(--paper-2); }
/* the current choice is marked with a tick, not a coloured left stripe: the stripe
   is a banned pattern, and a tick is what the OS menu it replaces already used */
.dd-opt[aria-selected="true"] { font-weight: 700; color: var(--ink); }
.dd-opt[aria-selected="true"]::before {
  content: ""; position: absolute; left: 1rem; top: 50%;
  width: 6px; height: 10px; margin-top: -6px;
  border: solid var(--green-deep); border-width: 0 2px 2px 0;
  transform: rotate(42deg); }
.dd-opt[aria-disabled="true"] { opacity: .45; cursor: default; }
.dd-empty { margin: 0; padding: .9rem 1rem; font-size: .88rem; color: var(--t-on-paper-mut); }

/* validity states have to reach the trigger, since the real select is off-screen */
.form-field.err .dd-btn { border-color: #b3402a; background: #fdf6f4; }
.form-field.ok .dd-btn { border-color: rgba(53,122,31,.5); }

/* The passport block disappears when the candidate says their passport is still in
   process, and this note takes its place. It is a caution, not an error: applying
   later is the right outcome, not a failure. */
.pp-wait {
  margin: .5rem 0 0; padding: .6rem .75rem;
  border: 1px solid rgba(217,155,35,.45); border-radius: var(--radius);
  background: rgba(217,155,35,.09);
  font-size: .8rem; line-height: 1.5; color: var(--t-on-paper); }
.pp-wait a { color: var(--brass-ink); font-weight: 700; }
.pp-wait[hidden] { display: none !important; }

/* Wrong file type, answered where it happened. A caution, not an error: attaching a
   photo of your certificate is a reasonable thing to try, and for JPG and PNG the
   answer is a button rather than a refusal. */
.pack-wrong {
  margin: .6rem 0 0; padding: .8rem .9rem;
  border: 1px solid rgba(217,155,35,.5); border-radius: var(--radius);
  background: rgba(217,155,35,.09); }
.pack-wrong[hidden] { display: none !important; }
.pw-lead { margin: 0; font-size: .88rem; font-weight: 700; color: var(--t-on-paper); }
.pw-body { margin: .35rem 0 0; font-size: .82rem; line-height: 1.55; color: var(--t-on-paper); }
.pw-body a { color: var(--brass-ink); font-weight: 700; }
.pw-go { margin-top: .7rem; }
/* the combine tool briefly marks itself when files are handed to it, so the eye
   follows the files instead of hunting for where they went */
@media (prefers-reduced-motion: no-preference) {
  .pdf-merge.is-flash { animation: pm-flash 1.4s cubic-bezier(.22,1,.36,1); }
  @keyframes pm-flash {
    0%, 100% { box-shadow: 0 0 0 0 rgba(217,155,35,0); }
    18%      { box-shadow: 0 0 0 4px rgba(217,155,35,.35); }
  }
}

/* ---- Europass language proficiency (lang-skills.js), on /apply/ and /cv-maker/ ------
   One block per language, five skills each. The selects are native on purpose (see
   lang-skills.js), so they are styled here rather than by select-dd. Five across on a
   desktop, three on a tablet, two on a phone: a 150px select still shows "B1 Independent". */
.lang-skills { grid-column: 1 / -1; display: grid; gap: .9rem; }
.lang-skills[hidden] { display: none; }
.lang-skills .lang-block { padding: .95rem 1rem 1rem; border: 1px solid var(--line-light);
  border-radius: var(--radius); background: var(--white); margin: 0; }
.lang-skills .lang-block.err { border-color: #b3402a; background: #fdf6f4; }
.lang-skills .lang-block .lang-name { display: block; font-size: .92rem; font-weight: 600;
  color: var(--ink); margin-bottom: .6rem; }
.lang-skills .lang-block .lang-name .lang-what { font-weight: 400; color: var(--t-on-paper-mut); }
.lang-top { display: flex; gap: .6rem; align-items: center; margin-bottom: .75rem; }
.lang-top .lang-all { flex: 1 1 14rem; max-width: 23rem; }
.lang-x { flex: none; min-height: 44px; padding: .55rem .9rem; border: 1px solid var(--line-light);
  border-radius: var(--radius); background: transparent; font: inherit; font-size: .82rem;
  font-weight: 600; color: var(--brass-ink); cursor: pointer; }
.lang-x:hover { border-color: var(--brass); }
.lang-x:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.lang-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .6rem; }
.lang-skills .lang-block .lang-cell { display: block; margin: 0; }
.lang-skills .lang-block .lang-cell > span { display: block; font-size: .74rem; font-weight: 600;
  color: var(--t-on-paper-mut); margin-bottom: .3rem; letter-spacing: .01em; }
.lang-skills .lang-block select { width: 100%; min-width: 0; min-height: 44px;
  padding: .6rem 2rem .6rem .75rem; border: 1px solid var(--line-light);
  border-radius: var(--radius); font: inherit; font-size: .93rem; color: var(--ink);
  background-color: var(--paper); appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%238a5d0e' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .7rem center; }
.lang-skills .lang-block select:focus { outline: none; border-color: var(--brass);
  background-color: var(--white); }
.lang-skills .lang-block.err select { border-color: #b3402a; }
.lang-skills .lang-block .err-msg { display: none; color: #b3402a; font-size: .78rem;
  font-weight: 600; margin-top: .6rem; }
.lang-skills .lang-block.err .err-msg { display: block; }
.lang-intro .hint b { color: var(--ink); font-weight: 600; }
.lang-add { display: flex; gap: .6rem; margin-top: .85rem; }
.lang-add input { flex: 1 1 auto; min-width: 0; }
.lang-add .btn { flex: none; }
/* Below 900px, and always in the CV maker's narrower form column, five across would cut
   "B1 Independent" short and two across leaves the fifth skill alone on a row. One skill
   per row instead: the name on the left, its level on the right. */
.cvb-form .lang-grid { grid-template-columns: 1fr; gap: .5rem; }
.cvb-form .lang-skills .lang-block .lang-cell { display: grid; align-items: center; gap: .6rem;
  grid-template-columns: 7.8rem minmax(0, 16rem); }
.cvb-form .lang-skills .lang-block .lang-cell > span { margin: 0; font-size: .84rem; color: var(--ink); }
@media (max-width: 900px) {
  .lang-grid { grid-template-columns: 1fr; gap: .5rem; }
  .lang-skills .lang-block .lang-cell { display: grid; align-items: center; gap: .6rem;
    grid-template-columns: 7.8rem minmax(0, 16rem); }
  .lang-skills .lang-block .lang-cell > span { margin: 0; font-size: .84rem; color: var(--ink); }
}
@media (max-width: 520px) {
  .lang-skills .lang-block { padding: .85rem .8rem .9rem; }
  .lang-skills .lang-block select[data-skill] { padding-left: .65rem; padding-right: 1.8rem; font-size: .9rem; }
  /* the two long skill names wrap inside their own column, so the level keeps its room */
  .lang-skills .lang-block .lang-cell { grid-template-columns: 5.6rem minmax(0, 1fr); }
  .lang-skills .lang-block .lang-cell > span { font-size: .8rem; line-height: 1.3; }
  .lang-top .lang-all { flex: 1 1 auto; min-width: 0; max-width: none; }
}

/* Work experience and education run the full width of the sheet, under the two columns
   (Abhi, 2026-10-03). In the right-hand column a long job line wrapped three or four times
   and pushed the sheet to a second page while the left rail stood empty. */
.cv-wide { padding: 3mm 12mm 1mm; }
.cv-wide section { margin-bottom: 7.5mm; }
.cv-left ul[hidden], .cv-left p[hidden] { display: none; }
@media print { .cv-wide section { break-inside: auto; page-break-inside: auto; } }

/* The same levels on the CV sheet: a full-width band above the declaration, because the
   personal-details value column is too narrow for six columns. */
.cv-langs { padding: 0 12mm 1mm; }
.cv-langs[hidden] { display: none; }
.cv-lang-t { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 9.2pt; color: #1f2933; }
.cv-lang-t th:first-child { width: 21%; }
.cv-lang-t th, .cv-lang-t td { padding: 1.5mm 2mm 1.5mm 0; text-align: left; vertical-align: top;
  border-bottom: .2mm solid #dfe4e9; }
.cv-lang-t thead th { font-size: 8pt; font-weight: 600; color: #6b7681; letter-spacing: .02em;
  border-bottom-color: #c2cad2; }
.cv-lang-t tbody th { font-weight: 700; }
.cv-lang-t td { font-variant-numeric: tabular-nums; }
.cv-lang-note { margin: 2mm 0 0; font-size: 7.6pt; line-height: 1.5; color: #6b7681; }
@media print { .cv-langs { break-inside: avoid; page-break-inside: avoid; } }
@media (max-width: 380px) {
  .lang-skills .lang-block select[data-skill] { font-size: .85rem; padding-right: 1.6rem;
    background-position: right .55rem center; }
}
@media (max-width: 340px) {
  .lang-skills .lang-block .lang-cell { grid-template-columns: 1fr; gap: .25rem; }
}
