:root {
  --brand: #0f6e5b;
  --brand-dark: #0a4f41;
  --danger: #b3261e;
  --warn-bg: #fff4e5;
  --warn-border: #e8a33d;
  --accent: #3949ab;
  --accent-dark: #2c3690;
  --accent-text: #ffffff;
  /* Brand-driven shades (BRAND_COLOR_* in config.py -> override <style> in
     every page head, see branding.theme_html()). */
  --brand-rgb: 15, 110, 91;
  --brand-deep: #0f4c3a;
  --brand-ink: #1b3a33;
  --brand-tint: #f0f7f5;
  --brand-tint-2: #eaf6f2;
  --brand-tint-3: #e7f5ee;
  --brand-tint-strong: #d9f2e6;
  --bg: #f7f7f5;
  --card: #ffffff;
  --text: #1c1c1c;
  --muted: #6b6b6b;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* Task 79: real tiled pattern image, replacing task 78's CSS dot-grid.
     --bg stays as a solid-color fallback underneath in case the image
     fails to load. */
  background-color: var(--bg);
  background-image: url("/static/bg-pattern.png");
  background-repeat: repeat;
  color: var(--text);
  max-width: 480px;
  margin: 0 auto;
  padding-bottom: 40px;
  font-size: 17px;
  /* Whole-site 15% shrink (pixkuwait, 2026-08-29), same reasoning as the
     admin-only pass above -- extended everywhere, not just /admin/*. */
  zoom: 0.85;
  /* Visible page boundary so content doesn't blend edge-to-edge into the
     background pattern (pixkuwait, 2026-08-29). */
  border: 2px solid #000;
  line-height: 1.6;
}

/* Simple, unmissable heading hierarchy (task 77): most templates use bare
   <h1>/<h2>/<h3> with no size rule here, so they previously rendered at
   whatever the browser's default em-based size happened to be. Explicit,
   clearly-stepped sizes make "this is a heading vs. body text" obvious at
   a glance instead of subtle. header.topbar h1 below is more specific and
   keeps its own smaller size for the colored top bar. */
h1 { font-size: 24px; font-weight: 700; line-height: 1.3; margin: 0 0 14px; }
h2 { font-size: 20px; font-weight: 700; line-height: 1.3; margin: 20px 0 10px; }
h3 { font-size: 18px; font-weight: 700; line-height: 1.3; margin: 16px 0 8px; }

header.topbar {
  background: var(--brand);
  color: white;
  padding: 16px;
  text-align: center;
}
header.topbar h1 { font-size: 19px; margin: 0; }
header.topbar p { font-size: 13px; margin: 4px 0 0; opacity: 0.9; }
header.topbar .logout-link { color: white; font-size: 16px; font-weight: 600; opacity: 1; text-decoration: underline; }
/* Employer-facing Arabic-language toggle (pixkuwait, 2026-07-20) --
   same treatment as .logout-link above, so it's legible against the
   dark topbar background instead of the browser's default link blue. */
header.topbar .lang-toggle a { color: white; font-size: 16px; font-weight: 600; opacity: 1; text-decoration: underline; }

main { padding: 16px; }

.site-footer {
  text-align: center;
  padding: 20px 16px 28px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
  border-top: 1px solid #e5e5e0;
  margin-top: 12px;
}
.site-footer a { color: var(--muted); text-decoration: underline; }
.site-footer .data-notice { margin: 10px auto 0; max-width: 560px; font-size: 11px; line-height: 1.5; opacity: .9; }

.card {
  background: transparent;
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
  /* Task 98: was #e5e5e0, near-invisible against the pink pattern -- now
     the same #d8d2c8 the admin tables already use, so card edges and
     table edges read as one consistent border colour. */
  border: 1px solid #d8d2c8;
}

/* Groups a card's own button-row(s) with a small heading, so several
   related actions in one card read as organized sections rather than
   one long unbroken row (admin_candidates.html, task 79 follow-up). */
