/* ═══════════════════════════════════════════════════════
   Learning Hive SMS — Main Stylesheet
   Honey/Amber + Warm Navy Design System
   ═══════════════════════════════════════════════════════ */

/* ── Alpine.js ───────────────────────────────────────── */

/* Hide elements until Alpine initialises — prevents flash */
[x-cloak] { display: none !important; }

/* ── Colour Tokens ───────────────────────────────────── */

:root {
  /* Brand — Honey/Amber. Channel triplets (space-separated R G B) so the
     Tailwind `honey` utilities resolve to rgb(var(--honey-N) / <alpha>) and a
     tenant can re-skin the accent by overriding these vars (see branding). */
  --honey-50:  255 251 235;
  --honey-100: 254 243 199;
  --honey-200: 253 230 138;
  --honey-300: 252 211 77;
  --honey-400: 251 191 36;
  --honey-500: 245 158 11;
  --honey-600: 217 119 6;
  --honey-700: 180 83 9;
  --honey-800: 146 64 14;
  --honey-900: 120 53 15;

  /* Navy — Deep dark tones */
  --color-navy-700: #1e2a45;
  --color-navy-800: #152035;
  --color-navy-900: #0f172a;
  --color-navy-950: #080d19;

  /* Semantic — Light mode */
  --color-bg-page:       #faf9f7;
  --color-bg-surface:    #ffffff;
  --color-bg-subtle:     #f5f4f1;
  --color-bg-inverse:    #0f172a;

  --color-text-primary:  #1a1a2e;
  --color-text-secondary:#52525b;
  --color-text-tertiary: #a1a1aa;
  --color-text-inverse:  #f1f5f9;

  --color-border:        #e4e4e7;
  --color-border-strong: #d4d4d8;

  /* Accent — derived from the honey palette so a tenant accent re-skins it */
  --color-accent:        rgb(var(--honey-500));
  --color-accent-hover:  rgb(var(--honey-600));
  --color-accent-light:  rgb(var(--honey-50));
  --color-accent-text:   rgb(var(--honey-800));

  /* Status colours */
  --color-success:       #16a34a;
  --color-success-bg:    #f0fdf4;
  --color-warning:       #d97706;
  --color-warning-bg:    #fffbeb;
  --color-danger:        #dc2626;
  --color-danger-bg:     #fef2f2;
  --color-info:          #2563eb;
  --color-info-bg:       #eff6ff;
  --color-neutral:       #52525b;
  --color-neutral-bg:    #f4f4f5;
}

/* Dark mode overrides */
.dark {
  --color-bg-page:       #0c0f1a;
  --color-bg-surface:    #161b2e;
  --color-bg-subtle:     #1c2237;
  --color-bg-inverse:    #0c0f1a;

  --color-text-primary:  #f1f5f9;
  --color-text-secondary:#94a3b8;
  --color-text-tertiary: #475569;
  --color-text-inverse:  #0f172a;

  --color-border:        #2a3040;
  --color-border-strong: #3a4155;

  --color-accent:        rgb(var(--honey-400));
  --color-accent-hover:  rgb(var(--honey-500));
  --color-accent-light:  rgb(var(--honey-900));
  --color-accent-text:   rgb(var(--honey-200));

  --color-success-bg:    #052e16;
  --color-warning-bg:    #422006;
  --color-danger-bg:     #450a0a;
  --color-info-bg:       #0c1a3a;
  --color-neutral-bg:    #1c2237;
}

/* ── Typography ──────────────────────────────────────── */

body {
  font-family: 'Inter', system-ui, sans-serif;
}

/* ── Navigation (Admin Sidebar) ─────────────────────── */

/* Mobile nav drawer. Off-canvas below lg (1024px), static from lg up — the
   breakpoint here must stay in step with the `lg:hidden` on the hamburger and
   the backdrop in admin_panel/base.html.

   Deliberately plain CSS rather than Tailwind's `-translate-x-full` +
   `max-lg:translate-x-0`: the open state has to beat the closed state, and
   stacking two conflicting translate utilities leaves the winner up to
   Tailwind's emit order. `.is-open` outranks the base rule on specificity here,
   so the drawer cannot get stuck closed. Keeping the closed transform in a
   stylesheet rather than an Alpine binding also means the drawer is already
   off-screen on first paint — Alpine is deferred, so binding the closed state
   would flash the full menu open on every mobile page load. */
@media (max-width: 1023.98px) {
  .nav-drawer { transform: translateX(-100%); }
  .nav-drawer.is-open { transform: translateX(0); }
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: #94a3b8;
  transition: all 150ms ease;
}

