/* The admin, wearing the public site's clothes.
 *
 * The colour ramp is set in UNFOLD["COLORS"] in settings; this file carries
 * everything a ramp cannot: the type, the corner radius, the card shadow and
 * the handful of places where Unfold's defaults fight the palette.
 *
 * Fraunces for headings and Mulish for body are exactly what the public site
 * uses, so the two surfaces read as one product rather than a site with a
 * Django admin bolted on. */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,700&family=Mulish:wght@300;400;500;600;700;800&display=swap');

:root {
  --serif: 'Fraunces', Georgia, serif;
  --sans: 'Mulish', -apple-system, system-ui, sans-serif;
  --admin-radius: 14px;
  --admin-radius-lg: 22px;
  --admin-pill: 44px;
  --admin-shadow-sm: 0 4px 18px rgba(112, 78, 250, .06);
  --admin-shadow: 0 18px 50px rgba(112, 78, 250, .10);
  --admin-cta: #F0AA00;
  --admin-cta-deep: #D4920A;
  --admin-line: rgba(112, 78, 250, .10);
  --admin-line-strong: rgba(112, 78, 250, .18);
}

body, .font-sans, input, select, textarea, button {
  font-family: var(--sans);
}

h1, h2, h3, .font-display, #content h1, .text-font-important-light {
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: -.012em;
}

.rounded-default { border-radius: var(--admin-radius); }
.shadow-xs, .shadow-sm { box-shadow: var(--admin-shadow-sm); }
.shadow-md, .shadow-lg { box-shadow: var(--admin-shadow); }

/* Filled primary controls keep white text.
 *
 * Unfold paints buttons with several shades of primary depending on the
 * component and the hover state. Covering only bg-primary-600 leaves any
 * control using another shade with dark text on a saturated violet ground,
 * which is unreadable. Cover the whole saturated range, and the icons with it. */
.bg-primary-500, .bg-primary-600, .bg-primary-700,
.bg-primary-800, .bg-primary-900,
.hover\:bg-primary-600:hover, .hover\:bg-primary-700:hover,
.bg-primary-600 *, .bg-primary-700 * {
  color: #ffffff;
}

a.bg-primary-500, a.bg-primary-600, a.bg-primary-700,
button.bg-primary-500, button.bg-primary-600, button.bg-primary-700,
input[type="submit"].bg-primary-500,
input[type="submit"].bg-primary-600,
input[type="submit"].bg-primary-700,
.button, input[type="submit"], .submit-row input[type="submit"] {
  color: #ffffff;
  font-weight: 700;
}

.bg-primary-500 svg, .bg-primary-600 svg, .bg-primary-700 svg,
.bg-primary-500 .material-symbols-outlined,
.bg-primary-600 .material-symbols-outlined,
.bg-primary-700 .material-symbols-outlined {
  color: #ffffff;
  fill: currentColor;
}

/* A disabled primary button dims the whole control rather than just the label:
   white on pale violet reads as broken rather than as disabled. */
.bg-primary-600:disabled,
.bg-primary-600[disabled],
button:disabled.bg-primary-600 {
  opacity: .55;
  color: #ffffff;
}

/* The save row is the one place the site's amber belongs, because it is the
   same decision the public site's call to action is: the thing you came to do.
   Amber is light, so the text stays dark or it disappears. */
.submit-row input[name="_save"] {
  background: linear-gradient(135deg, #F5C040, var(--admin-cta-deep));
  color: #1f1400;
  font-weight: 700;
}
.submit-row input[name="_save"]:hover { filter: brightness(1.05); }

/* Left untouched on purpose: the sidebar keeps Unfold's own neutral ground.
   Painting it with the primary violet puts violet nav labels on a violet
   background and the navigation becomes invisible. */

.dash-track span[title] { cursor: default; }

#content > div > .bg-white,
#content form > div > .bg-white,
fieldset.module,
.unfold-card {
  border-radius: var(--admin-radius-lg);
  border: 1px solid var(--admin-line);
}

#content .border,
#content .border-base-200 { border-color: var(--admin-line); }

.button,
a.button,
button,
input[type="submit"],
.submit-row input[type="submit"],
#content .bg-primary-600 {
  border-radius: var(--admin-pill);
  font-family: var(--sans);
  letter-spacing: 0;
  transition: transform .22s cubic-bezier(.22, 1, .36, 1), box-shadow .22s, filter .22s;
}

.button:hover,
a.button:hover,
input[type="submit"]:hover { transform: translateY(-2px); }

input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="url"], input[type="tel"],
input[type="search"], input[type="date"], input[type="time"],
input[type="datetime-local"], select, textarea {
  border-radius: var(--admin-radius);
  border: 1px solid var(--admin-line-strong);
  transition: border-color .15s, box-shadow .15s;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: rgb(var(--color-primary-500));
  box-shadow: 0 0 0 3px rgb(var(--color-primary-500) / .14);
}

#content table { border-radius: var(--admin-radius); overflow: hidden; }

#content thead th {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: .02em;
  text-transform: uppercase;
}

#nav-sidebar a, .unfold-sidebar a { border-radius: var(--admin-radius); }

/* ------------------------------------------------------------------ GrapesJS */

.gjs-field-wrapper { margin-top: .5rem; }

/* ------------------------------------------------------------------- Heatmap
 *
 * The page renders at its real breakpoint width inside an iframe and is scaled
 * down with a transform, so the stored click coordinates stay valid. Resizing
 * the iframe instead would reflow the page and move every point.
 *
 * Without these rules the stage has no positioning context, so the iframe and
 * the canvas stop stacking and the whole thing renders as an unusable column
 * of full-height frames.
 */
/* justify-items rather than a margin on the column: the grid track still spans
   the full content width, so the panel centres inside it at every breakpoint
   without the width having to be known here. */
.hm-grid { display: grid; gap: .75rem; align-items: start; justify-items: center; }
.hm-col { min-width: 0; }
.hm-viewport { position: relative; overflow: hidden; }
.hm-stage { position: relative; transform-origin: top left; }
.hm-frame { position: absolute; inset: 0; border: 0; display: block; pointer-events: none; }
.hm-canvas { position: absolute; inset: 0; pointer-events: none; }

/* One page at a time, at 40% of the viewport. A full-width panel makes a
   12000px page a scroll marathon, and the point of a heatmap is the shape of
   the heat rather than the legibility of the body copy. */
.hm-col { width: 40vw; max-width: 40vw; }
.hm-viewport { max-height: 78vh; overflow-y: auto; }

@media (max-width: 1400px) { .hm-col { width: 55vw; max-width: 55vw; } }
@media (max-width: 900px)  { .hm-col { width: 100%; max-width: 100%; } }
