/* ==========================================================================
   Moonfire ATS — Shared stylesheet
   File: /assets/css/app.css

   Tailwind (CDN) does the layout work. This file carries only what utility
   classes can't express well: keyframes, the dropzone states, the timeline
   spine, Kanban drag affordances, and scrollbar polish.
   ========================================================================== */

:root {
  --mf-navy:   #0f172a;

  /* Brand blues, mirroring www.moonfiregroup.com.
     --mf-accent      identity colour: decorative fills, borders, rings
     --mf-accent-dark icons and markers on white. 3.9:1, which clears the 3:1
                      WCAG needs for graphical objects; #00aaff alone is 2.4:1
     --mf-accent-ink  anywhere white text sits on the accent. 6.3:1, clears AA
     --mf-accent-soft tinted backgrounds
     --mf-accent-mid  light stop for gradients */
  --mf-accent:      #00aaff;
  --mf-accent-dark: #0088cc;
  --mf-accent-ink:  #006699;
  --mf-accent-soft: #e8f7ff;
  --mf-accent-mid:  #b8e6ff;

  --mf-ring:   rgba(0, 170, 255, .35);

  /* Back-compat alias. Any rule still asking for --mf-orange resolves to the
     brand accent, so a missed reference renders on-brand rather than stale. */
  --mf-orange: var(--mf-accent);
}

* { -webkit-tap-highlight-color: transparent; }

/* Brand wordmark knocked out to white for the navy admin chrome. The mark's
   "moon" half is a dark grey that is nearly invisible on #0f172a; going fully
   monochrome is the readable option and needs no second asset. */
.mf-logo-invert { filter: brightness(0) invert(1); }