.section-label {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.section-divider {
  border-top: 1px solid #e5e5e0;
  margin: 16px 0;
}

/* Task 98 (site-wide layout audit): password/email/search/url and
   <textarea> were missing from this list, so the staff + agency login
   password boxes rendered as tiny unstyled browser-default inputs next
   to a full-size Username box. Single-line controls also get one fixed
   height (--control-h) so a text input, a select and a date input sitting
   side by side are exactly the same height, and an inline button
   (form.btn-row below) can match it. */
:root { --control-h: 52px; }
input[type=text], input[type=tel], input[type=number], input[type=date],
input[type=password], input[type=email], input[type=search], input[type=url],
select, textarea {
  width: 100%;
  padding: 14px;
  font-size: 18px;
  font-family: inherit;
  border: 1px solid #ccc;
  border-radius: 8px;
  margin-bottom: 12px;
}
input[type=text], input[type=tel], input[type=number], input[type=date],
input[type=password], input[type=email], input[type=search], input[type=url],
select {
  height: var(--control-h);
  padding-top: 0;
  padding-bottom: 0;
}
textarea { line-height: 1.4; }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  border-color: var(--brand);
}
/* Task 98: a bare file input sat inline next to its label/button at a
   random offset (candidate edit form, agency dashboard). Block + small
   gap so "label / file picker / upload button" always stacks the same
   way. :not([hidden]) so the [hidden] pickers driven by a styled button
   (admin contracts' "Upload visa") stay hidden. */
input[type=file]:not([hidden]) { display: block; max-width: 100%; font-size: 15px; margin: 4px 0 8px; }

.btn {
  display: block;
  width: 100%;
  padding: 17px;
  font-size: 18px;
  font-weight: 700;
  /* Task 98: transparent 2px border (was `none`) so a filled .btn is the
     exact same height as an outlined .btn.secondary (which has a real
     2px border) when the two sit side by side in a row. */
  border: 2px solid transparent;
  border-radius: 8px;
  background: var(--brand);
  color: white;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  /* Task 98: <button> gets the browser's own font + `line-height: normal`
     while <a class="btn"> inherited body's 1.6, so a link-button and a
     real button with identical classes rendered at different heights
     side by side (e.g. Retention: "Back to candidates" vs "Purge
     selected"). One explicit font + line-height for both. */
  font-family: inherit;
  line-height: 1.3;
}
.btn:focus-visible { outline: 2px solid var(--brand-dark); outline-offset: 2px; }
.btn:hover { background: var(--brand-dark); }
.btn:active { background: var(--brand-dark); }
/* Outlined, brand-colored -- not flat gray -- so a secondary action still
   reads as clickable at a glance. pixkuwait found this live (2026-07-20):
   the old flat #e2e2e0 gray sat too close to the real :disabled gray
   (#ccc, below), so a perfectly-usable button like "Apply filters" looked
   greyed-out/inactive before ever being pressed. */