.nav-item:hover {
  background-color: rgba(255, 255, 255, 0.06);
  color: #e2e8f0;
}

.nav-item-active {
  background-color: rgb(var(--honey-500) / 0.12);
  color: rgb(var(--honey-400));
}

.nav-item-active svg {
  color: rgb(var(--honey-400));
}

/* Portal tabs */
.portal-tab {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  transition: all 150ms ease;
  white-space: nowrap;
}

.portal-tab:hover {
  background-color: var(--color-bg-subtle);
  color: var(--color-text-primary);
}

.portal-tab-active {
  background-color: var(--color-accent-light);
  color: var(--color-accent-text);
}

.dark .portal-tab-active {
  background-color: rgb(var(--honey-400) / 0.12);
  color: rgb(var(--honey-400));
}

/* ── Buttons ─────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: 0.5rem;
  padding: 0.5rem 0.875rem;
  font-size: 0.875rem;
  font-weight: 500;
  transition: all 150ms ease;
  cursor: pointer;
}

.btn:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-bg-surface), 0 0 0 4px var(--color-accent);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Primary — honey amber */
.btn-primary {
  background-color: var(--color-accent);
  color: rgb(var(--honey-900));
}
.btn-primary:hover {
  background-color: var(--color-accent-hover);
}
.dark .btn-primary {
  background-color: rgb(var(--honey-400));
  color: #422006;
}
.dark .btn-primary:hover {
  background-color: rgb(var(--honey-500));
}

/* Dark — navy/dark for secondary actions */
.btn-dark {
  background-color: #0f172a;
  color: #ffffff;
}
.btn-dark:hover {
  background-color: #1e293b;
}
.dark .btn-dark {
  background-color: #1e293b;
  color: #f1f5f9;
}
.dark .btn-dark:hover {
  background-color: #334155;
}

.btn-secondary {
  background-color: var(--color-bg-surface);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
}
.btn-secondary:hover {
  background-color: var(--color-bg-subtle);
  border-color: var(--color-border-strong);
}

.btn-danger {
  background-color: #dc2626;
  color: #ffffff;
}
.btn-danger:hover {
  background-color: #b91c1c;
}

.btn-ghost {
  color: var(--color-text-secondary);
  background: transparent;
}
.btn-ghost:hover {
  background-color: var(--color-bg-subtle);
  color: var(--color-text-primary);
}

.btn-sm {
  padding: 0.375rem 0.625rem;
  font-size: 0.75rem;
}

.btn-lg {
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  border-radius: 0.625rem;
}

.btn-icon {
  padding: 0.375rem;
}

/* ── Form Inputs ─────────────────────────────────────── */

.form-input {
  display: block;
  width: 100%;
  border-radius: 0.5rem;
  border: 1px solid var(--color-border);
  background-color: var(--color-bg-surface);
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  color: var(--color-text-primary);
  transition: box-shadow 150ms ease, border-color 150ms ease;
}

.form-input::placeholder {
  color: var(--color-text-tertiary);
}

.form-input:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgb(var(--honey-500) / 0.2);
  border-color: var(--color-accent);
}

.form-input:disabled {
  background-color: var(--color-bg-subtle);
  color: var(--color-text-tertiary);
}

.form-input.error {
  border-color: #f87171;
}
.form-input.error:focus {
  box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.2);
  border-color: #f87171;
}

.form-select {
  display: block;
  width: 100%;
  cursor: pointer;
  appearance: none;
  padding-right: 2rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23a1a1aa' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  background-position: right 0.5rem center;
  background-repeat: no-repeat;
  background-size: 1.25rem;
}

.form-label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-primary);
  margin-bottom: 0.375rem;
}

.form-label-required::after {
  content: ' *';
  color: #ef4444;
}

.form-hint {
  margin-top: 0.375rem;
  font-size: 0.75rem;
  color: var(--color-text-tertiary);
}

.form-error {
  margin-top: 0.375rem;
  font-size: 0.75rem;
  color: #dc2626;
}
.dark .form-error {
  color: #f87171;
}

.form-group {
  display: flex;
  flex-direction: column;
}

/* Error state via wrapper — set by components/_field.html when the bound
   field has errors, so templates never need to mutate widget attrs */
.form-group.has-error .form-input,
.form-group.has-error .form-select {
  border-color: #f87171;
}
.form-group.has-error .form-input:focus,
.form-group.has-error .form-select:focus {
  box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.2);
  border-color: #f87171;
}