body {
  /* Matches www.moonfiregroup.com — keep this stack and the marketing site's
     --font token in step, or the two properties drift apart visually. */
  font-family: 'Montserrat', system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* --------------------------------------------------------------------------
   Scrollbars — thin and unobtrusive
   -------------------------------------------------------------------------- */
.mf-scroll::-webkit-scrollbar { width: 8px; height: 8px; }
.mf-scroll::-webkit-scrollbar-track { background: transparent; }
.mf-scroll::-webkit-scrollbar-thumb {
  background: #cbd5e1; border-radius: 99px; border: 2px solid transparent;
  background-clip: content-box;
}
.mf-scroll::-webkit-scrollbar-thumb:hover { background: #94a3b8; background-clip: content-box; }
.mf-scroll { scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; }

/* --------------------------------------------------------------------------
   Motion
   -------------------------------------------------------------------------- */
@keyframes mf-fade-up   { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes mf-fade-in   { from { opacity: 0; } to { opacity: 1; } }
@keyframes mf-slide-in  { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes mf-pop       { 0% { transform: scale(.94); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
@keyframes mf-shimmer   { 0% { background-position: -600px 0; } 100% { background-position: 600px 0; } }
@keyframes mf-spin      { to { transform: rotate(360deg); } }
@keyframes mf-pulse-dot { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.mf-animate-up   { animation: mf-fade-up .38s cubic-bezier(.16,1,.3,1) both; }
.mf-animate-in   { animation: mf-fade-in .3s ease both; }
.mf-animate-pop  { animation: mf-pop .22s cubic-bezier(.16,1,.3,1) both; }
.mf-stagger > *  { animation: mf-fade-up .4s cubic-bezier(.16,1,.3,1) both; }
.mf-stagger > *:nth-child(1) { animation-delay: .02s }
.mf-stagger > *:nth-child(2) { animation-delay: .06s }
.mf-stagger > *:nth-child(3) { animation-delay: .10s }
.mf-stagger > *:nth-child(4) { animation-delay: .14s }
.mf-stagger > *:nth-child(5) { animation-delay: .18s }
.mf-stagger > *:nth-child(6) { animation-delay: .22s }
.mf-stagger > *:nth-child(7) { animation-delay: .26s }
.mf-stagger > *:nth-child(8) { animation-delay: .30s }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* --------------------------------------------------------------------------
   Skeleton loading
   -------------------------------------------------------------------------- */
.mf-skeleton {
  background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 37%, #f1f5f9 63%);
  background-size: 600px 100%;
  animation: mf-shimmer 1.4s infinite linear;
  border-radius: .6rem;
}

.mf-spinner {
  width: 1rem; height: 1rem;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; display: inline-block;
  animation: mf-spin .6s linear infinite;
}

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */
.mf-card {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 1rem;
  box-shadow: 0 1px 2px rgba(15,23,42,.04), 0 8px 24px -12px rgba(15,23,42,.12);
  transition: box-shadow .22s ease, transform .22s ease, border-color .22s ease;
}
.mf-card-hover:hover {
  box-shadow: 0 4px 8px rgba(15,23,42,.05), 0 20px 40px -20px rgba(15,23,42,.22);
  border-color: #cbd5e1;
  transform: translateY(-2px);
}

/* --------------------------------------------------------------------------
   Dropzone — the resume uploader
   -------------------------------------------------------------------------- */
.mf-dropzone {
  position: relative;
  border: 2px dashed #cbd5e1;
  border-radius: 1rem;
  background: #f8fafc;
  transition: border-color .2s ease, background .2s ease, transform .2s ease;
  cursor: pointer;
}
.mf-dropzone:hover { border-color: #94a3b8; background: #f1f5f9; }
.mf-dropzone:focus-visible { outline: none; box-shadow: 0 0 0 4px var(--mf-ring); }

.mf-dropzone.is-dragging {
  border-color: var(--mf-accent);
  background: var(--mf-accent-soft);
  transform: scale(1.01);
}
.mf-dropzone.is-dragging .mf-dz-icon { transform: translateY(-4px) scale(1.06); color: var(--mf-accent-dark); }

.mf-dropzone.is-busy   { border-style: solid; border-color: #93c5fd; background: #eff6ff; cursor: progress; }
.mf-dropzone.is-done   { border-style: solid; border-color: #6ee7b7; background: #ecfdf5; }
.mf-dropzone.is-error  { border-style: solid; border-color: #fca5a5; background: #fef2f2; }

.mf-dz-icon { transition: transform .2s ease, color .2s ease; }

.mf-progress { height: 6px; background: #e2e8f0; border-radius: 99px; overflow: hidden; }
.mf-progress > span {
  display: block; height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--mf-accent-mid), var(--mf-accent));
  border-radius: 99px; transition: width .25s ease;
}

/* Fields the parser just populated get a brief highlight. */
@keyframes mf-filled {
  0%   { background: var(--mf-accent-soft); border-color: var(--mf-accent-mid); }
  100% { background: #fff;    border-color: #cbd5e1; }
}
.mf-just-filled { animation: mf-filled 1.8s ease forwards; }

/* --------------------------------------------------------------------------
   Timeline — candidate status tracker
   -------------------------------------------------------------------------- */
.mf-timeline { position: relative; padding-left: 2rem; }
.mf-timeline::before {
  content: ''; position: absolute; left: .6875rem; top: .5rem; bottom: .5rem;
  width: 2px; background: linear-gradient(180deg, #e2e8f0, #f1f5f9);
}
.mf-timeline-item { position: relative; padding-bottom: 1.35rem; }
.mf-timeline-item:last-child { padding-bottom: 0; }
.mf-timeline-item > .mf-node {
  position: absolute; left: -2rem; top: .125rem;
  width: 1.5rem; height: 1.5rem; border-radius: 50%;
  display: grid; place-items: center;
  background: #fff; border: 2px solid #e2e8f0;
}
.mf-timeline-item.is-done > .mf-node    { border-color: #10b981; background: #10b981; color: #fff; }
.mf-timeline-item.is-current > .mf-node { border-color: var(--mf-accent); background: var(--mf-accent-soft); color: var(--mf-accent-ink); }
.mf-timeline-item.is-current > .mf-node::after {
  content: ''; position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid var(--mf-accent); opacity: .35; animation: mf-pulse-dot 1.8s ease-in-out infinite;
}
.mf-timeline-item.is-rejected > .mf-node { border-color: #f43f5e; background: #fff1f2; color: #f43f5e; }

/* --------------------------------------------------------------------------
   Kanban
   -------------------------------------------------------------------------- */
.mf-kanban { display: flex; gap: 1rem; overflow-x: auto; padding-bottom: .75rem; align-items: flex-start; }
.mf-kanban-col { flex: 0 0 300px; max-width: 300px; }
@media (min-width: 1536px) { .mf-kanban-col { flex: 1 1 0; max-width: none; } }

.mf-kanban-body { min-height: 120px; transition: background .18s ease, box-shadow .18s ease; border-radius: .85rem; }
.mf-kanban-body.is-over { background: var(--mf-accent-soft); box-shadow: inset 0 0 0 2px var(--mf-accent-mid); }

.mf-kanban-card { cursor: grab; transition: transform .16s ease, box-shadow .16s ease, opacity .16s ease; }
.mf-kanban-card:active { cursor: grabbing; }
.mf-kanban-card.is-dragging { opacity: .45; transform: rotate(1.5deg) scale(.98); }

/* --------------------------------------------------------------------------
   Toasts
   -------------------------------------------------------------------------- */
#mf-toasts {
  position: fixed; top: 1rem; right: 1rem; z-index: 90;
  display: flex; flex-direction: column; gap: .6rem;
  width: min(22rem, calc(100vw - 2rem)); pointer-events: none;
}
.mf-toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: .7rem;
  background: #fff; border: 1px solid #e2e8f0; border-left-width: 4px;
  border-radius: .85rem; padding: .85rem 1rem;
  box-shadow: 0 12px 32px -12px rgba(15,23,42,.28);
  animation: mf-slide-in .28s cubic-bezier(.16,1,.3,1) both;
  font-size: .875rem; color: #1e293b;
}
.mf-toast.is-leaving { animation: mf-fade-in .2s ease reverse both; }
.mf-toast--success { border-left-color: #10b981; }
.mf-toast--error   { border-left-color: #f43f5e; }
.mf-toast--info    { border-left-color: #0ea5e9; }
.mf-toast--warn    { border-left-color: #f59e0b; }

/* --------------------------------------------------------------------------
   Modal
   -------------------------------------------------------------------------- */
.mf-modal-backdrop {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(15,23,42,.55); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 1rem;
  animation: mf-fade-in .18s ease both;
}
.mf-modal {
  background: #fff; border-radius: 1.25rem; width: 100%;
  box-shadow: 0 30px 60px -20px rgba(15,23,42,.45);
  animation: mf-pop .22s cubic-bezier(.16,1,.3,1) both;
  max-height: calc(100vh - 2rem); display: flex; flex-direction: column;
}
body.mf-modal-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */
/* The doubled class (.mf-input.mf-input) is deliberate — do not "tidy" it away.
   @tailwindcss/forms ships a base reset that targets [type='text'], [type='email'],
   [type='password'], [type='search'], [type='number'], [type='tel'], [type='url'],
   [type='date'] … Those attribute selectors score 0-1-0, exactly the same as a bare
   .mf-input class, and the Play CDN (cdn.tailwindcss.com?plugins=forms) injects its
   stylesheet AFTER this file. A tie broken by source order means the plugin won every
   shared property: border-radius (reset to 0), padding, font-size, border-color and
   the placeholder colour / focus ring below. Doubling the class scores 0-2-0 and wins
   outright, independent of load order.
   Strictly only .mf-input needs the bump — the plugin matches <textarea> and <select>
   through element selectors (0-0-1), which already lose to a class. They are doubled
   too so the block stays uniform and nobody reintroduces the bug by "fixing" it. */
.mf-input.mf-input, .mf-select.mf-select, .mf-textarea.mf-textarea {
  width: 100%;
  border: 1px solid #cbd5e1; border-radius: .7rem;
  padding: .625rem .875rem; font-size: .9rem; color: #0f172a; background: #fff;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.mf-input.mf-input::placeholder, .mf-textarea.mf-textarea::placeholder { color: #94a3b8; }
.mf-input.mf-input:focus, .mf-select.mf-select:focus, .mf-textarea.mf-textarea:focus {
  outline: none; border-color: var(--mf-accent); box-shadow: 0 0 0 3.5px var(--mf-ring);
}
/* Both states are doubled for the same reason, and .is-invalid must stay AFTER the
   :focus rule above: the two now score an identical 0-3-0, so source order is what
   keeps a red invalid border visible while the field is focused. */
.mf-input.mf-input:disabled, .mf-textarea.mf-textarea:disabled { background: #f8fafc; color: #64748b; cursor: not-allowed; }
.mf-input.mf-input.is-invalid, .mf-textarea.mf-textarea.is-invalid { border-color: #f43f5e; box-shadow: 0 0 0 3.5px rgba(244,63,94,.18); }
/* inline-flex, not block: labels carry a small lucide icon that would
   otherwise sit on the text baseline and ride half a pixel low. */
.mf-label {
  display: flex; align-items: center; gap: .375rem;
  font-size: .8rem; font-weight: 600; color: #334155; margin-bottom: .35rem;
}
.mf-label > svg { color: #94a3b8; flex: none; }
.mf-hint  { font-size: .75rem; color: #64748b; margin-top: .3rem; }
.mf-error { font-size: .75rem; color: #e11d48; margin-top: .3rem; }

/* Doubled to stay above the shorthand `padding` in the .mf-select.mf-select base
   rule — a single .mf-select (0-1-0) would now lose to it and the option text
   would run under the chevron. */
.mf-select.mf-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .8rem center; padding-right: 2.25rem;
}

/* Honeypot — must be reachable by bots, invisible to humans. */
.mf-hp {
  position: absolute !important; left: -9999px !important;
  width: 1px; height: 1px; overflow: hidden; opacity: 0;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.mf-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  font-weight: 600; font-size: .875rem; border-radius: .7rem;
  padding: .625rem 1.1rem; transition: all .16s ease;
  cursor: pointer; border: 1px solid transparent; white-space: nowrap;
}
.mf-btn:disabled { opacity: .55; cursor: not-allowed; }
.mf-btn:focus-visible { outline: none; box-shadow: 0 0 0 3.5px var(--mf-ring); }
.mf-btn-primary   { background: var(--mf-accent-ink); color: #fff; }
.mf-btn-primary:hover:not(:disabled)   { background: #005580; box-shadow: 0 8px 20px -8px rgba(0,136,204,.7); }
.mf-btn-dark      { background: var(--mf-navy); color: #fff; }
.mf-btn-dark:hover:not(:disabled)      { background: #1e293b; }
.mf-btn-ghost     { background: #fff; color: #334155; border-color: #cbd5e1; }
.mf-btn-ghost:hover:not(:disabled)     { background: #f8fafc; border-color: #94a3b8; }
.mf-btn-danger    { background: #fff; color: #e11d48; border-color: #fecdd3; }
.mf-btn-danger:hover:not(:disabled)    { background: #fff1f2; border-color: #fda4af; }

/* --------------------------------------------------------------------------
   Misc
   -------------------------------------------------------------------------- */
.mf-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .7rem; font-weight: 600; padding: .2rem .55rem;
  border-radius: 99px; border: 1px solid transparent; white-space: nowrap;
}

.mf-empty { text-align: center; padding: 3rem 1.5rem; color: #64748b; }
.mf-empty svg { margin: 0 auto 1rem; color: #cbd5e1; }

[x-cloak], .mf-hidden { display: none !important; }

.mf-line-clamp-2 {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.mf-line-clamp-3 {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   Prose — operator-authored copy (job descriptions) rendered by Helpers::richText
   -------------------------------------------------------------------------- */
.mf-prose { color: #475569; font-size: .9375rem; line-height: 1.7; }
.mf-prose > * + * { margin-top: .85rem; }
.mf-prose p  { margin: 0; }
.mf-prose ul { margin: 0; padding-left: 1.15rem; list-style: disc; }
.mf-prose li { margin: .3rem 0; padding-left: .15rem; }
.mf-prose li::marker { color: var(--mf-accent-dark); }
.mf-prose strong { color: var(--mf-navy); font-weight: 600; }

@media print {
  .mf-no-print { display: none !important; }
  body { background: #fff; }
}

/* ==========================================================================
   Dark theme — ADMIN ONLY
   ==========================================================================

   Every rule below is gated behind [data-theme="dark"] on <html>, and
   Layout::open() only emits that attribute when $shell === 'admin'. Candidate,
   public and bare pages therefore never match a single line of this block even
   though they load the same stylesheet. That gate is the whole scoping
   mechanism — if you ever want dark elsewhere, widen it in Layout.php, not
   here.

   WHY OVERRIDES AND NOT `dark:` VARIANTS: the admin screens carry 217 hardcoded
   light colour utilities across admin/*.php + Layout.php. Adding a dark: twin
   to each would mean 217 markup edits and 217 chances to miss one. Instead this
   layer re-points the ~40 DISTINCT utilities they draw from, which is the same
   specificity trick the forms fix above relies on: Tailwind emits `.bg-white`
   at 0-1-0, and `[data-theme="dark"] .bg-white` scores 0-2-0, so it wins
   outright no matter that the Play CDN injects its stylesheet after this file.
   Variant utilities compile to `.hover\:bg-slate-50:hover` (0-2-0), so the dark
   twin has to keep the :hover to reach 0-3-0 — dropping it would silently lose.

   DELIBERATELY NOT REMAPPED — the navy sidebar. <aside data-nav> is already
   dark chrome in the light theme, and it is built from bg-navy-900,
   border-white/10, hover:bg-white/5, text-white, text-slate-300 and
   text-slate-400. None of those six appear in the remap list, so the sidebar
   renders identically in both themes with no re-assertion rules and no
   :not([data-nav] *) gymnastics. Keep it that way: the moment you remap
   text-slate-300 or text-slate-400 you break the sidebar, because those two are
   its body text. They are also perfectly legible on the dark panels below
   (6.2:1 and 11:1), which is exactly why they need no help.
   -------------------------------------------------------------------------- */

[data-theme="dark"] {
  /* Tells the browser to render native widgets — scrollbars, the <select>
     popup, date pickers, autofill — in their dark variants. One line does what
     would otherwise be unreachable from CSS. */
  color-scheme: dark;

  --mf-d-canvas: #0b1220;   /* page behind everything; darker than the panels */
  --mf-d-panel:  #131c2e;   /* cards, toasts, modals, mobile header */
  --mf-d-raised: #1b2537;   /* subtle fills and hovers (was slate-50/100) */
  --mf-d-sunken: #0e1626;   /* form fields — reads as cut into the panel */
  --mf-d-line:   #253145;   /* borders and dividers */
  --mf-d-line-2: #33415c;   /* hover borders, field borders */
  --mf-d-ink:    #e6edf6;   /* headings */
  --mf-d-ink-2:  #c3cddb;   /* body copy */
  --mf-d-ink-3:  #93a1b5;   /* muted copy (was slate-500, unreadable at 3.3:1) */
  --mf-d-accent: #4cc2ff;   /* accent TEXT. Not --mf-accent-ink, which stays
                               dark because .mf-btn-primary puts #fff on it. */

  /* Re-pointed, not redefined: every existing consumer (kanban drop target,
     current timeline node, dropzone drag state) picks this up for free. */
  --mf-accent-soft: rgba(0, 170, 255, .14);
}

/* The admin <body> carries bg-slate-100, which the surface rule below would
   otherwise turn into --mf-d-raised and flatten the canvas against the cards.
   [class] is an attribute selector purely to buy a point of specificity
   (0-2-1 > 0-2-0) without hardcoding which utility the body happens to use. */
[data-theme="dark"] body { color: var(--mf-d-ink-2); }
[data-theme="dark"] body[class] { background-color: var(--mf-d-canvas); }

/* ---- Surfaces ---------------------------------------------------------- */
[data-theme="dark"] .bg-white,
[data-theme="dark"] .bg-white\/85        { background-color: var(--mf-d-panel); }
[data-theme="dark"] .bg-slate-50,
[data-theme="dark"] .bg-slate-100        { background-color: var(--mf-d-raised); }
[data-theme="dark"] .bg-slate-200,
[data-theme="dark"] .bg-slate-300        { background-color: #334155; }

[data-theme="dark"] .bg-brand-50,
[data-theme="dark"] .bg-brand-50\/50,
[data-theme="dark"] .bg-brand-50\/60     { background-color: rgba(0, 170, 255, .12); }
[data-theme="dark"] .bg-emerald-50       { background-color: rgba(16, 185, 129, .14); }
[data-theme="dark"] .bg-amber-50         { background-color: rgba(245, 158, 11, .14); }
[data-theme="dark"] .bg-rose-50,
[data-theme="dark"] .bg-rose-50\/60      { background-color: rgba(244, 63, 94, .14); }
[data-theme="dark"] .bg-sky-50           { background-color: rgba(14, 165, 233, .14); }

/* Variant twins keep the :hover so they land at 0-3-0 and outrank the
   0-2-0 utility Tailwind generates. */
[data-theme="dark"] .hover\:bg-slate-50:hover,
[data-theme="dark"] .hover\:bg-slate-50\/60:hover  { background-color: var(--mf-d-raised); }
[data-theme="dark"] .hover\:bg-slate-100:hover,
[data-theme="dark"] .hover\:bg-slate-200:hover     { background-color: #233047; }
[data-theme="dark"] .hover\:bg-brand-50\/30:hover,
[data-theme="dark"] .hover\:bg-brand-50\/40:hover,
[data-theme="dark"] .hover\:bg-brand-100:hover     { background-color: rgba(0, 170, 255, .16); }
[data-theme="dark"] .hover\:bg-rose-50:hover       { background-color: rgba(244, 63, 94, .16); }
[data-theme="dark"] .hover\:bg-amber-50:hover      { background-color: rgba(245, 158, 11, .16); }

/* ---- Borders ----------------------------------------------------------- */
[data-theme="dark"] .border-slate-100,
[data-theme="dark"] .border-slate-200    { border-color: var(--mf-d-line); }
[data-theme="dark"] .border-rose-200     { border-color: rgba(244, 63, 94, .35); }
[data-theme="dark"] .hover\:border-slate-300:hover { border-color: var(--mf-d-line-2); }
[data-theme="dark"] .hover\:border-brand-200:hover { border-color: rgba(0, 170, 255, .45); }

/* Tailwind's divide utility emits `.divide-x > :not([hidden]) ~ :not([hidden])`
   at 0-3-0 — the two :not()s each contribute their argument's weight. The dark
   twin must repeat the whole chain to reach 0-4-0. */
[data-theme="dark"] .divide-slate-100 > :not([hidden]) ~ :not([hidden]) { border-color: var(--mf-d-line); }

/* ---- Text -------------------------------------------------------------- */
[data-theme="dark"] .text-navy-900,
[data-theme="dark"] .text-slate-900,
[data-theme="dark"] .text-slate-800      { color: var(--mf-d-ink); }
[data-theme="dark"] .text-slate-700,
[data-theme="dark"] .text-slate-600      { color: var(--mf-d-ink-2); }
[data-theme="dark"] .text-slate-500      { color: var(--mf-d-ink-3); }
[data-theme="dark"] .hover\:text-navy-900:hover { color: var(--mf-d-ink); }

[data-theme="dark"] .text-brand-600,
[data-theme="dark"] .text-brand-700      { color: var(--mf-d-accent); }
[data-theme="dark"] .hover\:text-brand-600:hover,
[data-theme="dark"] .group:hover .group-hover\:text-brand-600 { color: var(--mf-d-accent); }

[data-theme="dark"] .text-emerald-500,
[data-theme="dark"] .text-emerald-600,
[data-theme="dark"] .text-emerald-700    { color: #34d399; }
[data-theme="dark"] .text-rose-600,
[data-theme="dark"] .text-rose-700,
[data-theme="dark"] .text-rose-800\/80,
[data-theme="dark"] .text-rose-900       { color: #fb7185; }
[data-theme="dark"] .hover\:text-rose-600:hover { color: #fb7185; }
[data-theme="dark"] .text-amber-500,
[data-theme="dark"] .text-amber-600,
[data-theme="dark"] .text-amber-700      { color: #fbbf24; }
[data-theme="dark"] .text-sky-600        { color: #38bdf8; }

/* ---- mf- components ---------------------------------------------------- */
[data-theme="dark"] .mf-card {
  background: var(--mf-d-panel); border-color: var(--mf-d-line);
  box-shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px -12px rgba(0,0,0,.55);
}
[data-theme="dark"] .mf-card-hover:hover {
  border-color: var(--mf-d-line-2);
  box-shadow: 0 4px 8px rgba(0,0,0,.35), 0 20px 40px -20px rgba(0,0,0,.6);
}

/* background-COLOR, never the `background` shorthand: .mf-select.mf-select
   paints the chevron with background-image/-repeat/-position, and a shorthand
   here (0-3-0, later in the file) would reset all three to initial and the
   arrow would vanish. Only the colour is ours to change. */
[data-theme="dark"] .mf-input.mf-input,
[data-theme="dark"] .mf-select.mf-select,
[data-theme="dark"] .mf-textarea.mf-textarea {
  background-color: var(--mf-d-sunken); border-color: var(--mf-d-line-2); color: var(--mf-d-ink);
}
[data-theme="dark"] .mf-input.mf-input::placeholder,
[data-theme="dark"] .mf-textarea.mf-textarea::placeholder { color: #6b7c93; }
/* The base rule above scores 0-3-0 — identical to the light `:focus` and
   `.is-invalid` rules in the Forms section. A tie goes to whichever is later in
   the file, which is this block, so without these two the focus ring and the
   red invalid border would both be silently overwritten by the resting border.
   Same ordering contract as the light theme: .is-invalid stays after :focus. */
[data-theme="dark"] .mf-input.mf-input:focus,
[data-theme="dark"] .mf-select.mf-select:focus,
[data-theme="dark"] .mf-textarea.mf-textarea:focus { border-color: var(--mf-accent); }
[data-theme="dark"] .mf-input.mf-input.is-invalid,
[data-theme="dark"] .mf-textarea.mf-textarea.is-invalid { border-color: #f43f5e; }
[data-theme="dark"] .mf-input.mf-input:disabled,
[data-theme="dark"] .mf-textarea.mf-textarea:disabled { background-color: #0a1120; color: #6b7c93; }
/* Chevron restroked from slate-500 to slate-400 — the darker one disappears
   against --mf-d-sunken. */
[data-theme="dark"] .mf-select.mf-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
}

[data-theme="dark"] .mf-label            { color: var(--mf-d-ink-2); }
[data-theme="dark"] .mf-label > svg      { color: var(--mf-d-ink-3); }
[data-theme="dark"] .mf-hint             { color: var(--mf-d-ink-3); }
[data-theme="dark"] .mf-error            { color: #fb7185; }
[data-theme="dark"] .mf-empty            { color: var(--mf-d-ink-3); }
[data-theme="dark"] .mf-empty svg        { color: #3a4a63; }
[data-theme="dark"] .mf-prose            { color: var(--mf-d-ink-2); }
[data-theme="dark"] .mf-prose strong     { color: var(--mf-d-ink); }
[data-theme="dark"] .mf-progress         { background: var(--mf-d-line); }
[data-theme="dark"] .mf-skeleton {
  background: linear-gradient(90deg, #182236 25%, #22304a 37%, #182236 63%);
  background-size: 600px 100%;
}

/* .mf-btn-ghost is the workhorse here (34 uses). Its light :hover scores 0-3-0
   and would otherwise repaint the button #f8fafc on hover, so the dark twin has
   to match the full :hover:not(:disabled) chain at 0-4-0. */
[data-theme="dark"] .mf-btn-ghost  { background: var(--mf-d-panel); color: var(--mf-d-ink-2); border-color: var(--mf-d-line-2); }
[data-theme="dark"] .mf-btn-ghost:hover:not(:disabled)  { background: var(--mf-d-raised); border-color: #465a7a; }
[data-theme="dark"] .mf-btn-dark   { background: #334155; }
[data-theme="dark"] .mf-btn-dark:hover:not(:disabled)   { background: #415367; }
/* --mf-accent-ink (#006699) is legible but murky on --mf-d-canvas; one step
   lighter keeps white text at 4.5:1 and reads as the primary action. */
[data-theme="dark"] .mf-btn-primary { background: var(--mf-accent-dark); }
[data-theme="dark"] .mf-btn-primary:hover:not(:disabled) { background: #0077b3; box-shadow: 0 8px 20px -8px rgba(0,136,204,.5); }
[data-theme="dark"] .mf-btn-danger  { background: var(--mf-d-panel); color: #fb7185; border-color: rgba(244,63,94,.4); }
[data-theme="dark"] .mf-btn-danger:hover:not(:disabled) { background: rgba(244,63,94,.14); border-color: rgba(244,63,94,.6); }

[data-theme="dark"] .mf-toast {
  background: var(--mf-d-panel); border-color: var(--mf-d-line);
  color: var(--mf-d-ink-2); box-shadow: 0 12px 32px -12px rgba(0,0,0,.7);
}
[data-theme="dark"] .mf-modal { background: var(--mf-d-panel); box-shadow: 0 30px 60px -20px rgba(0,0,0,.75); }

[data-theme="dark"] .mf-timeline::before { background: linear-gradient(180deg, var(--mf-d-line-2), var(--mf-d-line)); }
[data-theme="dark"] .mf-timeline-item > .mf-node { background: var(--mf-d-panel); border-color: var(--mf-d-line-2); }
[data-theme="dark"] .mf-timeline-item.is-current > .mf-node  { color: var(--mf-d-accent); }
[data-theme="dark"] .mf-timeline-item.is-rejected > .mf-node { background: rgba(244,63,94,.16); }

[data-theme="dark"] .mf-scroll { scrollbar-color: #33415c transparent; }
[data-theme="dark"] .mf-scroll::-webkit-scrollbar-thumb { background: #33415c; background-clip: content-box; }
[data-theme="dark"] .mf-scroll::-webkit-scrollbar-thumb:hover { background: #465a7a; background-clip: content-box; }

/* ---- The toggle itself ------------------------------------------------- */
/* One button, two icons, no JS to swap them: the theme attribute decides which
   is displayed, so the control is always correct on first paint even though the
   attribute is set by the inline script in <head>. */
[data-theme="dark"] .mf-theme-sun,
.mf-theme-moon                  { display: block; }
[data-theme="dark"] .mf-theme-moon,
.mf-theme-sun                   { display: none; }

/* Printing an admin page while dark is on would otherwise put light text on
   whatever the printer gives us. Force the light contract back for print. */
@media print {
  [data-theme="dark"] { color-scheme: light; }
  [data-theme="dark"] body[class] { background-color: #fff; }
  [data-theme="dark"] body { color: #1e293b; }
}