.btn.secondary { background: #fff; color: var(--brand); border: 2px solid var(--brand); }
.btn.secondary:hover { background: var(--brand-tint); }
.btn.secondary:active { background: var(--brand-tint); }
/* UPDATED (pixkuwait, 2026-08-01): was `button.btn` / `button.btn.secondary`
   -- element-scoped, so any <a class="btn"> (nav links like "+ Add
   candidate") never matched at all and rendered with no background or
   border, looking unstyled next to buttons that had a modifier class.
   Dropping the `button` type qualifier so a plain .btn/.btn.secondary
   link gets the same fill/outline a <button> does. */
button.btn:disabled { background: #ccc; color: #fff; cursor: not-allowed; border-color: transparent; }

.candidate-card {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
/* Candidate photo removed in task 103 -- cards are text-only now. */
.badge {
  display: inline-block;
  font-size: 12px;
  padding: 3px 9px;
  border-radius: 999px;
  font-weight: 700;
}
.badge.available { background: var(--brand-tint-strong); color: var(--brand-dark); }
.badge.reserved { background: #fdecc8; color: #8a5a00; }
.badge.placed { background: #e0e0e0; color: #555; }
/* Active/Deactivated column on admin_candidates.html -- was plain text,
   easy to misread as a status alongside the actual Status badge next to
   it. Same visual language (colored pill) makes "is she visible to
   employers right now" readable at a glance instead of by word alone. */
.badge.active { background: var(--brand-tint-strong); color: var(--brand-dark); }
.badge.deactivated { background: #f7d9d9; color: var(--danger); }
/* Task 94: agency portal's cancelled candidates -- same red pill. */
.badge.cancelled { background: #f7d9d9; color: var(--danger); }

/* Small play-icon badge on catalog cards indicating a bio video exists --
   deliberately NOT an inline video/autoplay element (Team briefs/
   11-bio-video-feature.md: keep the catalog list view light). */
.badge.video-badge {
  /* Inline next to the "available" badge since task 103 (no photo to
     sit under any more). */
  background: rgba(var(--brand-rgb), 0.92);
  color: white;
  white-space: nowrap;
}

.skills-row { font-size: 13px; color: var(--muted); margin-top: 4px; }

.disclaimer {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  border-radius: 8px;
  padding: 14px;
  font-size: 14px;
  margin-bottom: 16px;
  line-height: 1.5;
}
.disclaimer > strong:first-child { display: block; margin-bottom: 4px; }
/* Task 98: was `.disclaimer strong` -- every bold word inside the body
   text (e.g. "deleted" in the Civil ID photo notice, "not the final
   contract signing" on the signing page) was also forced onto its own
   line. Only the leading title is a block now. */

.dev-note {
  background: #eef3ff;
  border: 1px dashed #7a9fe0;
  border-radius: 8px;
  padding: 10px;
  font-size: 13px;
  margin-bottom: 12px;
  color: #2a4a8a;
}

.error-msg { color: var(--danger); font-size: 15px; font-weight: 600; margin: 8px 0; }
/* Success/confirmation counterpart to .error-msg above -- added for the
   walk-in reservation result panel (Team briefs/
   081-walkin-reservation-intake.md), but generic enough to reuse
   anywhere a positive confirmation (not a form error) needs the same
   treatment. */
.success-msg { color: var(--brand-dark); font-size: 15px; font-weight: 600; margin: 8px 0; }
.muted { color: var(--muted); font-size: 14px; }

.empty-state {
  text-align: center;
  padding: 40px 20px;
  color: var(--muted);
}
.empty-state svg { opacity: 0.45; margin-bottom: 12px; }
.empty-state .empty-title { font-size: 16px; font-weight: 700; color: var(--text); margin-bottom: 4px; }
.empty-state .empty-hint { font-size: 14px; color: var(--muted); }
.empty-state .empty-hint a { color: var(--brand); font-weight: 600; }

/* Bulk-import result banner (Team briefs/cv-field-extraction.md item 5):
   a real successful import previously only got a plain <p> summary buried
   below the form, which pixkuwait's own live test read as "nothing
   happened" -- this is a can't-miss-it banner instead, colored by outcome
   so a batch with real problems doesn't LOOK identical to a clean one. */
.import-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  border-radius: 10px;
  padding: 14px 16px;
  margin-bottom: 16px;
  font-size: 16px;
  font-weight: 700;
  border: 1px solid transparent;
}
.import-banner .icon { font-size: 22px; line-height: 1; }
.import-banner.ok { background: var(--brand-tint-3); border-color: var(--brand); color: var(--brand-dark); }
.import-banner.partial { background: var(--warn-bg); border-color: var(--warn-border); color: #7a4a00; }
.import-banner.none { background: #fdeceb; border-color: var(--danger); color: var(--danger); }

canvas#sigpad {
  border: 2px dashed #999;
  border-radius: 8px;
  width: 100%;
  touch-action: none;
  background: white;
}

img.contract-preview {
  width: 100%;
  border: 1px solid #ccc;
  border-radius: 8px;
  cursor: zoom-in;
}

/* Tap-to-enlarge lightbox for the contract preview (2026-07-12, pixkuwait's
   request -- the scanned form is too small/dense to read at card width). */
.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.9);
  z-index: 1000;
  padding: 20px;
  box-sizing: border-box;
  overflow: auto;
  cursor: zoom-out;
}
.lightbox.open { display: flex; align-items: flex-start; justify-content: center; }
.lightbox img { width: 120%; max-width: 576px; border-radius: 4px; }

.field-row { margin-bottom: 10px; }
.field-row label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 4px; }
/* Team briefs/093: "please check this" note under a value the app filled
   in (Kuwaiti preselected / DOB from the Civil ID number) -- the warning
   box style so it's obvious, but compact enough to sit under one field. */
.field-row .field-confirm-note { margin: 6px 0 0; padding: 8px 10px; font-size: 13px; }

/* --------------------------------------------------------------------------
   Staff admin pages (added 2026-07-02). The rest of this app is deliberately
   mobile-first/narrow (employers use phones, per the brief) -- the admin
   area is used by agency staff at a desk, so it gets a wider layout via this
   body class instead of the fixed 480px max-width above. */
body.admin { max-width: 900px; }

/* Candidates table needs min-width: 1300px (below) to keep its 9 columns
   readable -- at the 900px cap above, that pushed the actions column
   (Edit/Delete/Deactivate) off-screen, needing a horizontal scroll to
   reach it (pixkuwait, 2026-08-31). Wider just for that page so the
   whole row fits without scrolling on a normal desk monitor; other
   admin pages (forms etc.) just get extra breathing room, no downside. */
body.admin.candidates-page { max-width: 1400px; }

/* The 15% shrink is now applied site-wide on the base `body` rule above
   (pixkuwait, 2026-08-29) -- this used to be admin-only, superseded.

   The additional 10% table-only zoom that used to live here (stacking
   on top of body's 0.85) is REMOVED (pixkuwait, 2026-08-31) -- it was
   the actual cause of the green header row rendering wider than the
   table body: a table with its own `zoom` computes <thead> and
   <tbody> row-group widths slightly differently in this browser
   engine, especially combined with table-layout:fixed. Confirmed via
   screenshot the header bar's right edge sat past the body's actual
   right edge. This is the same category of bug as the sticky-header
   fix above and the sticky-CODE-column fix before that -- `zoom` on
   this table has now caused three separate rendering bugs, so it's
   coming off entirely rather than being re-tuned a fourth time. Table
   now only inherits the site-wide 0.85 from body, same as every other
   admin element -- it'll render visually larger than it did with the
   extra 0.9, which is the tradeoff for it being byte-for-byte
   consistent between header and body. */

table.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
table.admin-table th, table.admin-table td {
  text-align: left;
  padding: 10px 8px;
  border-bottom: 1px solid #e6e6e3;
  vertical-align: middle;
}
table.admin-table th { color: var(--muted); font-weight: 700; font-size: 12px; text-transform: uppercase; }
table.admin-table img.thumb { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; background: #ddd; }
/* UPDATED (pixkuwait, 2026-08-01): was `tr.inactive-row { opacity: 0.55 }`
   on the whole row -- opacity applies to a subtree as a unit, so the
   Activate/Delete buttons in the actions cell dimmed right along with
   the descriptive columns and read as disabled/unclickable even though
   they're fully live. Scoping the fade to everything EXCEPT the actions
   cell (.btn-row) keeps "this row is inactive" visible while keeping
   its buttons unambiguously clickable. */
table.admin-table tr.inactive-row td:not(.btn-row) { opacity: 0.55; }

/* Task 98: an actions cell (<td class="btn-row">) was `display: flex`
   from .btn-row above, which takes the <td> out of the table layout --
   the cell then only sized to its buttons, so it stopped short of its
   column (header bar visibly wider than the cells under it) and lost
   its row's full height/border. Keep it a real table cell; space the
   buttons with margins instead of flex gap. */
table.admin-table td.btn-row { display: table-cell; }
table.admin-table td.btn-row > .btn,
table.admin-table td.btn-row > a,
table.admin-table td.btn-row > button {
  margin-block: 2px;
  margin-inline-end: 6px;
  vertical-align: middle;
}
table.admin-table td .btn { white-space: nowrap; }
/* Phone: keep table columns readable and let the table scroll inside
   its own card (.card:has(table.admin-table) below) instead of crushing
   codes and buttons into 1-2 character wide columns. */
@media (max-width: 600px) {
  table.admin-table { min-width: 560px; }
}

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* Task 98 -- shared inline form row (form.btn-row: process updates,
   staff, agencies). Each field is a <div> holding <label><br><input>,
   followed by a submit button. Before: inputs kept their 12px bottom
   margin and buttons their own smaller height, so every button sat
   lower than / shorter than the input next to it, and inputs stayed at
   their intrinsic ~190px so long placeholders were cut off. Now: labels
   stack above, every field flexes to fill the row, controls and the
   button share one height and one bottom line. On a phone every field
   and the button take the full width (stacked). */
form.btn-row { align-items: flex-end; gap: 12px; margin-bottom: 4px; }
form.btn-row > div { flex: 1 1 180px; min-width: 0; }
form.btn-row > div.wide { flex: 2 1 300px; }
form.btn-row > div > br { display: none; }
form.btn-row > div > label { display: block; margin-bottom: 4px; }
form.btn-row input, form.btn-row select { margin-bottom: 0; }
form.btn-row > div.inline-check { flex: 0 0 auto; height: var(--control-h); display: flex; align-items: center; }
form.btn-row > div.inline-check label { margin: 0; display: flex; align-items: center; gap: 6px; }
form.btn-row > .btn {
  flex: 0 0 auto;
  height: var(--control-h);
  padding-top: 0;
  padding-bottom: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
}
@media (max-width: 600px) {
  form.btn-row > div, form.btn-row > div.wide, form.btn-row > .btn { flex: 1 1 100%; }
}
/* UPDATED (pixkuwait, 2026-08-01): was `.btn-row button.btn, .btn-row
   a.btn` (class+type+class = higher specificity than `.btn.small`'s
   two plain classes), so .btn.small/.btn.tiny were silently losing to
   THIS rule's padding/font-size on every row button across the whole
   admin app (Deactivate, Edit, Cancel reservation, Assign number, etc)
   -- they always rendered at this rule's size no matter what modifier
   they had. Dropping the type qualifiers makes this the same
   specificity as .btn.small/.btn.tiny below, so source order (those
   come later) lets them correctly win. */
.btn-row .btn { width: auto; padding: 11px 18px; font-size: 15px; font-weight: 700; display: inline-block; text-decoration: none; }
.btn.small { padding: 9px 14px; font-size: 14px; width: auto; display: inline-block; }
/* Smaller still -- for an action that should be easy to reach but not
   visually compete with routine row actions (e.g. permanent delete). */
.btn.tiny { padding: 5px 9px; font-size: 12px; width: auto; display: inline-block; }

/* CV button on the candidate detail page -- pixkuwait's explicit
   instruction: it needs to be much bigger than a normal button so no
   employer can miss it (2026-07-12). */
.btn.cv-highlight {
  padding: 28px;
  font-size: 24px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  border-radius: 10px;
}
.download-box {
  border: 3px solid var(--brand);
  border-radius: 12px;
  padding: 16px;
  margin: 4px 0 16px;
  background: var(--brand-tint-2);
  text-align: center;
}
.download-box .btn {
  font-size: 24px;
  font-weight: 700;
  padding: 20px;
}
.btn.danger { background: var(--danger); }
.btn.danger:hover { background: #7e1a15; }
.btn.danger:active { background: #7e1a15; }
/* Deactivate is reversible (a Reactivate button undoes it) -- red/--danger
   is reserved for actually destructive/error states elsewhere (error
   messages, failed imports), so using it here read as more alarming than
   the action warrants. Reuses the same amber already used for the
   partial-import warning banner. */
.btn.warn { background: var(--warn-border); color: #4a2e00; }
.btn.warn:hover { background: #c98a2e; }
.btn.warn:active { background: #c98a2e; }
/* Distinct from brand/danger/warn on purpose -- for a nav item that
   should stand out from routine candidate-record actions in the same
   row (e.g. "Manage staff", which grants real permissions). Part of the
   shared admin design so any agency clone gets the same visual language
   for "important, don't miss this" without a per-app tweak. */
.btn.accent { background: var(--accent); color: var(--accent-text); }
.btn.accent:hover { background: var(--accent-dark); }
.btn.accent:active { background: var(--accent-dark); }

.admin-topbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
/* Back/sign-out links inside admin headers, and the employer-facing
   back link (.topbar-nav-btn, used by _macros.html's topbar() macro) --
   pixkuwait 2026-07-31: these were plain low-contrast text (12px,
   90% opacity here; bold-but-boxless on the employer side) and easy to
   miss. Both now get the same visible button treatment from one place. */
.admin-topbar a,
.topbar-nav-btn {
  display: inline-block;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 6px;
  padding: 8px 14px;
  color: white;
  font-weight: 700;
  font-size: 14px;
  opacity: 1;
  text-decoration: none;
}
.admin-topbar a:hover,
.topbar-nav-btn:hover,
.admin-topbar a:active,
.topbar-nav-btn:active { background: rgba(255, 255, 255, 0.32); }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.form-grid .field-row.full { grid-column: 1 / -1; }
@media (max-width: 600px) { .form-grid { grid-template-columns: 1fr; } }

.checkbox-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; font-size: 15px; }
.checkbox-row input[type=checkbox] { width: auto; margin: 0; }

.skills-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px 12px; margin-bottom: 12px; }
@media (max-width: 480px) { .skills-grid { grid-template-columns: repeat(2, 1fr); } }

/* --- Candidates table: clearer columns/rows (pixkuwait-supplied, 2026-08-29) --- */
.card:has(table.admin-table) {
  overflow-x: auto;
  max-width: 100%;
}

table.admin-table {
  border-collapse: collapse;
  width: 100%;
}

/* min-width/table-layout/column-widths below are sized for the
   candidates table's 9 columns specifically. `table.admin-table` is
   also used on the (5-column) staff table, which was inheriting a
   forced 1300px min-width it doesn't need -- overflowing its page's
   900px boundary -- plus a stray 80px width landing on its actions
   cell from nth-child(5). Scoped to .candidates-page so the staff
   table goes back to natural auto-sized columns (pixkuwait, 2026-08-31). */
body.candidates-page table.admin-table {
  min-width: 1300px;
  table-layout: fixed;
}

table.admin-table th,
table.admin-table td {
  border: 1px solid #d8d2c8;
  padding: 8px 10px;
  text-align: left;
  vertical-align: middle;
  font-size: 13px;
  overflow-wrap: break-word;
}

/* Was `position: sticky; top: 0` so the header stayed visible while
   scrolling down the page -- dropped (pixkuwait, 2026-08-31) because it
   desyncs from the body's horizontal scroll under this page's `zoom`
   scaling: header labels end up scrolled to a different horizontal
   offset than the columns they label, and the green bar visibly runs
   wider than the table's actual last column. Same root cause as the
   sticky CODE column dropped earlier (see the "no sticky/frozen column
   anymore" note above) -- zoom + position:sticky don't reliably agree
   in this table. */
table.admin-table thead th {
  background: var(--brand-deep);
  color: #fff;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* Photo column (was col 1) removed entirely, 2026-08-29 -- pixkuwait
   found it unused in practice. Everything shifted down by one:
   1: code, 2: name, 3: position, 4: nationality, 5: salary, 6: status,
   7: active, 8: last edited, 9: actions. No sticky/frozen column
   anymore -- pixkuwait found the pinned code column looked stuck. */
body.candidates-page table.admin-table th:nth-child(1),
body.candidates-page table.admin-table td:nth-child(1) {
  width: 105px;
  font-weight: 600;
}

body.candidates-page table.admin-table th:nth-child(2), body.candidates-page table.admin-table td:nth-child(2) { width: 190px; }
body.candidates-page table.admin-table th:nth-child(3), body.candidates-page table.admin-table td:nth-child(3) { width: 110px; }
body.candidates-page table.admin-table th:nth-child(4), body.candidates-page table.admin-table td:nth-child(4) { width: 100px; }
body.candidates-page table.admin-table th:nth-child(5), body.candidates-page table.admin-table td:nth-child(5) { width: 80px; }
body.candidates-page table.admin-table th:nth-child(6), body.candidates-page table.admin-table td:nth-child(6) { width: 90px; }
body.candidates-page table.admin-table th:nth-child(7), body.candidates-page table.admin-table td:nth-child(7) { width: 90px; }
body.candidates-page table.admin-table th:nth-child(8), body.candidates-page table.admin-table td:nth-child(8) { width: 100px; }
body.candidates-page table.admin-table th:nth-child(9), body.candidates-page table.admin-table td:nth-child(9) { width: 190px; }

/* Task 98: was display:flex on this <td> -- see the td.btn-row note
   above; spacing now comes from the shared td.btn-row margins. */
body.candidates-page table.admin-table td:nth-child(9) a,
body.candidates-page table.admin-table td:nth-child(9) button {
  font-size: 11px;
  padding: 3px 6px;
  white-space: nowrap;
}

/* zebra striping */
table.admin-table tbody tr:nth-child(odd) td { background: #faf7f0; }
table.admin-table tbody tr:nth-child(even) td { background: #ffffff; }
table.admin-table tbody tr:nth-child(odd) td:nth-child(1) { background: #f2ede1; }
table.admin-table tbody tr:nth-child(even) td:nth-child(1) { background: #f7f5ee; }

/* ---------------------------------------------------------------------
   Agency portal in Amharic (Team briefs/108, task 108). Only applies when
   the page is rendered with <html lang="am">; English is untouched.
   Noto Sans Ethiopic (SIL OFL, see fonts/NotoSansEthiopic-OFL.txt) is
   self-hosted -- a subset (Ethiopic blocks + a few punctuation marks) of
   the variable font, so Latin text (JAM11, file names, KNET, CV) keeps
   rendering in the normal system font. Ethiopic glyphs are wide and
   dense, so type is ~12% larger than the English layout. LTR.
   --------------------------------------------------------------------- */
@font-face {
  font-family: "Noto Sans Ethiopic";
  src: url("/static/fonts/NotoSansEthiopic-subset.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+1200-139F, U+2D80-2DDF, U+AB00-AB2F, U+00B7, U+2014, U+2026, U+2190, U+2192;
}
html[lang="am"] body,
html[lang="am"] input, html[lang="am"] select, html[lang="am"] textarea,
html[lang="am"] button, html[lang="am"] .btn {
  font-family: "Noto Sans Ethiopic", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
html[lang="am"] body { font-size: 19px; line-height: 1.7; }
html[lang="am"] h1 { font-size: 27px; }
html[lang="am"] h2 { font-size: 22px; }
html[lang="am"] h3 { font-size: 20px; }
html[lang="am"] header.topbar h1 { font-size: 21px; }
html[lang="am"] header.topbar p { font-size: 15px; }
html[lang="am"] .muted { font-size: 16px; }
html[lang="am"] .error-msg, html[lang="am"] .success-msg { font-size: 17px; }
html[lang="am"] input[type=text], html[lang="am"] input[type=password],
html[lang="am"] select, html[lang="am"] textarea { font-size: 20px; }
html[lang="am"] input[type=file]:not([hidden]) { font-size: 17px; }
html[lang="am"] .btn { font-size: 20px; }
html[lang="am"] .btn-row .btn { font-size: 17px; }
html[lang="am"] .btn.small { font-size: 16px; }
html[lang="am"] table.admin-table { font-size: 16px; }
html[lang="am"] table.admin-table th { font-size: 14px; text-transform: none; }
/* Let long Amharic button labels wrap instead of widening the table cell. */
html[lang="am"] table.admin-table td .btn { white-space: normal; }

/* Agency language toggle ("English | አማርኛ") in the topbar. */
header.topbar .agency-lang { font-size: 14px; margin-top: 6px; }
header.topbar .agency-lang a { color: white; text-decoration: underline; opacity: 0.9; }
header.topbar .agency-lang a.current { font-weight: 700; text-decoration: none; opacity: 1; }
header.topbar .agency-lang .am { font-family: "Noto Sans Ethiopic", sans-serif; }

/* Task 122: catalog card video thumbnail + full-screen player. */
.video-thumb {
  position: relative; flex: 0 0 84px; width: 84px; height: 112px; padding: 0;
  border: 0; border-radius: 10px; overflow: hidden; background: var(--brand-ink); cursor: pointer;
}
.video-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.video-thumb-play {
  position: absolute; inset: 0; margin: auto; width: 34px; height: 34px; line-height: 34px;
  border-radius: 50%; background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 15px; text-align: center;
  padding-inline-start: 2px; box-sizing: border-box;
}
.video-thumb-tag {
  position: absolute; bottom: 4px; inset-inline-start: 4px; font-size: 11px; font-weight: 700;
  background: rgba(var(--brand-rgb), 0.92); color: #fff; padding: 1px 7px; border-radius: 999px;
}
.vplayer { position: fixed; inset: 0; z-index: 1000; background: #000; display: flex; flex-direction: column; }
.vplayer[hidden] { display: none; }
.vplayer-bar, .vplayer-nav { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; gap: 10px; }
.vplayer-count { color: #fff; font-size: 14px; }
.vplayer-btn { background: rgba(255,255,255,0.15); color: #fff; border: 0; border-radius: 999px; padding: 12px 18px; font-size: 15px; font-weight: 700; min-height: 44px; }
.vplayer-stage { flex: 1; min-height: 0; position: relative; display: flex; align-items: center; justify-content: center; touch-action: pan-y; }
.vplayer-stage video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.vplayer-info { display: block; padding: 8px 14px 0; color: #fff; text-decoration: none; }
.vplayer-name { display: block; font-size: 17px; font-weight: 700; }
.vplayer-pos { display: block; font-size: 13px; opacity: 0.8; }
.vplayer-cv { display: block; margin: 8px 14px 4px; padding: 14px 18px; min-height: 48px; box-sizing: border-box; text-align: center; background: var(--brand); color: #fff; border-radius: 999px; font-size: 16px; font-weight: 700; text-decoration: none; }
/* Task 128: swipe hint. pointer-events none on the pill; only the arrows take taps,
   so swipes and the native video controls (bottom seek bar) are untouched. */
.vplayer-arrow { position: absolute; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: rgba(0,0,0,0.25); color: #fff; font-size: 30px; line-height: 44px; text-align: center; opacity: 0.45; pointer-events: auto; z-index: 2; }
.vplayer-arrow[hidden] { display: none; }
.vplayer-arrow-left { left: 6px; }
.vplayer-arrow-right { right: 6px; }
.vplayer-hint { position: absolute; top: 14%; left: 50%; transform: translateX(-50%); max-width: 90%; box-sizing: border-box; padding: 10px 18px; border-radius: 999px; background: rgba(0,0,0,0.65); color: #fff; font-size: 15px; font-weight: 700; text-align: center; pointer-events: none; opacity: 0; z-index: 3; }
.vplayer-hint[hidden] { display: none; }
.vplayer-hint.show { animation: vplayer-hint-fade 3s ease-out forwards; }
@keyframes vplayer-hint-fade { 0%, 80% { opacity: 1; } 100% { opacity: 0; } }
.vplayer-err { position: absolute; color: #fff; background: rgba(0,0,0,0.7); padding: 10px 14px; border-radius: 8px; }

/* Task 126: Manage Candidates search + filter bar. Wraps at phone width. */
.search-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 8px; }
.search-row:last-child { margin-bottom: 0; }
.search-row input, .search-row select { margin-bottom: 0; }
.search-row input[type=search] { flex: 1 1 220px; min-width: 0; width: auto; }
.search-row select { flex: 0 1 240px; min-width: 0; width: auto; }

/* Task 142: a field with a problem is outlined in red, its message sits right under it. */
input[aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 2px rgba(180, 40, 40, 0.18); }
.field-error { margin: 4px 0 0; }
