/* =====================================================================
   RHDC Recruitment Management System — public portal theme
   Identity: Rangamati hill country + Bangladesh national palette.
   Signature: layered hill-ridge dividers echoing the council emblem.
   ===================================================================== */

/* ---------------------------------------------------------------------
   Self-hosted typography (works fully offline — no Google Fonts).
   English (Latin)  -> Inter        : clean, professional, high legibility.
   Bangla (বাংলা)   -> SolaimanLipi  : the standard Bangla government font.
   The unicode-range on each face makes the browser pick the right font
   per-character automatically, so mixed Bangla/English lines render each
   script in its correct font with no manual class switching.
   --------------------------------------------------------------------- */

/* --- Inter (English / Latin) --- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-latin-400-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/inter-latin-500-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-latin-600-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-latin-700-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/inter-latin-800-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --- SolaimanLipi (Bangla) — restricted to the Bengali script block --- */
@font-face {
  font-family: "SolaimanLipi";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/solaimanlipi-normal-v1.0.woff2") format("woff2"),
       url("../fonts/solaimanlipi-normal-v1.0.ttf") format("truetype");
  unicode-range: U+0964-0965, U+0980-09FF, U+200C-200D, U+20B9, U+2013-2014, U+25CC;
}
@font-face {
  font-family: "SolaimanLipi";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/solaimanlipi-bold-v1.0.woff2") format("woff2"),
       url("../fonts/solaimanlipi-bold-v1.0.ttf") format("truetype");
  unicode-range: U+0964-0965, U+0980-09FF, U+200C-200D, U+20B9, U+2013-2014, U+25CC;
}