/* Element-scoped (not bare .form-checkbox) — CheckboxSelectMultiple and
   RadioSelect widgets copy their attrs' class onto the *wrapping* <div>
   as well as each <input>. A bare class selector here would also shrink
   that wrapper to 1rem, squashing every option's text into it. */
input.form-checkbox,
input.form-radio {
  width: 1rem;
  height: 1rem;
  cursor: pointer;
  accent-color: var(--color-accent);
}
input.form-checkbox:focus-visible,
input.form-radio:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Multi-option checkbox/radio groups (CampaignForm programs/events,
   event/lead "interested programs") — Django renders these as a bare
   <div> per option with no spacing; give each option room to breathe. */
.form-group > div:has(> div > label > input.form-checkbox),
.form-group > div:has(> div > label > input.form-radio) {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.form-group > div:has(> div > label > input.form-checkbox) > div label,
.form-group > div:has(> div > label > input.form-radio) > div label {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--color-text-primary);
}

/* Stop iOS Safari zooming the page when a field takes focus.

   Safari scales the whole viewport in on focus of any control whose font-size
   is under 16px, and leaves it scaled — so on an iPhone every form in the app
   currently lurches sideways on the first tap and the user has to pinch back
   out. `.form-input` is 0.875rem and `.form-select` inherits whatever the
   markup gives it, so both trip it.

   Two things about the selectors are deliberate:

   Keyed on `pointer: coarse` rather than a width breakpoint, because this is a
   touch-input behaviour, not a narrow-screen one — an iPad at 800px zooms just
   as an iPhone does, while a desktop window dragged narrow should keep the
   dense sizing staff expect.

   Element-scoped (`input.form-input`, not `.form-input`) for the same reason
   the checkbox rules above are: specificity. 91 of 146 `.form-input` and 57 of
   71 `.form-select` usages also carry a Tailwind `text-xs`/`text-sm` utility,
   which is a single class and would otherwise win or lose on stylesheet order.
   Adding the element name outranks it outright.

   `select.filter-select` currently matches nothing — the class is defined but
   unused — and is listed so the trap does not reopen if anyone adopts it. */
@media (pointer: coarse) {
  input.form-input,
  select.form-input,
  textarea.form-input,
  select.form-select,
  select.filter-select {
    font-size: 1rem;
  }
}

/* ── Filter selects ──────────────────────────────────── */

.filter-select {
  border-radius: 0.5rem;
  border: 1px solid var(--color-border);
  background-color: var(--color-bg-surface);
  padding: 0.375rem 2rem 0.375rem 0.75rem;
  font-size: 0.75rem;
  color: var(--color-text-primary);
  appearance: none;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23a1a1aa' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  background-position: right 0.5rem center;
  background-repeat: no-repeat;
  background-size: 1rem;
  cursor: pointer;
}

/* ── Pagination ──────────────────────────────────────── */

.pagination-btn {
  display: inline-flex;
  align-items: center;
  padding: 0.375rem 0.75rem;
  border-radius: 0.375rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
  background-color: var(--color-bg-surface);
  transition: all 150ms ease;
}

.pagination-btn:hover {
  background-color: var(--color-bg-subtle);
  border-color: var(--color-border-strong);
  color: var(--color-text-primary);
}

/* ── Progress bars ───────────────────────────────────── */

/*
 * A data-driven width is the one thing a static Tailwind class cannot express:
 * `w-[{{ pct }}%]` is never generated, because Tailwind scans source, not
 * rendered output. So the styling lives here and the template supplies only the
 * datum, as a CSS custom property:
 *
 *   <div class="progress-track">
 *     <div class="progress-fill" style="--fill: 45%"></div>
 *   </div>
 *
 * That keeps to the design system's "Tailwind classes or CSS custom properties
 * only" rule — nothing about the appearance is inline.
 */
.progress-track {
  height: 0.375rem;
  border-radius: 9999px;
  background-color: var(--color-bg-subtle);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  border-radius: 9999px;
  background-color: var(--color-accent);
  width: var(--fill, 0%);
}

.progress-fill-success { background-color: var(--color-success); }
.progress-fill-warning { background-color: var(--color-warning); }
.progress-fill-danger  { background-color: var(--color-danger); }

/* ── HTMX Indicator ──────────────────────────────────── */

.htmx-request #htmx-indicator {
  transform: scaleX(0.6) !important;
}

.htmx-settling #htmx-indicator {
  transform: scaleX(1) !important;
}

/* ── Button Loading Spinner ──────────────────────────── */

/* Hidden by default; shown while an enclosing HTMX request is in flight
   (form gets .htmx-request) or via Alpine on full-page submits */