:root {
  --green-900: #06382b;
  --green-800: #0a4a39;
  --green-700: #006a4e;   /* Bangladesh flag green */
  --green-100: #e2efe9;
  --green-050: #f2f7f4;
  --red-600:  #f42a41;    /* Bangladesh flag red — used sparingly */
  --red-700:  #d21f34;
  --paper:    #fbfcfa;
  --ink:      #14231d;
  --ink-soft: #47564f;
  --line:     #d8e2dc;
  --gold:     #c9a227;
  --radius:   .55rem;
  --shadow:   0 6px 24px rgba(6, 56, 43, .10);
  /* Latin runs use Inter; Bangla runs fall through to SolaimanLipi via unicode-range. */
  --font-display: "Inter", "SolaimanLipi", system-ui, "Segoe UI", sans-serif;
  --font-body:    "Inter", "SolaimanLipi", system-ui, "Segoe UI", sans-serif;
  --font-bangla:  "SolaimanLipi", "Inter", system-ui, sans-serif;
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

html { height: 100%; }
body {
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  /* Sticky footer: fill at least the full viewport so the footer never
     floats up leaving a blank gap on short pages — on every device. */
  min-height: 100vh;
  min-height: 100dvh;        /* accounts for mobile browser toolbars */
  display: flex;
  flex-direction: column;
}
/* main content grows to absorb leftover height; header & footer stay put */
#content { flex: 1 0 auto; }
body > *:not(#content) { flex-shrink: 0; }
h1, h2, h3, h4, h5, .display-font { font-family: var(--font-display); font-weight: 700; }

a { color: var(--green-700); }
a:hover { color: var(--green-900); }

/* ------------------------------------------------ government masthead */
.govt-strip {
  background: var(--green-900);
  color: #cfe6dc;
  font-size: .8rem;
  letter-spacing: .02em;
}
.govt-strip a { color: #eaf5f0; text-decoration: none; }
.govt-strip a:hover { color: #fff; text-decoration: underline; }

/* language switcher (bn / en) */
.lang-switch form { margin: 0; }
.lang-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: #eaf5f0; font: inherit; line-height: 1;
}
.lang-link:hover { color: #fff; text-decoration: underline; }
.lang-link.active { color: #fff; font-weight: 700; text-decoration: underline; }

.masthead { background: #fff; border-bottom: 1px solid var(--line); }
.masthead .org-bng { font-family: var(--font-display); font-size: 1.45rem; font-weight: 700; color: var(--green-800); line-height: 1.2; }
.masthead .org-eng { font-size: .95rem; color: var(--ink-soft); font-weight: 600; letter-spacing: .01em; }
.masthead .govt-line { font-size: .78rem; color: var(--red-700); font-weight: 600; text-transform: uppercase; letter-spacing: .08em; }
.masthead img.logo {
  height: 66px; width: auto; max-width: 84px;
  object-fit: contain;              /* fit whole logo, never crop or stretch */
  display: block;
}

/* ------------------------------------------------ navigation */
.navbar-rms {
  background: linear-gradient(180deg, var(--green-700), var(--green-800));
  box-shadow: 0 2px 10px rgba(6,56,43,.25);
}
.navbar-rms .nav-link {
  color: #eaf5f0;
  font-weight: 600;
  font-size: .92rem;
  padding: .8rem 1rem;
  border-bottom: 3px solid transparent;
}
.navbar-rms .nav-link:hover,
.navbar-rms .nav-link:focus-visible { color: #fff; background: rgba(255,255,255,.08); }
.navbar-rms .nav-link.active { border-bottom-color: var(--red-600); color: #fff; }
.navbar-rms .dropdown-menu { border-radius: 0 0 var(--radius) var(--radius); border: 1px solid var(--line); }

/* ------------------------------------------------ hill-ridge signature */
.ridge { display: block; width: 100%; height: 46px; }
.hero {
  position: relative;
  color: #fff;
  background:
    radial-gradient(1200px 380px at 85% -60px, rgba(244,42,65,.28), transparent 60%),
    linear-gradient(160deg, var(--green-800) 0%, var(--green-700) 55%, #0d7a5c 100%);
  overflow: hidden;
}
.hero::after { /* faint concentric sun echoing the emblem */
  content: "";
  position: absolute; right: -90px; top: -90px;
  width: 340px; height: 340px; border-radius: 50%;
  border: 26px solid rgba(255,255,255,.05);
  box-shadow: 0 0 0 42px rgba(255,255,255,.04), 0 0 0 90px rgba(255,255,255,.025);
  pointer-events: none;
}
.hero h1 { font-size: clamp(1.6rem, 3.4vw, 2.6rem); }
.hero .lead { color: #d9ece4; max-width: 46rem; }

/* quick service tiles */
.service-tile {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.15rem 1rem;
  text-align: center;
  text-decoration: none;
  color: var(--ink);
  display: block;
  height: 100%;
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.service-tile:hover, .service-tile:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: var(--green-700);
  color: var(--ink);
}
.service-tile .icon {
  width: 52px; height: 52px; margin: 0 auto .6rem;
  display: grid; place-items: center;
  background: var(--green-050); color: var(--green-700);
  border-radius: 50%; font-size: 1.4rem;
}
.service-tile strong { display: block; font-family: var(--font-display); }
.service-tile small { color: var(--ink-soft); }

/* ------------------------------------------------ cards & sections */
.section-title {
  font-family: var(--font-display);
  color: var(--green-800);
  position: relative;
  padding-left: .9rem;
}
.section-title::before {
  content: "";
  position: absolute; left: 0; top: .18em; bottom: .18em;
  width: 5px; border-radius: 3px;
  background: linear-gradient(var(--red-600), var(--green-700));
}
.card-rms { border: 1px solid var(--line); border-radius: var(--radius); background: #fff; }
.card-rms .card-header { background: var(--green-050); border-bottom: 1px solid var(--line); font-weight: 700; color: var(--green-800); }

.circular-card { border-left: 4px solid var(--green-700); }
.circular-card.closed { border-left-color: #9aa7a1; opacity: .85; }
.deadline-chip { background: #fdeef0; color: var(--red-700); font-weight: 700; border-radius: 999px; padding: .15rem .7rem; font-size: .8rem; }
.open-chip { background: var(--green-100); color: var(--green-800); font-weight: 700; border-radius: 999px; padding: .15rem .7rem; font-size: .8rem; }

.stat-band { background: var(--green-050); border-block: 1px solid var(--line); }
.stat-value { font-family: var(--font-display); font-size: 2rem; font-weight: 800; color: var(--green-800); }
.stat-label { color: var(--ink-soft); font-size: .85rem; }

/* notice list */
.notice-item { display: flex; gap: .8rem; padding: .7rem 0; border-bottom: 1px dashed var(--line); text-decoration: none; color: var(--ink); }
.notice-item:last-child { border-bottom: 0; }
.notice-item:hover .title { color: var(--green-700); text-decoration: underline; }
.notice-date {
  min-width: 54px; text-align: center; background: var(--green-050);
  border: 1px solid var(--line); border-radius: .4rem; padding: .25rem;
  font-family: var(--font-display); line-height: 1.1;
}
.notice-date b { display: block; color: var(--red-700); font-size: 1.1rem; }
.notice-date span { font-size: .68rem; text-transform: uppercase; color: var(--ink-soft); }

/* ------------------------------------------------ buttons */
.btn-rms { background: var(--green-700); border-color: var(--green-700); color: #fff; font-weight: 700; }
.btn-rms:hover, .btn-rms:focus { background: var(--green-800); border-color: var(--green-800); color: #fff; }
.btn-rms-outline { border: 2px solid var(--green-700); color: var(--green-700); font-weight: 700; background: #fff; }
.btn-rms-outline:hover { background: var(--green-700); color: #fff; }
.btn-accent { background: var(--red-600); border-color: var(--red-600); color: #fff; font-weight: 700; }
.btn-accent:hover { background: var(--red-700); border-color: var(--red-700); color: #fff; }

/* ------------------------------------------------ forms & wizard */
.form-label { font-weight: 600; color: var(--ink); }
.form-label .req { color: var(--red-600); }
.form-control:focus, .form-select:focus {
  border-color: var(--green-700);
  box-shadow: 0 0 0 .2rem rgba(0,106,78,.15);
}
.wizard-steps { display: flex; flex-wrap: wrap; gap: .4rem; counter-reset: step; margin-bottom: 1.2rem; }
.wizard-step {
  counter-increment: step;
  flex: 1 1 120px;
  background: #fff; border: 1px solid var(--line); border-radius: .4rem;
  padding: .45rem .6rem .45rem 2.2rem; position: relative;
  font-size: .8rem; font-weight: 600; color: var(--ink-soft);
}
.wizard-step::before {
  content: counter(step);
  position: absolute; left: .5rem; top: 50%; transform: translateY(-50%);
  width: 1.35rem; height: 1.35rem; border-radius: 50%;
  display: grid; place-items: center; font-size: .72rem;
  background: var(--green-050); color: var(--green-700); border: 1px solid var(--line);
}
.wizard-step.active { border-color: var(--green-700); color: var(--green-800); background: var(--green-050); }
.wizard-step.active::before { background: var(--green-700); color: #fff; }

.rows { counter-reset: repeatRow; }
.repeat-row {
  counter-increment: repeatRow;
  background: #fff;
  border: 1px solid var(--line);
  border-left: 3px solid var(--green-700);
  border-radius: var(--radius);
  padding: 1.05rem 1rem .9rem 2.5rem;
  margin-bottom: .85rem;
  position: relative;
  transition: box-shadow .15s ease, border-color .15s ease;
}
.repeat-row:hover { box-shadow: 0 3px 12px rgba(11,61,46,.08); border-left-color: var(--green-800); }
.repeat-row::before {
  content: counter(repeatRow);
  position: absolute; top: 1rem; left: .65rem;
  width: 1.4rem; height: 1.4rem; border-radius: 50%;
  background: var(--green-700); color: #fff;
  font-size: .72rem; font-weight: 700; line-height: 1.4rem; text-align: center;
}
.repeat-row .remove-row {
  position: absolute; top: .5rem; right: .5rem;
  border-radius: 50%; width: 1.7rem; height: 1.7rem; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
}
.repeat-row .form-label { font-size: .78rem; font-weight: 600; color: var(--green-800); margin-bottom: .2rem; }
[data-repeat] .add-row { margin-top: .2rem; }

/* ------------------------------------------------ bilingual field labels
   Primary language on the baseline, the other language as a muted hint that
   wraps to its own line in narrow (repeatable) columns instead of colliding
   with the placeholder. Keeps English + বাংলা readable side by side. */
.field-label { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: .4rem; row-gap: 0; margin-bottom: .3rem; }
.field-label .lbl-main { font-weight: 600; color: var(--ink); }
.field-label .lbl-alt {
  font-weight: 400; font-size: .82em; color: var(--ink-soft);
}
.field-label .lbl-alt::before { content: "·"; margin-right: .4rem; color: var(--green-700); opacity: .55; }
.field-label .req { color: var(--red-600); margin-left: .05rem; font-weight: 700; }
/* inside a compact repeat row the hint drops below the main label */
.repeat-row .field-label { row-gap: .05rem; margin-bottom: .25rem; }
.repeat-row .field-label .lbl-main { color: var(--green-800); font-size: .82rem; }
.repeat-row .field-label .lbl-alt { flex-basis: 100%; font-size: .72rem; line-height: 1.15; }
.repeat-row .field-label .lbl-alt::before { content: none; }

/* One straight line of inputs across a repeat row.
   The hint takes a whole line of its own here, so anything after it in source
   order — the required asterisk — was landing on a *third* line and pushing that
   one input below its neighbours. Ordering keeps the asterisk with the label it
   marks, and letting the label box absorb the leftover height (its lines pinned
   to the bottom) keeps every input on the same baseline even when a label wraps. */
.repeat-row .row > [class*="col-"] { display: flex; flex-direction: column; }
.repeat-row .field-label { flex: 1 0 auto; align-content: flex-end; }
.repeat-row .field-label .req { order: 1; }
.repeat-row .field-label .lbl-alt { order: 2; }

/* placeholders: lighten so the bilingual hint text reads as guidance, not data.
   :lang() keeps the Bangla hint in SolaimanLipi even inside a Latin input. */
.form-control::placeholder, .form-select::placeholder { color: #9aa8a1; opacity: 1; font-weight: 400; }

/* ------------------------------------------------ application form polish
   Consistent, government-form-clean treatment applied to every section card. */
.card-rms .card-header {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .5rem;
  padding: .7rem 1rem; position: relative; letter-spacing: .005em;
}
.card-rms .card-header::before {                 /* slim flag-green accent rail */
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--green-700);
}
.card-rms .card-header .text-secondary,          /* the Bangla sub-title */
.card-rms .card-header .fw-normal { color: var(--ink-soft) !important; }
.card-rms .card-body { padding: 1.15rem 1rem 1.25rem; }

.form-control, .form-select {
  border-color: var(--line);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.form-control:hover:not(:disabled), .form-select:hover:not(:disabled) { border-color: #b9cbc2; }
.form-control:disabled, .form-select:disabled { background: var(--green-050); opacity: .8; }
.req { color: var(--red-600); }

/* ------------------------------------------------ cascading address block
   A level fetching its options reads as busy; a level still waiting on its
   parent is simply disabled and greyed by the rule above. */
.form-select.is-loading { cursor: progress; opacity: .7; }
[data-addr]:disabled { cursor: not-allowed; }
[data-addr="post_code"] { font-variant-numeric: tabular-nums; letter-spacing: .04em; }

/* ------------------------------------------------ government-form tables
   Particular 10 of docs/form.pdf is one Address table with a Present and a
   Permanent column. The web form reproduces it: ruled cells, a shaded label
   column, bilingual headers, and inputs that sit flush inside each cell. */
.govt-table {
  width: 100%;
  margin-bottom: .75rem;
  border: 1px solid var(--green-800);
  border-collapse: collapse;
  background: #fff;
}
.govt-table th, .govt-table td {
  border: 1px solid var(--line);
  padding: .4rem .5rem;
  vertical-align: middle;
}
.govt-table thead th {
  background: var(--green-050);
  color: var(--green-800);
  border-bottom: 1.5px solid var(--green-800);
  font-weight: 700;
  font-size: .88rem;
  text-align: center;
  vertical-align: top;
}
.govt-table thead th.col-label { text-align: left; }
.govt-table .alt {
  display: block;
  font-weight: 400;
  font-size: .78rem;
  color: var(--ink-soft);
  line-height: 1.3;
}
.govt-table tbody th.col-label {
  background: #fbfdfc;
  font-weight: 600;
  font-size: .84rem;
  color: var(--green-800);
  width: 22%;
  min-width: 9.5rem;
}
.govt-table tbody th.col-label label { margin: 0; cursor: pointer; display: block; }
/* the required star belongs beside the label, not orphaned on the next line */
.govt-table tbody th.col-label .lbl-main { display: inline; }
.govt-table tbody th.col-label .req { margin-left: .15rem; }
.govt-table .col-value { width: 39%; }
.govt-table .form-control, .govt-table .form-select {
  border-color: transparent;
  background-color: transparent;
  box-shadow: none;
  padding: .25rem .4rem;
  font-size: .9rem;
}
.govt-table .form-control:hover, .govt-table .form-select:hover:not(:disabled),
.govt-table .form-control:focus, .govt-table .form-select:focus {
  border-color: var(--green-700);
  background-color: #fff;
}
.govt-table .form-control:focus, .govt-table .form-select:focus {
  box-shadow: 0 0 0 .18rem rgba(11, 61, 46, .12);
}
.govt-table .form-text, .govt-table .invalid-feedback { font-size: .74rem; margin-top: .1rem; }

/* a level still waiting on its parent reads as unavailable */
.govt-table .form-select:disabled, .govt-table .form-control:disabled {
  background-color: #f6f8f7;
  color: #9aa8a1;
  opacity: 1;
}

/* the permanent column while "same as present" is ticked: visible, legible,
   and plainly not editable — this must win over the :disabled rule above */
.govt-table td.is-locked-cell { background: var(--green-050); }
.govt-table td.is-locked-cell .form-select:disabled,
.govt-table td.is-locked-cell .form-control:disabled,
.govt-table .is-locked {
  background-color: transparent;
  color: var(--ink);
  opacity: 1;
  cursor: default;
  border-color: transparent;
}
.govt-table .is-locked:hover { border-color: transparent; background-color: transparent; }

.address-table .perm-head { display: flex; flex-direction: column; gap: .3rem; align-items: center; }
.same-as-present { padding-left: 1.6rem; text-align: left; }
.same-as-present .form-check-input { margin-left: -1.6rem; margin-top: .18rem; }
.same-as-present .form-check-input:checked { background-color: var(--green-700); border-color: var(--green-700); }
.same-as-present .form-check-label { cursor: pointer; font-size: .8rem; font-weight: 600; color: var(--green-800); }
.same-as-present .form-check-label .alt { font-weight: 400; }

@media (max-width: 720px) {
  .govt-table tbody th.col-label { min-width: 7rem; font-size: .78rem; }
  .govt-table th, .govt-table td { padding: .3rem .35rem; }
}

/* ------------------------------------------------ photo & signature boxes
   A framed thumbnail beside its actions, sized to the aspect ratio the final PDF
   prints — what the applicant sees is exactly what the form will carry. */
.upload-box {
  display: flex; gap: .9rem; align-items: center;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: #fff; padding: .75rem .85rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.upload-box:hover { border-color: #b9cbc2; }
.upload-box:has(.upload-img:not([hidden])) { border-color: var(--green-700); background: #fcfefd; }
.upload-box.is-invalid-box { border-color: var(--red-600); background: #fffafa; }
.upload-thumb {
  flex: 0 0 auto; position: relative;
  display: grid; place-items: center;
  border: 1px dashed #c3d3cb; border-radius: 6px;
  background: var(--green-050);
  overflow: hidden;
}
.upload-box:has(.upload-img:not([hidden])) .upload-thumb { border-style: solid; border-color: var(--green-700); }
.upload-box[data-kind="photo"] .upload-thumb { width: 88px; height: 88px; }        /* 1:1, as printed */
.upload-box[data-kind="signature"] .upload-thumb { width: 132px; height: 44px; }   /* ~3:1 strip */
.upload-thumb .upload-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.upload-thumb .upload-empty { color: #a9b8b1; font-size: 1.5rem; line-height: 1; }

.upload-side { flex: 1 1 auto; min-width: 0; }
.upload-side .upload-input {
  /* the real input stays reachable for keyboard and no-JS users, while the
     styled buttons are what everyone else clicks */
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.upload-actions { display: flex; flex-wrap: wrap; gap: .35rem; }
.upload-actions [data-act="clear"] { line-height: 1; padding: .2rem .45rem; }
.upload-side .upload-meta {
  margin-top: .3rem; font-size: .75rem; line-height: 1.3; color: var(--ink-soft);
}
.upload-side .upload-error { font-size: .76rem; margin-top: .2rem; }
.upload-input:focus-visible ~ .upload-actions [data-act="pick"] { outline: 3px solid var(--gold); outline-offset: 2px; }

.doc-upload .upload-error { font-size: .76rem; }
.doc-upload .doc-current { margin-top: .3rem; }

@media (max-width: 420px) {
  .upload-box { flex-direction: column; align-items: flex-start; }
}

/* ------------------------------------------------ tables */
.table-rms thead { background: var(--green-800); color: #fff; }
.table-rms thead th { font-weight: 600; font-size: .85rem; border: 0; }
.table-rms tbody tr:hover { background: var(--green-050); }

/* status pills */
.status-pill { border-radius: 999px; padding: .2rem .75rem; font-size: .78rem; font-weight: 700; color: #fff; display: inline-block; }

/* ------------------------------------------------ footer */
.footer {
  background: var(--green-900);
  color: #bcd9cd;
}
.footer h6 { color: #fff; font-family: var(--font-display); letter-spacing: .04em; }
.footer a { color: #cfe6dc; text-decoration: none; display: block; padding: .18rem 0; font-size: .9rem; }
.footer a:hover { color: #fff; text-decoration: underline; }
.footer-bottom { background: #042920; color: #8fb8a8; font-size: .82rem; }

/* embedded PDF viewer (PDF.js) — govt-style scrollable document box */
.pdf-viewer {
  position: relative;
  width: 100%;
  height: 80vh;
  min-height: 520px;
  overflow: auto;                 /* scroll through pages */
  background: #525659;            /* classic PDF reader grey */
  padding: 16px 0;
  -webkit-overflow-scrolling: touch;
}
.pdf-viewer .pdf-pages { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.pdf-viewer canvas.pdf-page {
  max-width: 96%;
  height: auto;
  background: #fff;
  box-shadow: 0 4px 16px rgba(0,0,0,.35);
  border-radius: 2px;
}
.pdf-viewer .pdf-frame { width: 100%; height: 100%; border: 0; display: block; background: #fff; }
.pdf-viewer .pdf-status {
  position: absolute; inset: 0; margin: auto; height: fit-content; width: fit-content;
  color: #e7edea; font-size: .95rem; display: flex; align-items: center; gap: .6rem;
}
.pdf-viewer .pdf-status .spinner {
  width: 18px; height: 18px; border: 3px solid rgba(255,255,255,.35);
  border-top-color: #fff; border-radius: 50%; display: inline-block;
  animation: pdfspin .8s linear infinite;
}
@keyframes pdfspin { to { transform: rotate(360deg); } }

/* always-visible actions under the viewer, so the file is never inaccessible */
.pdf-actions {
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  padding: .7rem .9rem; border-top: 1px solid var(--line);
  background: #fff; border-radius: 0 0 var(--radius) var(--radius);
}
.pdf-actions span { margin-right: auto; }
@media (max-width: 576px) {
  .pdf-viewer { height: 70vh; min-height: 380px; }
  .pdf-viewer canvas.pdf-page { max-width: 99%; }
}

/* admit / applicant copy print sheet */
.print-sheet { background: #fff; border: 1px solid var(--line); max-width: 860px; margin: 0 auto; padding: 2rem; }
.print-sheet .sheet-head { border-bottom: 3px double var(--green-700); padding-bottom: 1rem; margin-bottom: 1rem; text-align: center; }
@media print {
  .no-print, .navbar-rms, .govt-strip, .footer, .footer-bottom, .masthead .btn { display: none !important; }
  .print-sheet { border: 0; padding: 0; }
}

/* focus visibility (accessibility floor) */
a:focus-visible, button:focus-visible, .form-control:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
}

/* mobile polish */
@media (max-width: 576px) {
  .masthead .org-bng { font-size: 1.1rem; }
  .masthead img.logo { height: 48px; width: auto; max-width: 60px; }
  .hero h1 { font-size: 1.45rem; }
  .stat-value { font-size: 1.5rem; }
}

/* ---------------------------------------------------------------------------
   Applicant dashboard (/my/) — one application per line.

   Colour carries the meaning here, and it says the same thing four times over so
   it survives a glance, a colour-blind eye and a phone screen: the left rail, the
   row's background wash, the solid payment chip, and the wording of the button.
   Colour is never the ONLY signal — every state also has its own icon and its own
   words, because red-vs-green alone fails roughly 1 in 12 men.

   Red   = fee not done / rejected -> the application is NOT complete
   Amber = fee submitted, awaiting the office
   Green = fee verified -> complete
   --------------------------------------------------------------------------- */
.app-summary { display: flex; flex-wrap: wrap; gap: .6rem; }
/* each tile is a filter button: clicking it narrows the list, instantly */
.app-summary__item {
  flex: 1 1 7rem; display: flex; flex-direction: column; gap: .05rem;
  padding: .55rem .8rem; border-radius: var(--radius);
  border: 1px solid var(--line); border-left: 4px solid var(--ink-soft);
  background: #fff; text-align: left; cursor: pointer;
  transition: box-shadow .15s ease, transform .12s ease, border-color .15s ease;
}
.app-summary__item:hover { box-shadow: var(--shadow); transform: translateY(-1px); }
.app-summary__item.is-active { box-shadow: inset 0 0 0 2px var(--green-700); }
.app-summary__item.is-ok     { border-left-color: var(--green-700); background: linear-gradient(90deg, var(--green-050), #fff 60%); }
.app-summary__item.is-due    { border-left-color: var(--red-600);   background: linear-gradient(90deg, #fdf0f2, #fff 60%); }
.app-summary__item.is-review { border-left-color: var(--gold);      background: linear-gradient(90deg, #fdf6e3, #fff 60%); }
.app-summary__n { font-size: 1.35rem; font-weight: 800; line-height: 1.15; color: var(--ink); }
.app-summary__k { font-size: .74rem; font-weight: 600; color: var(--ink-soft); }
.app-summary__item.is-ok     .app-summary__n { color: var(--green-700); }
.app-summary__item.is-due    .app-summary__n { color: var(--red-700); }
.app-summary__item.is-review .app-summary__n { color: #8a6d1f; }

.app-rows { display: grid; gap: .55rem; }

.app-row {
  display: flex; align-items: center; gap: .75rem;
  padding: .65rem .9rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  border-left: 5px solid var(--line);
  background: #fff;
  transition: box-shadow .16s ease, transform .16s ease;
  /* Rows are siblings, so a later one paints over an earlier one — which is exactly
     where the Download menu of row 1 used to disappear. `position: relative` gives the
     row a z-index to raise, and `focus-within` fires while the dropdown is open
     (its toggle holds focus), lifting the whole row above the rows below it.
     The hover `transform` also creates a stacking context, which trapped the menu
     inside the row; the raised z-index is what gets it back out on top. */
  position: relative;
  z-index: 0;
}
.app-row:hover        { box-shadow: var(--shadow); transform: translateY(-1px); z-index: 2; }
.app-row:focus-within { z-index: 30; }

/* Belt and braces: keep the menu above the page chrome, and never let it be clipped. */
.app-row .dropdown-menu { z-index: 1060; }
.app-row .dropdown-menu.show { display: block; }
.app-rows { overflow: visible; }

/* the wash fades out fast, so long rows stay readable and never look like a banner */
.app-row--unpaid, .app-row--rejected {
  border-left-color: var(--red-600);
  background: linear-gradient(90deg, #fdecee 0%, #fff 26%);
}
.app-row--paid {
  border-left-color: var(--green-700);
  background: linear-gradient(90deg, var(--green-100) 0%, #fff 26%);
}
.app-row--review {
  border-left-color: var(--gold);
  background: linear-gradient(90deg, #fdf6e3 0%, #fff 26%);
}

/* the only flexible cell: it absorbs the slack and truncates, so the row holds one line */
.app-row__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.app-row__post {
  font-weight: 700; font-size: 1rem; color: var(--green-800); line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.app-row__meta {
  font-size: .78rem; color: var(--ink-soft); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.app-row__meta .app-no { font-weight: 700; color: var(--ink); letter-spacing: .01em; }
.app-row__meta .sep    { opacity: .4; margin: 0 .3rem; }
.app-row__meta .fee {
  font-weight: 700; color: var(--green-800);
  background: var(--green-050); border: 1px solid #cfe3d8;
  padding: .05rem .4rem; border-radius: 999px;
}

/* solid, high-contrast chip — the loudest thing in the row, by design */
.pay-tag {
  flex: none; display: inline-flex; align-items: center; gap: .35rem;
  padding: .34rem .7rem; border-radius: 999px;
  font-size: .78rem; font-weight: 800; white-space: nowrap; cursor: help;
  color: #fff; border: 1px solid transparent;
}
.pay-tag--unpaid, .pay-tag--rejected { background: var(--red-600);   border-color: var(--red-700); }
.pay-tag--paid                       { background: var(--green-700); border-color: var(--green-800); }
.pay-tag--review                     { background: #b98d05; border-color: #9a7504; }

.app-row__status { flex: none; }
.app-row__act { flex: none; display: flex; align-items: center; gap: .35rem; }

.app-row__pay-btn { font-weight: 700; white-space: nowrap; border: 2px solid transparent; color: #fff; }
.app-row__pay-btn--unpaid, .app-row__pay-btn--rejected { background: var(--red-600); }
.app-row__pay-btn--unpaid:hover, .app-row__pay-btn--rejected:hover { background: var(--red-700); color: #fff; }
.app-row__pay-btn--review { background: #b98d05; }
.app-row__pay-btn--review:hover { background: #9a7504; color: #fff; }

/* the admit card before it is downloadable: present, obviously inert, and it says why
   on hover. A <span>, not a disabled <a> — a dead link that silently does nothing
   reads as a broken page. */
.btn-admit-dead {
  display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
  height: 30px; padding: 0 .6rem; border-radius: .3rem;
  font-size: .72rem; font-weight: 600; line-height: 1;
  background: #eef1ef; color: var(--ink-soft); border: 1px dashed #c3cec7;
  cursor: not-allowed; white-space: nowrap;
}
.btn-admit-dead:hover { background: #eef1ef; color: var(--ink-soft); }
.btn-admit-dead small { opacity: .8; }

.app-empty { text-align: center; padding: 3rem 1rem; color: var(--ink-soft); background: #fff; }
.app-empty .bi { font-size: 2.4rem; display: block; margin-bottom: .6rem; opacity: .55; }

/* ---- responsive -----------------------------------------------------------
   One line is a desktop promise. Rather than crush it into an unreadable strip of
   ellipses on a phone, the row degrades in two deliberate steps. */

/* Tablet: let the detail line wrap under the title; the row still holds. */
@media (max-width: 992px) {
  .app-row__meta { white-space: normal; }
}

/* Phone: stack. Payment state comes first after the title (it is the thing that
   blocks the applicant), then the buttons go full-width and thumb-sized. */
@media (max-width: 768px) {
  .app-row { flex-wrap: wrap; align-items: flex-start; row-gap: .55rem; padding: .75rem .85rem; }
  .app-row__main   { flex: 1 1 100%; }
  .pay-tag         { order: 1; }
  .app-row__status { order: 2; }
  .app-row__act    { order: 3; }
  /* NOTE: the toolbar's own sizing lives in the button block further down — one
     source of truth. It used to be stretched full-width here, which turned three
     small controls into three competing slabs and tripled the row's height. */
  /* the wash reads top-to-bottom once the row is stacked */
  .app-row--unpaid, .app-row--rejected { background: linear-gradient(180deg, #fdecee 0%, #fff 38%); }
  .app-row--paid   { background: linear-gradient(180deg, var(--green-100) 0%, #fff 38%); }
  .app-row--review { background: linear-gradient(180deg, #fdf6e3 0%, #fff 38%); }
}

@media (max-width: 420px) {
  .app-row__post { white-space: normal; }
}

/* Respect a reduced-motion preference — the lift is decoration, not information. */
@media (prefers-reduced-motion: reduce) {
  .app-row { transition: none; }
  .app-row:hover { transform: none; }
}

/* ---- the payment chip as a button ---------------------------------------- */
.pay-tag--btn {
  border: 1px solid transparent; cursor: pointer;
  box-shadow: 0 1px 2px rgba(6, 56, 43, .18);
  transition: filter .15s ease, transform .12s ease, box-shadow .15s ease;
}
.pay-tag--btn:hover  { filter: brightness(1.07); transform: translateY(-1px); box-shadow: 0 3px 8px rgba(6, 56, 43, .22); }
.pay-tag--btn:active { transform: translateY(0); }
.pay-tag__more { font-size: .82em; opacity: .75; margin-left: .1rem; }

.btn-admit-dead, .btn-admit-dead:hover { transform: none !important; box-shadow: none !important; }

/* ---- payment-details modal ------------------------------------------------ */
.pay-modal { border: 0; border-radius: .8rem; overflow: hidden; box-shadow: 0 24px 60px rgba(6, 56, 43, .32); }
.pay-modal .modal-header {
  background: var(--green-800); color: #fff; border-bottom: 0; padding: .8rem 1rem;
}
.pay-modal .modal-header .btn-close { filter: invert(1) grayscale(1) brightness(2); opacity: .85; }
.pay-modal .modal-title { font-size: 1rem; font-weight: 700; }
.pay-modal .modal-body { padding: 1rem; }
.pay-modal .modal-footer { border-top: 1px solid var(--line); background: var(--green-050); padding: .6rem 1rem; }

/* the state banner repeats the row's colour, so the modal is unmistakably about
   the row that opened it */
.pay-modal__state {
  display: flex; gap: .65rem; align-items: flex-start;
  padding: .7rem .8rem; border-radius: var(--radius); margin-bottom: .9rem;
}
.pay-modal__state .bi { font-size: 1.3rem; flex: none; }
.pay-modal__state strong { display: block; font-size: .95rem; font-weight: 800; }
.pay-modal__state small  { display: block; font-size: .82rem; line-height: 1.35; }
.pay-modal--paid     .pay-modal__state { background: var(--green-100); color: var(--green-800); }
.pay-modal--review   .pay-modal__state { background: #fdf6e3; color: #7a5c02; }
.pay-modal--rejected .pay-modal__state,
.pay-modal--unpaid   .pay-modal__state { background: #fdecee; color: var(--red-700); }

.pay-modal__grid {
  display: grid; grid-template-columns: minmax(7.5rem, 40%) 1fr;
  gap: .1rem .8rem; margin: 0;
}
.pay-modal__grid dt {
  font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  color: var(--ink-soft); padding: .4rem 0; border-top: 1px solid var(--line);
}
.pay-modal__grid dd {
  font-size: .9rem; font-weight: 600; color: var(--ink); margin: 0;
  padding: .4rem 0; border-top: 1px solid var(--line);
  word-break: break-word; display: flex; align-items: center; gap: .4rem;
}
.pay-modal__grid dt:first-of-type, .pay-modal__grid dd:first-of-type { border-top: 0; }
.pay-modal__grid code { background: var(--green-050); border: 1px solid #cfe3d8;
  padding: .1rem .4rem; border-radius: .3rem; color: var(--green-800); font-weight: 700; }
.pay-modal__grid .muted { color: var(--ink-soft); font-weight: 400; }
.pay-modal__logo { height: 20px; width: auto; border-radius: .2rem; }

@media (max-width: 480px) {
  .pay-modal__grid { grid-template-columns: 1fr; gap: 0; }
  .pay-modal__grid dd { border-top: 0; padding-top: 0; margin-bottom: .35rem; }
}

/* ---- one button system for the applicant screens ---------------------------
   Rectangular, compact, icon + small label — sized to sit quietly beside the payment
   chip rather than compete with it. Every button is the same shape and the same
   height; only COLOUR says what it does — green = go, red = you owe us, grey =
   neutral/leave. They stay on ONE line at every width: the labels are short and set
   nowrap, so three of them still fit across a 360px phone without stretching into
   slabs. Height holds at 30px (32px on touch), which is small but still a reliable
   tap target for a control this narrow. */
.btn-pay, .btn-pay-danger, .btn-ghost,
.app-row__act .btn, .app-row__pay-btn {
  --btn-fs: .72rem;
  display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
  font-size: var(--btn-fs); font-weight: 600; line-height: 1;
  padding: 0 .6rem; height: 30px; border-radius: .3rem;      /* rectangular */
  border: 1px solid transparent; white-space: nowrap; text-decoration: none;
  transition: background-color .15s ease, box-shadow .15s ease, transform .1s ease;
}
.btn-pay i, .btn-pay-danger i, .btn-ghost i,
.app-row__act .btn i, .app-row__pay-btn i { font-size: .95em; line-height: 1; }
/* Bootstrap's own .btn-sm would fight the height above — neutralise it */
.app-row__act .btn.btn-sm, .btn.btn-sm.btn-pay, .btn.btn-sm.btn-pay-danger,
.btn.btn-sm.btn-ghost { padding: 0 .6rem; font-size: var(--btn-fs); }
.app-row__act .dropdown-toggle::after { margin-left: .3rem; }

.btn-pay:hover, .btn-pay-danger:hover, .btn-ghost:hover,
.app-row__act .btn:hover, .app-row__pay-btn:hover { box-shadow: 0 2px 6px rgba(6, 56, 43, .18); }
.btn-pay:active, .btn-pay-danger:active, .btn-ghost:active { transform: translateY(1px); box-shadow: none; }

/* green: the action that moves things forward */
.btn-pay { background: var(--green-700); color: #fff; border-color: var(--green-800); }
.btn-pay:hover { background: var(--green-800); color: #fff; }
.btn-pay:disabled { opacity: .7; cursor: wait; }

/* red: money is owed */
.btn-pay-danger { background: var(--red-600); color: #fff; border-color: var(--red-700); }
.btn-pay-danger:hover { background: var(--red-700); color: #fff; }

/* grey: neutral / leave without doing anything */
.btn-ghost { background: #fff; color: var(--ink-soft); border-color: var(--line); }
.btn-ghost:hover { background: #f2f5f3; color: var(--ink); }

/* the row's own pay button follows the same shape, coloured by state */
.app-row__pay-btn--unpaid, .app-row__pay-btn--rejected {
  background: var(--red-600); color: #fff; border-color: var(--red-700);
}
.app-row__pay-btn--unpaid:hover, .app-row__pay-btn--rejected:hover { background: var(--red-700); color: #fff; }

.pay-actions { display: flex; justify-content: flex-end; gap: .5rem; }

.pay-locked {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .75rem; font-weight: 700; color: #7a5c02;
  background: #fdf6e3; border: 1px solid #ecdca4;
  padding: .25rem .55rem; border-radius: .3rem;
}

@media (max-width: 768px) {
  /* Same compact buttons as on desktop — only the touch height nudges up. They are
     NOT stretched to full width: a row of three small, evenly-sized controls reads as
     a toolbar, whereas full-width slabs read as three competing primary actions and
     push the row to three times its height. */
  .btn-pay, .btn-pay-danger, .btn-ghost,
  .app-row__act .btn, .app-row__pay-btn, .btn-admit-dead {
    --btn-fs: .72rem; height: 32px; padding: 0 .6rem;
  }
  .app-row__act { flex: 1 1 100%; flex-wrap: nowrap; gap: .3rem; }
  .app-row__act .btn, .app-row__act .dropdown { flex: 0 0 auto; }   /* natural width */
  .app-row__act .dropdown > .btn { width: auto; }

  .pay-actions { flex-direction: row; justify-content: flex-end; }
  .pay-actions .btn { flex: 0 0 auto; }

  .app-summary { gap: .45rem; }
  .app-summary__item { flex: 1 1 5.5rem; padding: .5rem .6rem; }
  .app-summary__n { font-size: 1.2rem; }
  .app-summary__k { font-size: .7rem; }
  .pay-tag { font-size: .72rem; padding: .28rem .55rem; }

  .pay-modal .modal-footer { flex-wrap: wrap; gap: .4rem; }
  .pay-locked { flex: 1 1 100%; justify-content: center; margin: 0 0 .2rem !important; }
}

/* Very narrow phones: labels would start to wrap, so let the toolbar scroll sideways
   rather than break the one-line rule or shrink the text below legibility. */
@media (max-width: 400px) {
  .app-row__act { overflow-x: auto; scrollbar-width: none; }
  .app-row__act::-webkit-scrollbar { display: none; }
}

/* .btn-rms-outline ships a 2px border, which makes it read a hair taller and heavier
   than its neighbours in the row toolbar. Inside the row, match the others exactly. */
.app-row__act .btn-rms-outline { border-width: 1px; font-weight: 600; }
.app-row__act .btn-rms { font-weight: 600; }

/* Roll number — shown only once the admit card exists (see show_roll in the view).
   Styled as a quiet slate chip, deliberately NOT green/red: it is a fact about the
   exam, not a status the applicant has to act on. */
.roll-tag {
  display: inline-flex; align-items: center; gap: .15rem;
  font-weight: 700; color: var(--green-800);
  background: #eef3f0; border: 1px solid #cfe3d8;
  padding: .05rem .4rem; border-radius: 999px;
}
.roll-tag .bi { font-size: .85em; opacity: .7; }

/* ---- receipt preview inside the payment confirmation modal -----------------
   The applicant sees the actual image they attached before it is sent, because
   "did I upload the right screenshot?" is the one thing they cannot check
   afterwards — the payment locks the moment it is submitted. */
.pay-attach {
  margin-top: .9rem; padding: .6rem; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--green-050);
}
.pay-attach__head {
  display: flex; align-items: center; gap: .4rem;
  font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  color: var(--ink-soft); margin-bottom: .5rem;
}
.pay-attach__open {
  margin-left: auto; display: inline-flex; align-items: center; gap: .25rem;
  font-size: .72rem; font-weight: 700; text-transform: none; letter-spacing: 0;
  color: var(--green-700); text-decoration: none;
}
.pay-attach__open:hover { text-decoration: underline; }
.pay-attach__img {
  display: block; width: 100%; max-height: 260px; object-fit: contain;
  background: #fff; border: 1px solid var(--line); border-radius: .3rem;
}
.pay-attach__file {
  display: flex; align-items: center; gap: .45rem;
  background: #fff; border: 1px solid var(--line); border-radius: .3rem;
  padding: .5rem .6rem; font-size: .85rem; font-weight: 600; color: var(--ink);
}
.pay-attach__file .bi { font-size: 1.1rem; color: var(--red-700); }
@media (max-width: 480px) { .pay-attach__img { max-height: 200px; } }

/* ---- password field with a reveal button ---------------------------------- */
.pw-wrap { position: relative; }
.pw-wrap .form-control { padding-right: 2.6rem; }
.pw-eye {
  position: absolute; top: 0; right: 0; height: 100%; width: 2.5rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; color: var(--ink-soft);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.pw-eye:hover { color: var(--green-700); }
.pw-eye:focus-visible { outline: 3px solid var(--gold); outline-offset: -2px; }
/* Bootstrap paints its own invalid icon inside the field; with the eye there too they
   collide, so suppress the icon and keep the red border + the message below. */
.pw-wrap .form-control.is-invalid,
.pw-wrap .form-control.is-valid { background-image: none; padding-right: 2.6rem; }

/* the field that is wrong should be obvious without reading anything */
.form-control.is-invalid { border-color: var(--red-600); }
.form-control.is-invalid:focus {
  border-color: var(--red-600); box-shadow: 0 0 0 .2rem rgba(244, 42, 65, .18);
}
.invalid-feedback { color: var(--red-700); font-size: .8rem; font-weight: 600; }