.btn .btn-spinner {
  display: none;
}

.htmx-request .btn .btn-spinner,
.btn.htmx-request .btn-spinner,
.btn .btn-spinner.spinning {
  display: inline-block;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Toast Messages ──────────────────────────────────── */

.toast-progress {
  width: 100%;
  animation: toast-progress 5s linear forwards;
}

.toast:hover .toast-progress {
  animation-play-state: paused;
}

@keyframes toast-progress {
  from { width: 100%; }
  to   { width: 0; }
}

/* ── Scroll Animations (Landing Page) ────────────────── */

.scroll-animate {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.scroll-animate.animate-in {
  opacity: 1;
  transform: translateY(0);
}

.scroll-animate-delay-1 { transition-delay: 0.1s; }
.scroll-animate-delay-2 { transition-delay: 0.2s; }
.scroll-animate-delay-3 { transition-delay: 0.3s; }
.scroll-animate-delay-4 { transition-delay: 0.4s; }

/* ── Honeycomb Pattern (Landing Page) ────────────────── */

.honeycomb-pattern {
  background-image: url("data:image/svg+xml,%3Csvg width='56' height='100' viewBox='0 0 56 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M28 66L0 50L0 16L28 0L56 16L56 50L28 66L28 100' fill='none' stroke='%23f59e0b' stroke-width='0.5' opacity='0.07'/%3E%3Cpath d='M28 0L28 34L0 50L0 84L28 100L56 84L56 50L28 34' fill='none' stroke='%23f59e0b' stroke-width='0.5' opacity='0.05'/%3E%3C/svg%3E");
}

/* ── Landing Page Utilities ──────────────────────────── */

.gradient-honey {
  background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 50%, #fde68a 100%);
}

.dark .gradient-honey {
  background: linear-gradient(135deg, #1c1608 0%, #261d0a 50%, #2a1f0a 100%);
}

.gradient-navy {
  background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
}

/* ── Rich Text ───────────────────────────────────────── */

/* The element rules for `.prose` live in templates/components/_document_prose.html,
   shared verbatim with the certificate PDF. What belongs here instead is
   everything web-only: the size modifier, colours that follow the tenant accent,
   and the chrome around the authoring editor. */

.prose-sm {
  font-size: 0.875rem;
}

/* The cursive face for {{ signer_signature }}.

   Bundled rather than named through the generic `cursive` keyword, and that is
   the whole point. `cursive` resolves to whatever the reader's machine happens to
   have — Segoe Script on Windows, Apple Chancery on macOS, often Comic Sans in
   Chrome — while WeasyPrint has only DejaVu installed and would fall back to a
   plain sans. The same agreement would look like two different documents, which
   is the one thing the shared `.prose` ruleset exists to prevent. One file, both
   surfaces: the PDF loads this same TTF through the `contract-font:` scheme.

   Dancing Script, SIL Open Font License 1.1 — licence shipped alongside it at
   static/fonts/DancingScript-OFL.txt, which the licence requires.

   A variable font with a single weight axis. WeasyPrint instantiates it at 400
   when it subsets, so there is no static instance to ship. There is no italic
   axis either, which is why nothing sets font-style on it: that would ask for a
   synthetic oblique and double-slant a face that is already cursive. */
@font-face {
  font-family: "LHive Signature";
  src: url("../fonts/DancingScript.02ed13c946ba.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

.prose a,
.prose-editor .ProseMirror a {
  color: rgb(var(--honey-600));
}

.dark .prose a,
.dark .prose-editor .ProseMirror a {
  color: rgb(var(--honey-400));
}

/* django-prose-editor reads these four custom properties and falls back to
   Django-admin variables that do not exist outside the admin — which is why the
   authoring surface rendered as a white box on a dark page. Setting them is the
   supported hook; overriding the editor's own selectors is not. */
.prose-editor,
.prose-editor-dialog {
  --prose-editor-background:   var(--color-bg-surface);
  --prose-editor-foreground:   var(--color-text-primary);
  --prose-editor-border-color: var(--color-border);
  --prose-editor-active-color: rgb(var(--honey-500));
}

.prose-editor .ProseMirror {
  min-height: 16rem;
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  border-radius: 0.5rem;
}

.prose-editor .ProseMirror:focus {
  box-shadow: 0 0 0 2px rgb(var(--honey-500) / 0.2);
}

/* ── Utilities ───────────────────────────────────────── */

.text-2xs {
  font-size: 0.625rem;
  line-height: 1rem;
}

.tabular-nums {
  font-variant-numeric: tabular-nums;
}
