/* ============================================================
   Deutschkurs Finder — admin panel + school-portal base styles

   Token contract aligned with site/css/style.css so:
     1. Public site and portal share the same visual default (the
        blue palette — formerly the ?theme=blue preview, promoted
        to default 2026-05-23).
     2. Theme overrides (site/css/theme-purple.css, theme-red.css)
        applied on TOP of this file via the portal layout's theme-
        loader work without any further coordination — the same
        :root vars they override are already what every portal
        rule reads from.

   --paper is kept as an alias for --bg so existing admin rules
   (`background: var(--paper)`) keep working AND automatically
   re-resolve when a theme override changes --bg.
   ============================================================ */

:root {
  /* ── Type ── (unchanged) */
  --serif:   'Instrument Serif', Georgia, serif;
  --sans:    'DM Sans', system-ui, sans-serif;
  --display: 'Space Grotesk', system-ui, sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, monospace;

  /* ── Palette — matches site/css/style.css :root (blue default) ── */
  --bg:           #EFF6FF;       /* blue 50 */
  --bg-2:         #DBEAFE;       /* blue 100 */
  --paper:        var(--bg);     /* legacy alias — re-resolves with theme */
  --surface:      rgba(255, 255, 255, 0.78);
  --surface-2:    rgba(255, 255, 255, 0.60);
  --surface-solid:#FFFFFF;
  --ink:          #0F172A;       /* slate 900 */
  --ink-soft:     #334155;       /* slate 700 */
  --muted:        #64748B;       /* slate 500 */
  --border:       rgba(59, 130, 246, 0.16);
  --border-strong:rgba(59, 130, 246, 0.32);

  --accent:       #1D4ED8;       /* blue 700 */
  --accent-2:     #0EA5E9;       /* sky 500 */
  --accent-3:     #6366F1;       /* indigo 500 */
  --accent-soft:  #DBEAFE;
  --accent-bg:    rgba(29, 78, 216, 0.08);

  --gold:         #B45309;
  --gold-bg:      #FEF3C7;
  --green:        #16A34A;
  --success:      var(--green);
  --success-bg:   #D1FAE5;
  --yellow:       #CA8A04;

  --grad-hero:    linear-gradient(135deg, #1D4ED8 0%, #0EA5E9 55%, #38BDF8 100%);
  --grad-soft:    linear-gradient(135deg, rgba(29,78,216,0.10), rgba(14,165,233,0.10) 50%, rgba(99,102,241,0.10));

  /* ── Layout ── */
  --radius:   14px;
  --shadow:   0 10px 40px -10px rgba(15, 23, 42, 0.12), 0 2px 6px -2px rgba(15, 23, 42, 0.06);

  color-scheme: light;
}

[data-theme="dark"] {
  --bg:           #0B1220;
  --bg-2:         #0F172A;
  --paper:        var(--bg);
  --surface:      rgba(15, 23, 42, 0.66);
  --surface-2:    rgba(15, 23, 42, 0.46);
  --surface-solid:#0F172A;
  --ink:          #F1F5F9;       /* slate 100 */
  --ink-soft:     #CBD5E1;       /* slate 300 */
  --muted:        #94A3B8;       /* slate 400 */
  --border:       rgba(96, 165, 250, 0.16);
  --border-strong:rgba(96, 165, 250, 0.30);

  --accent:       #60A5FA;       /* blue 400 */
  --accent-2:     #38BDF8;       /* sky 400 */
  --accent-3:     #818CF8;       /* indigo 400 */
  --accent-soft:  rgba(96, 165, 250, 0.20);
  --accent-bg:    rgba(96, 165, 250, 0.12);

  --gold:         #FBBF24;
  --gold-bg:      rgba(251, 191, 36, 0.14);
  --green:        #34D399;
  --success:      var(--green);
  --success-bg:   rgba(52, 211, 153, 0.14);
  --yellow:       #FBBF24;

  --grad-hero:    linear-gradient(135deg, #60A5FA 0%, #38BDF8 55%, #818CF8 100%);
  --grad-soft:    linear-gradient(135deg, rgba(96,165,250,0.14), rgba(56,189,248,0.10) 50%, rgba(129,140,248,0.14));

  --shadow:       0 10px 40px -10px rgba(0,0,0,0.5), 0 2px 6px -2px rgba(0,0,0,0.3);

  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; min-height: 100vh; }

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

code, .mono { font-family: var(--mono); font-size: 0.9em; }
code {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1px 6px;
}

/* ---------- Layout ---------- */
.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0;
  width: 220px;
  background: var(--surface);
  backdrop-filter: blur(20px);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  padding: 1.5rem 1rem;
  z-index: 10;
}
.sidebar .brand { display: block; margin-bottom: 2rem; line-height: 1.1; }
.sidebar .brand-mark { font-family: var(--serif); font-size: 1.8rem; color: var(--ink); display: block; }
.sidebar .brand-sub  {
  font-family: var(--mono); font-size: 11px; color: var(--accent);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.sidebar nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.sidebar nav a {
  padding: 8px 12px; border-radius: 8px;
  color: var(--ink-soft); font-weight: 500; font-size: 14px;
}
.sidebar nav a:hover { background: var(--border); color: var(--ink); text-decoration: none; }
.sidebar nav a.active {
  background: var(--grad-hero); color: #fff;
}
.sidebar .nav-sep {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  color: var(--ink-soft); letter-spacing: 0.1em;
  margin: 1.2rem 12px 0.4rem;
}
.sidebar-foot {
  padding-top: 1rem; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 6px;
}
.sidebar-foot .who {
  font-family: var(--mono); font-size: 11px; color: var(--ink-soft); text-align: center;
}

.content {
  margin-left: 220px;
  padding: 2rem 2.2rem 4rem;
  max-width: 1200px;
}
.content.no-sidebar { margin-left: 0; max-width: 100%; }

/* ---------- Page head ---------- */
/* Two-column grid: title + lede stack in column 1; any .page-actions
   buttons (e.g. "+ New school") sit in column 2 spanning both rows.
   Layout collapses to one column on narrow viewports below.
   Used by every admin + school-portal page header so the title is
   always on its own line with the description directly under it. */
.page-head {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 1.5rem;
  row-gap: 0.35rem;
  align-items: center;
  margin-bottom: 1.8rem;
}
.page-head h1 {
  grid-column: 1; grid-row: 1;
  font-family: var(--serif); font-weight: 400; font-size: 2.2rem;
  letter-spacing: -0.02em; margin: 0;
}
.page-head .page-lede {
  grid-column: 1; grid-row: 2;
  color: var(--ink-soft); font-size: 14.5px; margin: 0;
}
.page-head .page-actions {
  grid-column: 2; grid-row: 1 / span 2;
  display: flex; gap: 0.5rem; flex-shrink: 0; align-self: center;
}
@media (max-width: 700px) {
  .page-head {
    grid-template-columns: 1fr;
  }
  .page-head .page-actions {
    grid-column: 1; grid-row: auto;
    justify-self: start; margin-top: 0.3rem;
  }
}

/* ---------- Cards ---------- */
.card {
  background: var(--surface);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.4rem 1.6rem;
  margin-bottom: 1.4rem;
  box-shadow: var(--shadow);
}
.card h2 {
  font-family: var(--serif); font-weight: 400; font-size: 1.5rem;
  margin: 0 0 1rem; letter-spacing: -0.01em;
}
.card h3 {
  font-family: var(--display); font-weight: 600; font-size: 14px;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-soft); margin: 1.8rem 0 0.8rem;
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.4rem; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem 1.4rem; }
@media (max-width: 900px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }
.span-2 { grid-column: span 2; }

/* School-page editor — each section sits in its own .editor-card.
   Same visual language as .card but with a polished header (serif
   title + muted subtitle) and consistent spacing between sections.
   Used in both admin/templates/schools/page_edit.html and
   admin/portal/templates/portal/school_page_edit.html. */
.editor-card {
  background: var(--surface);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem 1.7rem;
  margin-bottom: 1.4rem;
  box-shadow: var(--shadow);
}
.editor-card-head {
  margin: -0.2rem 0 1.2rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--border);
}
.editor-card-head h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.45rem;
  letter-spacing: -0.01em;
  margin: 0 0 0.2rem;
  color: var(--ink);
}
.editor-card-head p {
  margin: 0;
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.5;
}
@media (max-width: 700px) {
  .editor-card { padding: 1.2rem 1.2rem; }
  .editor-card-head h2 { font-size: 1.2rem; }
}

/* Repeated rows inside an editor card (Teachers, FAQs, Promotions).
   Each row is a <details class="repeated-block"> so they collapse to
   a summary line, and each row sits in its own bordered panel so
   stacked rows never run together visually. */
.repeated-block {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.9rem 1.05rem;
  margin-bottom: 0.9rem;
  background: var(--surface-soft, rgba(0, 0, 0, 0.015));
}
.repeated-block:last-child {
  margin-bottom: 0;
}
.repeated-block > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
  list-style: none;
  padding: 0.15rem 0.1rem;
  user-select: none;
}
.repeated-block > summary::-webkit-details-marker { display: none; }
.repeated-block > summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  margin-right: 0.3em;
  color: var(--ink-soft);
  transition: transform 0.15s ease;
}
.repeated-block[open] > summary::before {
  transform: rotate(90deg);
}
.repeated-block[open] > summary {
  margin-bottom: 0.8rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px dashed var(--border);
}
.repeated-block:hover {
  border-color: var(--border-strong, var(--border));
}

/* Footer strip inside each repeated row holding the Remove button.
   Sits below the field grid, right-aligned, separated by a dashed
   rule so it doesn't get mistaken for a form field. */
.row-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.9rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border);
}
.remove-row-btn {
  color: #b04040;
  border-color: rgba(176, 64, 64, 0.3);
}
.remove-row-btn:hover {
  background: rgba(176, 64, 64, 0.08);
  border-color: rgba(176, 64, 64, 0.55);
  color: #8a2a2a;
}
/* Remove button is always visible. When it's the only row, the JS
   handler clears the fields in place instead of deleting the block —
   so the + Add button always has a template to clone from. */

/* Bottom-align cells inside any .grid-2 / .grid-3 that sits inside
   an .editor-card or a .repeated-block. Labels in adjacent grid cells
   often have unequal heights (one carries a "— free text" / "—
   numbers" / "YYYY-MM-DD" hint, its partner doesn't) — by default the
   shorter label's input sits higher than the taller label's input,
   producing visible misalignment. Bottom-aligning the cells makes
   every input line up along the bottom of the row regardless of
   label height. The label's content uses flex-column with a fixed
   gap so the gap between label-text and input stays constant. */
.editor-card .grid-2,
.editor-card .grid-3,
.repeated-block .grid-2,
.repeated-block .grid-3 {
  align-items: end;
}
.editor-card .grid-2 > label,
.editor-card .grid-3 > label,
.repeated-block .grid-2 > label,
.repeated-block .grid-3 > label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
/* span-2 labels (full-row textareas, image-upload widgets) shouldn't
   bottom-align — they fill the row regardless. */
.editor-card .grid-2 > .span-2,
.editor-card .grid-3 > .span-2,
.repeated-block .grid-2 > .span-2,
.repeated-block .grid-3 > .span-2 {
  align-self: stretch;
}

/* Class size: the whole label is a single flex row — headline, two
   narrow number inputs separated by an en-dash, and the auto-computed
   typical-size readout all sit on one line. Overrides the global
   flex-column rule on .editor-card .grid-2 > label and the
   .form input { width: 100% } that would otherwise make the inputs
   stack and stretch. Wraps on narrow viewports. */
.class-size-label {
  flex-direction: row !important;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.55rem !important;
  margin-bottom: 0.9rem;
}
.class-size-label > .class-size-headline {
  display: inline;
  margin: 0;
  flex: 0 0 auto;
}
.class-size-label > input[type="number"] {
  width: 6rem !important;
  flex: 0 0 auto;
  margin: 0;
}
.class-size-sep {
  color: var(--ink-soft);
  font-size: 1.1em;
  user-select: none;
}
.class-size-display {
  color: var(--ink-soft);
  font-size: 0.95em;
  font-style: italic;
  flex: 0 0 auto;
}
.class-size-display:empty { display: none; }

/* Opening hours: each day has two native time pickers + a Clear button
   in a single flex row. Override the global .form input { width: 100% }
   so the pickers shrink to their natural width and sit beside each
   other inside one grid cell. */
.hours-day-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.hours-day-row input[type="time"] {
  width: auto !important;
  flex: 1 1 0;
  min-width: 5.5rem;
}
.hours-sep {
  color: var(--ink-soft);
  font-size: 1.05em;
  user-select: none;
  flex: 0 0 auto;
}
.hours-clear-btn {
  flex: 0 0 auto;
  padding: 4px 8px;
}

/* Social URL fields: a red border + small inline error appears when
   the entered URL's hostname doesn't match the platform's expected
   hosts. The .invalid class is toggled by JS on input/blur. */
.social-field.invalid input[type="url"] {
  border-color: #c0392b;
  background: rgba(192, 57, 43, 0.05);
}
.social-error {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: #c0392b;
}
.social-error[hidden] { display: none; }

/* Funding vouchers: checkboxes for known systems + a free-text "Other"
   row underneath. The checkbox grid wraps to keep multi-column layout
   on wide editors but collapses to one column on narrow viewports. */
.funding-vouchers-block {
  margin-bottom: 0.9rem;
}
.funding-vouchers-label {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
  margin-bottom: 8px;
  color: var(--ink);
}
.funding-checkbox-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.45rem 1rem;
  margin-bottom: 0.85rem;
}
@media (max-width: 700px) {
  .funding-checkbox-grid { grid-template-columns: 1fr; }
}
.check-inline {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 0;
  font-size: 14px;
  cursor: pointer;
}
.check-inline input[type="checkbox"] {
  margin-top: 3px;
  flex: 0 0 auto;
}
.check-inline > span { line-height: 1.35; }
.funding-extras-row {
  display: block;
  margin: 0;
}

/* ---------- Stats ---------- */
.stat-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem;
}
@media (max-width: 900px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }
.stat-card {
  background: var(--surface);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.2rem 1.4rem;
  box-shadow: var(--shadow);
}
.stat-num {
  font-family: var(--serif); font-size: 2.6rem;
  background: var(--grad-hero); -webkit-background-clip: text;
  background-clip: text; color: transparent; line-height: 1.05;
}
.stat-label { font-family: var(--display); font-weight: 600; font-size: 13px; margin-top: 4px; }
.stat-sub   { font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }

/* ---------- Tables ---------- */
.datatable {
  width: 100%; border-collapse: collapse; font-size: 14px;
  /* table-layout: auto lets the browser balance column widths across
     all rows, so we never get the "one row makes its column wider
     than the rest" wobble. */
  table-layout: auto;
}
.datatable th, .datatable td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  /* Very subtle vertical separator between columns — without it the
     eye has no anchor for where one column ends and the next begins,
     and rows with mixed line counts look like they're bleeding into
     each other. The last column has no right border so it doesn't
     produce a stray line at the card's edge. */
  border-right: 1px solid var(--border);
  /* Vertically center every cell — multi-line content (e.g. a wrapped
     district name) used to push the short cells to the top of the row
     while the actions cell sat at the middle, making rows look uneven. */
  vertical-align: middle;
}
.datatable th:last-child,
.datatable td:last-child {
  border-right: 0;
}
.datatable th {
  font-family: var(--display); font-weight: 600; font-size: 12px;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-soft);
}
.datatable tr:hover td { background: rgba(109,40,217,0.04); }
.actions { display: flex; gap: 0.7rem; align-items: center; flex-wrap: wrap; }
.actions form { display: inline; margin: 0; }
/* When `.actions` is used as a <td> class (admin + portal datatables),
   the generic `display: flex` above silently nukes the cell's
   table-cell layout — so the edit/delete cell floats out of the row.
   Restore table-cell display on td.actions and lay out the inline
   children (edit link + delete form) by hand. */
/* Shrink-to-fit the actions column (and any cell tagged .cell-shrink)
   so they never claim more horizontal space than their content needs.
   Browsers treat width: 1% on a table cell as "as narrow as you can
   be while honoring min-content" — the slack then flows to the wider
   columns (Website, District, Name). Used on Tier / Source / Rating /
   numeric columns so pill cells don't open gaps that make wide rows
   visually drift apart. */
.datatable th:last-child,
.datatable th.cell-shrink,
.datatable td.cell-shrink,
td.actions {
  width: 1%;
  white-space: nowrap;
}
td.actions {
  display: table-cell;
  vertical-align: middle;
  font-size: 13px;
  text-align: left;
  line-height: 1.55;
}
/* Stack the action links vertically — one per line — so the column
   only needs ~80px instead of ~290px. This stops the cluster from
   pushing the table wider than the surrounding .card and bleeding
   the last links ("+ course", "remove") past the card's right
   border. */
td.actions > a,
td.actions > form { display: block; margin: 0; }
td.actions form { padding: 0; }
td.actions .danger-link {
  background: none;
  border: 0;
  padding: 0;
  color: #c0392b;
  font: inherit;
  cursor: pointer;
}
td.actions .danger-link:hover { text-decoration: underline; }

.kv { width: 100%; border-collapse: collapse; }
.kv th, .kv td { padding: 6px 4px; text-align: left; font-size: 14px; }
.kv th { font-weight: 500; color: var(--ink-soft); }

/* ---------- Pills ---------- */
.pill {
  display: inline-block;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  padding: 2px 8px; border-radius: 999px; line-height: 1.6;
}
.pill-submitted { background: rgba(37,99,235,0.10);  color: var(--accent-3); }
.pill-live      { background: rgba(22,163,74,0.10);  color: var(--green);    }
.pill-static    { background: rgba(202,138,4,0.12);  color: var(--yellow);   }
.pill-other     { background: rgba(109,40,217,0.10); color: var(--accent);   }
/* Premium portal tier pills. Free is muted (the default), Basic is
   accent blue, Pro is the high-emphasis green so paid schools jump
   out at a glance in the list view. */
.pill-tier-free  { background: rgba(100,116,139,0.10); color: #475569;        }
.pill-tier-basic { background: rgba(37,99,235,0.10);  color: var(--accent-3); }
.pill-tier-pro   { background: rgba(22,163,74,0.10);  color: var(--green);    }

/* ---------- Forms ---------- */
.form label { display: block; margin-bottom: 0.9rem; }
.form label > span { display: block; font-size: 14.5px; font-weight: 600; margin-bottom: 4px; color: var(--ink); }
/* Hints inside a label headline ("(Straße)", "— free text", etc.)
   flow inline with the headline so the row reads as one line. A
   long hint still wraps naturally if it can't fit. This overrides
   the global .form small { display: block } rule that's used for
   helper text sitting BELOW form fields. */
.form label > span small,
.form label > span .muted {
  display: inline;
  margin: 0 0 0 0.15em;
  padding: 0;
  font-weight: 400;
  font-size: 0.9em;
  color: var(--ink-soft);
}
.form input[type="text"],
.form input[type="email"],
.form input[type="password"],
.form input[type="tel"],
.form input[type="url"],
.form input[type="number"],
.form input[type="date"],
.form input[type="time"],
.form input[type="search"],
.form input[type="file"],
.form select,
.form textarea {
  width: 100%;
  padding: 9px 11px;
  background: var(--surface-solid);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-size: 14px;
}
.form textarea.mono { font-family: var(--mono); font-size: 13px; line-height: 1.5; }
.form input:focus, .form select:focus, .form textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(109,40,217,0.15);
}
.form small { color: var(--ink-soft); font-size: 12px; display: block; margin-top: 3px; }
.form .row { display: flex; gap: 8px; }
.form .row input { flex: 1; }

.chk-grid {
  display: flex; flex-wrap: wrap; gap: 0.4rem 0.8rem;
  border: 1px solid var(--border); border-radius: 8px;
  padding: 0.8rem 1rem; margin: 0 0 0.9rem;
}
.chk-grid legend {
  font-size: 13px; font-weight: 500; color: var(--ink-soft);
  padding: 0 6px;
}
.chk { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; }
.chk input { width: 16px; height: 16px; }
.chk.inline { margin-bottom: 0; }

.form-actions {
  display: flex; gap: 0.6rem; margin-top: 1.2rem; padding-top: 1.2rem;
  border-top: 1px solid var(--border);
}

.filter-row {
  display: flex; flex-wrap: wrap; gap: 0.7rem 1rem; align-items: flex-end;
}
.filter-row label { flex: 1; min-width: 160px; margin-bottom: 0; }

.upload-row { display: flex; gap: 1rem; align-items: flex-end; }
.upload-row .grow { flex: 1; margin-bottom: 0; }

/* ---------- Buttons ---------- */
.primary-btn, .ghost-btn, .danger-btn, .danger-link {
  font-family: var(--display); font-weight: 600; font-size: 14px;
  padding: 9px 16px; border-radius: 10px;
  cursor: pointer; border: 1px solid transparent;
  transition: transform 0.06s ease, filter 0.15s ease;
}
.primary-btn { background: var(--grad-hero); color: #fff; }
.primary-btn:hover { filter: brightness(1.08); }
.primary-btn:active { transform: translateY(1px); }
.ghost-btn {
  background: transparent; color: var(--ink);
  border-color: var(--border);
}
.ghost-btn:hover { background: var(--border); }
.danger-btn { background: #DC2626; color: #fff; }
.danger-btn:hover { filter: brightness(1.08); }
.danger-link {
  background: transparent; border: none; padding: 0;
  color: #DC2626; font-weight: 500; cursor: pointer; font-size: 14px;
}
.danger-link:hover { text-decoration: underline; }

/* ---------- Flashes ---------- */
.flashes { margin-bottom: 1rem; display: flex; flex-direction: column; gap: 0.5rem; }
.flash {
  padding: 12px 16px; border-radius: 10px; font-size: 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-left-width: 4px;
}
.flash-success { border-left-color: var(--green); }
.flash-error   { border-left-color: #DC2626; }
.flash-info    { border-left-color: var(--accent); }

/* ---------- Login screen ---------- */
.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 20% 10%, rgba(109,40,217,0.15), transparent 50%),
              radial-gradient(circle at 80% 80%, rgba(219,39,119,0.12), transparent 50%);
}
.login-card {
  width: 360px; padding: 2.4rem 2.2rem;
  background: var(--surface); backdrop-filter: blur(20px);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.login-brand { text-align: center; margin-bottom: 1.2rem; line-height: 1.1; }
.login-brand .brand-mark { font-family: var(--serif); font-size: 2.2rem; display: block; }
.login-brand .brand-sub  {
  font-family: var(--mono); font-size: 11px; color: var(--accent);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.login-lede { text-align: center; color: var(--ink-soft); font-size: 14px; margin-bottom: 1.6rem; }

/* ---------- Log viewer ---------- */
.log-view {
  background: var(--surface-solid);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 1rem 1.2rem;
  font-family: var(--mono); font-size: 12.5px;
  line-height: 1.5; max-height: 600px;
  overflow: auto; white-space: pre-wrap; word-break: break-word;
}

.muted { color: var(--ink-soft); }
.courses-table small.muted { font-size: 11.5px; }

/* ----------------------------------------------------------------
   Mobile  (≤ 800px)
   The sidebar collapses to a top bar; tables get horizontal scroll.
   ---------------------------------------------------------------- */
@media (max-width: 800px) {
  .sidebar {
    position: static; width: 100%; height: auto;
    border-right: none; border-bottom: 1px solid var(--border);
    padding: 1rem 1.2rem;
  }
  .sidebar .brand { margin-bottom: 0.8rem; }
  .sidebar nav {
    flex-direction: row; flex-wrap: wrap; gap: 4px;
  }
  .sidebar nav a {
    font-size: 13px; padding: 6px 10px;
  }
  .sidebar .nav-sep { display: none; }
  .sidebar-foot {
    flex-direction: row; align-items: center;
    border-top: none; padding-top: 0.6rem;
    gap: 8px;
  }
  .sidebar-foot .who { font-size: 10.5px; margin-left: auto; }
  .content {
    margin-left: 0; padding: 1.2rem 1rem 3rem;
  }
  .page-head h1 { font-size: 1.7rem; }
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .stat-num { font-size: 2rem; }
  .datatable {
    display: block; overflow-x: auto; white-space: nowrap;
  }
  .actions { flex-wrap: wrap; gap: 0.4rem; }
  .form-actions { flex-wrap: wrap; }
}

/* =========================================================
   Image upload widgets + Cropper modal (admin school-page editor)
   ========================================================= */

.image-upload {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.img-label {
  display: block;
  font-family: var(--display, "Space Grotesk", system-ui, sans-serif);
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft, #555);
  margin-bottom: 0.2rem;
}
.img-preview {
  position: relative;
  width: 100%;
  background: var(--surface, #f5f5f5);
  border: 1px dashed var(--border, #ccc);
  border-radius: 12px;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.img-preview img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* When there's no image yet, hide the dashed placeholder box entirely
   — the upload button alone is enough of an affordance. Use
   :not(:has(img)) instead of :empty because Jinja leaves whitespace
   (newline + indentation) between the div tags when the {% if %}
   branch is false, and :empty fails on any whitespace text node. */
.img-preview:not(:has(img)) { display: none; }
.img-preview[data-empty-aspect="2.667"] { aspect-ratio: 8/3; }
.img-preview[data-empty-aspect="1.333"] { aspect-ratio: 4/3; }
.img-preview[data-empty-aspect="1"]     { aspect-ratio: 1/1; }
.img-preview-small { max-width: 200px; }
.img-preview-photo { aspect-ratio: 4/3; }

/* "+ Add teacher" / "+ Add FAQ" buttons under the repeated-block
   containers on the school-page editor. Modest visual weight — they
   sit between sections, not as primary CTAs. */
.add-row-btn {
  margin-top: 0.6rem;
  margin-bottom: 1.5rem;
}
.add-row-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.img-preview-teacher { max-width: 180px; aspect-ratio: 1/1; }

.img-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.img-upload-btn, .img-remove-btn {
  padding: 0.4rem 0.85rem; font-size: 12.5px;
  border-radius: 8px; cursor: pointer;
}
.img-upload-btn.small, .img-remove-btn.small { padding: 0.3rem 0.65rem; font-size: 11.5px; }
.img-status { font-size: 12px; color: var(--ink-soft, #666); }

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.8rem;
}
.image-upload-photo {
  padding: 0.6rem;
  border: 1px solid var(--border, #eee);
  border-radius: 12px;
  background: var(--surface, #fafafa);
}
.photo-caption { font-size: 12.5px; padding: 0.35rem 0.5rem; margin: 0; }

.crop-modal {
  position: fixed; inset: 0;
  background: rgba(20, 15, 40, 0.65);
  backdrop-filter: blur(3px);
  z-index: 5000;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}
.crop-modal[hidden] { display: none; }
.crop-modal-box {
  background: var(--surface-solid, #fff);
  border: 1px solid var(--border, #ccc);
  border-radius: 14px;
  width: 100%; max-width: 760px; max-height: 92vh;
  display: flex; flex-direction: column;
  padding: 1.2rem 1.4rem;
  box-shadow: 0 32px 64px -16px rgba(20, 15, 40, 0.5);
}
.crop-modal-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; }
.crop-modal-head h3 { margin: 0; font-family: var(--serif, Georgia, serif); font-size: 1.3rem; font-weight: 400; }
.crop-canvas {
  flex: 1 1 auto; min-height: 0; max-height: 60vh;
  background: #1a1a1a; border-radius: 8px; overflow: hidden;
  margin: 0.7rem 0;
  display: flex; align-items: center; justify-content: center;
}
.crop-canvas img { max-width: 100%; max-height: 100%; display: block; }
.crop-modal-actions { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-top: 0.5rem; }

/* ---- Live address preview on the school-edit form ---- */
.address-preview {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin-top: 1.25rem;
  padding: 0.8rem 1rem;
  background: var(--surface-soft, rgba(0,0,0,0.03));
  border-left: 3px solid var(--accent, #6f4dff);
  border-radius: 6px;
  font-size: 14px;
}
.address-preview strong { color: var(--fg, #111); font-size: 15px; }

/* ============================================================
   Analytics dashboards (portal /portal/analytics + admin /ops/analytics)
   ============================================================ */

/* Base KPI grid + cards (moved from portal.css so admin templates
   render the same UI). */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin: 1.25rem 0 1.5rem;
}
@media (max-width: 900px) { .stats-grid { grid-template-columns: 1fr; } }
.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem 1.25rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.stat-card > header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.3rem;
}
.stat-card h3 {
  font-family: var(--display, sans-serif);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft, #555);
  margin: 0;
}
.stat-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  font-size: 11px; font-weight: 600;
  color: var(--ink-soft, #555);
  background: var(--surface-soft, rgba(0,0,0,0.05));
  border-radius: 50%;
  cursor: help;
}
.stat-big {
  font-family: var(--serif, Georgia);
  font-size: 3rem;
  line-height: 1;
  font-weight: 400;
  color: var(--ink, #111);
  letter-spacing: -0.02em;
}
.stat-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: baseline;
  margin-top: 0.35rem;
  font-size: 13px;
}
.trend-up   { color: var(--success, #16a34a); font-weight: 600; }
.trend-down { color: var(--danger,  #dc2626); font-weight: 600; }
.trend-flat { color: var(--ink-soft, #555); font-weight: 500; }
.trend-none { color: var(--ink-soft, #555); }
.stat-breakdown {
  list-style: none;
  padding: 0;
  margin: 0.85rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  border-top: 1px dashed var(--border, #e5e7eb);
  padding-top: 0.7rem;
  font-size: 13px;
}
.stat-breakdown li {
  display: flex;
  justify-content: space-between;
  color: var(--ink-soft, #555);
}
.stat-breakdown li strong { color: var(--ink, #111); }
.stat-note { margin: 0.75rem 0 0; font-size: 12.5px; line-height: 1.45; }

.analytics-meta { margin-bottom: 1.5rem; }
.analytics-meta h3 {
  font-family: var(--display, sans-serif);
  font-size: 14px;
  font-weight: 600;
  margin: 0 0 0.6rem;
}
.analytics-meta ul {
  margin: 0;
  padding-left: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 13.5px;
  line-height: 1.5;
}

.analytics-cta {
  background: linear-gradient(135deg,
    var(--accent-bg, rgba(111, 77, 255, 0.08)),
    transparent 70%);
  border: 1px solid var(--accent, #6f4dff);
}
.analytics-cta h3 {
  font-family: var(--serif, Georgia);
  font-size: 1.3rem;
  font-style: italic;
  margin: 0 0 0.5rem;
  color: var(--accent, #6f4dff);
}
.analytics-cta p { margin: 0.4rem 0; font-size: 14px; }
.analytics-cta ul {
  margin: 0.6rem 0;
  padding-left: 1.2rem;
  font-size: 14px;
  line-height: 1.55;
}

/* 4-up KPI grid (was 3 in v1; now Profile views, Outbound clicks,
   CTR, Inquiries). Falls back to 2-col then 1-col on narrow. */
.stats-grid.stats-grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) {
  .stats-grid.stats-grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .stats-grid.stats-grid-4 { grid-template-columns: 1fr; }
}

/* Two-column block for "Day of week" + "Top referrers" side by side. */
.analytics-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1.25rem;
}
@media (max-width: 900px) {
  .analytics-grid { grid-template-columns: 1fr; }
}

/* Tiles use flex columns so:
   - All cards in a row stretch to the same height (CSS grid default)
   - Content inside fills the available space evenly (no big blank
     gaps when one card is shorter than its siblings)
   - The "muted no-data" messages don't crowd the top of an
     otherwise-empty tile. */
.analytics-section {
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
}
/* NB: deliberately NO `.analytics-section + .analytics-section
   { margin-top: ... }` rule. The adjacent-sibling combinator
   matches grid siblings too — adding a top margin to every card
   after the first pushed the 2nd/3rd cards in a row DOWN below
   the 1st, making rows look misaligned. Vertical spacing between
   stacked sections already comes from `.card { margin-bottom }`,
   and horizontal spacing in grid rows comes from the grid `gap`. */
/* The chart/list area inside each tile grows to fill the card,
   pushing the section-head to the top consistently. */
.analytics-section > .dow-bars,
.analytics-section > .hour-chart,
.analytics-section > .referrers-list,
.analytics-section > .funnel,
.analytics-section > .courses-table,
.analytics-section > .datatable,
.analytics-section > .lifetime-row {
  flex: 0 0 auto;     /* don't try to grow into available height */
}

/* The 2-col + 3-col grid rows: make all child cards explicitly the
   same height so contents below align cleanly. CSS grid does this
   by default with align-items: stretch — explicit for clarity. */
.analytics-grid { align-items: stretch; }
.analytics-grid > .analytics-section { height: 100%; }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.85rem;
}
.section-head h3 {
  font-family: var(--display, sans-serif);
  font-size: 14px;
  font-weight: 600;
  margin: 0;
}
.section-sub {
  font-size: 12.5px;
  color: var(--muted, #777);
}

/* ---- Sparkline (SVG inline) ---- */
.sparkline {
  width: 100%;
  height: 64px;
  display: block;
}
.sparkline polyline {
  fill: none;
  stroke: var(--accent, #6f4dff);
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.sparkline .sparkline-fill {
  fill: var(--accent-bg, rgba(111, 77, 255, 0.10));
  stroke: none;
}
.sparkline-axis {
  display: flex;
  justify-content: space-between;
  font-size: 11.5px;
  margin-top: 0.3rem;
}
.sparkline-empty {
  padding: 1.5rem;
  text-align: center;
  font-size: 13px;
  background: var(--surface-soft, rgba(0,0,0,0.02));
  border-radius: 8px;
}

/* ---- Day-of-week bars (CSS only) ----
   Count → bar → label, stacked from top to bottom inside each
   .dow-bar.  justify-content: flex-end pushes everything to the
   bottom so the bar grows up and the count sits *just above* its
   bar (not floating at the top of a tall, mostly-empty container —
   which is what the first version did). */
.dow-bars {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.4rem;
  align-items: end;
  height: 140px;
}
.dow-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  gap: 0.2rem;
}
.dow-bar-count {
  font-size: 11px;
  color: var(--muted, #777);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dow-bar-fill {
  width: 60%;
  min-height: 2px;
  background: linear-gradient(180deg,
    var(--accent, #6f4dff) 0%,
    var(--accent-2, #9b7fff) 100%);
  border-radius: 4px 4px 0 0;
  transition: height 0.25s ease;
}
.dow-bar-label {
  margin-top: 0.15rem;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted, #777);
}

/* ---- Referrers list (host • bar • count) ---- */
.referrers-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.referrers-list li {
  display: grid;
  grid-template-columns: minmax(120px, 35%) 1fr 50px;
  gap: 0.75rem;
  align-items: center;
  font-size: 13.5px;
}
.referrer-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink, #111);
}
.referrer-bar {
  background: var(--surface-soft, rgba(0,0,0,0.04));
  border-radius: 4px;
  height: 8px;
  overflow: hidden;
}
.referrer-bar-fill {
  height: 100%;
  background: linear-gradient(90deg,
    var(--accent, #6f4dff),
    var(--accent-2, #9b7fff));
  border-radius: 4px;
}
.referrer-count {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 13px;
  color: var(--ink, #111);
}

/* ---- Top-courses table (portal) ---- */
.courses-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}
.courses-table th, .courses-table td {
  padding: 0.6rem 0.7rem;
  text-align: left;
  border-bottom: 1px solid var(--border, #e5e7eb);
}
.courses-table th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-soft, #555); font-weight: 600; }
.courses-table td.num, .courses-table th.num,
.datatable td.num, .datatable th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ---- Lifetime totals strip ---- */
.lifetime-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
}
.lifetime-row > div {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.8rem;
  background: var(--surface-soft, rgba(0,0,0,0.03));
  border-radius: 8px;
}
.lifetime-row > div .muted { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.lifetime-row > div strong { font-family: var(--serif, Georgia); font-size: 1.5rem; line-height: 1.1; }

/* ---- Admin school-picker bar ---- */
.school-picker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}
.school-picker label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.school-picker select {
  padding: 0.4rem 0.6rem;
  font-family: var(--sans);
  font-size: 13.5px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-solid, #fff);
  color: var(--ink, #111);
}

/* ---- "SPONSORED" badge in the admin schools table ---- */
.badge-sponsored {
  display: inline-block;
  font: 700 10px/1 var(--display, sans-serif);
  letter-spacing: 0.12em;
  padding: 4px 8px;
  border-radius: 4px;
  color: #fff;
  background: linear-gradient(90deg, #f59e0b, #d97706);
}

/* ---- table-wrap to allow horizontal scroll for the big admin table on phone ---- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---- Range picker (the time-range dropdown above each dashboard) ---- */
.range-picker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.85rem;
  margin: 1rem 0 1.25rem;
  padding: 0.75rem 1rem;
  background: var(--surface-soft, rgba(0,0,0,0.03));
  border: 1px solid var(--border, #e5e7eb);
  border-radius: 10px;
}
.range-picker label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 13px;
  margin: 0;
}
.range-picker label > span {
  font-family: var(--display, sans-serif);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft, #555);
}
.range-picker select {
  padding: 0.45rem 0.7rem;
  font: 600 13.5px/1.2 var(--sans);
  border: 1px solid var(--border, #d1d5db);
  border-radius: 6px;
  background: var(--surface-solid, #fff);
  color: var(--ink, #111);
  cursor: pointer;
}
.range-picker .muted.small { font-size: 12px; }

/* ---- 3-column variant for device/browser/os triplet ---- */
.analytics-grid.analytics-grid-3 {
  grid-template-columns: repeat(3, 1fr);
  margin-top: 0;
}
@media (max-width: 1100px) {
  .analytics-grid.analytics-grid-3 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
  .analytics-grid.analytics-grid-3 { grid-template-columns: 1fr; }
}

/* ---- Hour-of-day chart (Google "Popular times" style) ----
   24 vertical bars in one row, heights proportional to view counts.
   Sparse axis labels every 3 hours.  Much easier to read than the
   old 12x2 heatmap — peaks and valleys are visible at a glance. */
.hour-chart {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  gap: 3px;
  align-items: end;
  height: 130px;
  padding: 0 4px;
}
.hour-chart-bar {
  background: linear-gradient(180deg,
    var(--accent, #6f4dff) 0%,
    var(--accent-2, #9b7fff) 100%);
  border-radius: 3px 3px 0 0;
  min-height: 2px;
  position: relative;
  transition: opacity 0.12s, transform 0.12s;
  cursor: default;
}
.hour-chart-bar:hover {
  opacity: 0.85;
  transform: scaleY(1.03);
  transform-origin: bottom;
}
.hour-chart-bar .hour-chart-tooltip {
  /* Reveal on hover only — keeps the chart clean */
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  padding: 2px 6px;
  background: var(--ink, #111);
  color: #fff;
  font-size: 10.5px;
  font-weight: 600;
  border-radius: 3px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s;
  margin-bottom: 4px;
  font-variant-numeric: tabular-nums;
}
.hour-chart-bar:hover .hour-chart-tooltip { opacity: 1; }

.hour-chart-axis {
  display: flex;
  justify-content: space-between;
  /* The 24 bars span the full width with 3px gaps; padding-left/right
     of half a column nudges each label to sit under its bar's centre. */
  padding: 0 calc((100% - 8px) / 16);
  margin-top: 0.45rem;
  font-family: var(--display, sans-serif);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--muted, #777);
  font-variant-numeric: tabular-nums;
}

/* ---- Funnel chart ---- */
.funnel {
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: funnel-step;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.funnel-stage { counter-increment: funnel-step; }
.funnel-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 13.5px;
  margin-bottom: 0.3rem;
}
.funnel-label {
  font-family: var(--display, sans-serif);
  font-weight: 600;
  color: var(--ink, #111);
}
.funnel-label::before {
  content: counter(funnel-step) ". ";
  color: var(--ink-soft, #555);
  font-weight: 400;
}
.funnel-count {
  font-family: var(--serif, Georgia);
  font-size: 1.2rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink, #111);
}
.funnel-bar {
  background: var(--surface-soft, rgba(0,0,0,0.04));
  border-radius: 8px;
  height: 22px;
  overflow: hidden;
  position: relative;
}
.funnel-bar-fill {
  height: 100%;
  background: linear-gradient(90deg,
    var(--accent, #6f4dff),
    var(--accent-2, #9b7fff));
  border-radius: 8px;
  transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.funnel-dropoff {
  margin-top: 0.3rem;
  font-size: 11.5px;
}

/* ---- Split bar (new vs returning) ---- */
.split-bar {
  display: flex;
  width: 100%;
  height: 56px;
  border-radius: 10px;
  overflow: hidden;
  margin-top: 0.5rem;
}
.split-bar > div {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  padding: 0 0.5rem;
}
.split-bar > div strong { font-size: 1.05rem; margin-right: 0.4rem; }
.split-bar-new       { background: var(--accent,  #6f4dff); }
.split-bar-returning { background: var(--accent-2, #9b7fff); }

/* ---- Peer benchmarks ---- */
.peer-section {
  background: linear-gradient(135deg,
    var(--accent-bg, rgba(111, 77, 255, 0.06)),
    transparent 60%);
}
.peer-row > div strong { color: var(--accent, #6f4dff); }
.peer-summary {
  margin: 1rem 0 0;
  padding: 0.75rem 1rem;
  background: var(--surface-solid, #fff);
  border-left: 3px solid var(--accent, #6f4dff);
  border-radius: 6px;
  font-size: 14px;
  line-height: 1.5;
}

/* ---- Lat/Lng read-only inputs + auto-detect button ----
   Shared by all three school-edit surfaces:
     portal /portal/school
     portal /portal/onboarding (register-new-school tab)
     admin  /schools/<slug>/edit
   Defaults to readonly so users don't worry about touching coords —
   the "Auto-detect from address" button calls Nominatim. "Edit
   manually" unlocks the inputs if the geocoder needs a correction. */
.latlng-field input[readonly] {
  background: var(--surface-soft, rgba(0, 0, 0, 0.04));
  color: var(--muted, #777);
  cursor: not-allowed;
  border-style: dashed;
}
.latlng-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.6rem;
}
.latlng-btn {
  appearance: none;
  font: 500 12.5px/1 var(--sans);
  padding: 0.5rem 0.85rem;
  border-radius: 8px;
  border: 1px solid var(--accent, #6f4dff);
  background: var(--accent, #6f4dff);
  color: #fff;
  cursor: pointer;
  transition: opacity 0.15s, transform 0.05s;
}
.latlng-btn:hover { opacity: 0.92; }
.latlng-btn:active { transform: translateY(1px); }
.latlng-btn:disabled { opacity: 0.5; cursor: progress; }
.latlng-btn.ghost {
  background: transparent;
  color: var(--accent, #6f4dff);
}
.latlng-btn.ghost:hover {
  background: var(--accent-bg, rgba(111, 77, 255, 0.08));
}
.latlng-status {
  font-size: 12.5px;
  color: var(--muted, #777);
  flex: 1 1 100%;
}
.latlng-status[data-kind="ok"]      { color: var(--success, #16a34a); }
.latlng-status[data-kind="error"]   { color: var(--danger,  #dc2626); }
.latlng-status[data-kind="loading"] { color: var(--accent,  #6f4dff); }

/* ---------- /subscriptions: filter chips + row tinting ---------- */
/* Status-filter chips at the top of /subscriptions. Mirrors the
   "selected vs unselected tab" idea but flat so multiple can coexist
   visually with the data table below. */
.filter-chips {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  margin: 0.4rem 0 1.25rem;
}
.filter-chips .chip {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.35rem 0.85rem; border-radius: 999px;
  font-size: 13px; line-height: 1.3; text-decoration: none;
  border: 1px solid var(--border); color: var(--ink);
  background: var(--surface-solid);
}
.filter-chips .chip:hover { background: var(--border); }
.filter-chips .chip-active {
  background: var(--accent); color: #fff; border-color: var(--accent);
}
.filter-chips .chip-active:hover { filter: brightness(1.08); background: var(--accent); }
.filter-chips .chip-count {
  font-family: var(--mono); font-size: 11.5px;
  background: rgba(0,0,0,0.06); padding: 1px 7px; border-radius: 999px;
}
.filter-chips .chip-active .chip-count { background: rgba(255,255,255,0.20); }

/* /subscriptions row tinting — expired rows are loud, expiring rows
   are warm, the rest are normal. The pills inside still carry the
   full label so the colour is reinforcement not the only signal. */
.sub-row-expired  { background: rgba(220,38,38,0.05); }
.sub-row-expiring { background: rgba(202,138,4,0.05); }
.sub-note { max-width: 320px; font-size: 12.5px; color: var(--muted); }

/* Smaller variants of the existing buttons for dense action columns. */
.ghost-btn.small  { padding: 0.3rem 0.65rem; font-size: 12px; }
.ghost-btn.danger { color: #DC2626; border-color: rgba(220,38,38,0.30); }
.ghost-btn.danger:hover { background: rgba(220,38,38,0.10); }

/* Empty-state card used when a filter returns no rows. */
.empty-state { text-align: center; padding: 2rem 1rem; }

/* ---------- Theme popover (Auto / Light / Dark) — admin ---------- */
.theme-wrap { position: relative; display: inline-block; }
.theme-menu {
  position: absolute;
  left: 0; bottom: calc(100% + 0.45rem);
  min-width: 180px;
  padding: 0.35rem;
  background: var(--surface, #fff);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.22);
  z-index: 1100;
}
.theme-menu-item {
  display: flex; align-items: center; gap: 0.55rem;
  width: 100%;
  background: transparent; border: 0;
  padding: 0.5rem 0.65rem;
  font: inherit; font-size: 13.5px;
  color: var(--ink);
  border-radius: 8px; cursor: pointer;
  text-align: left;
}
.theme-menu-item:hover { background: rgba(109,40,217,0.10); color: var(--accent); }
.theme-menu-item.is-active {
  background: rgba(109,40,217,0.10);
  color: var(--accent);
  font-weight: 600;
}
.theme-menu-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  flex-shrink: 0;
}
.theme-menu-icon svg { width: 16px; height: 16px; }
.theme-menu-label { display: flex; flex-direction: column; line-height: 1.15; }
.theme-menu-label small {
  color: var(--ink-soft); font-size: 11px; font-weight: 400;
  margin-top: 1px;
}

/* ---------- Review-inbox tabs (queue + removal requests) ---------- */
.review-tabs {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 1.4rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}
.review-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: transparent;
  border: 0;
  padding: 0.55rem 0.95rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 14px;
  color: var(--ink-soft);
  cursor: pointer;
  border-radius: 8px;
  transition: background 0.15s, color 0.15s;
}
.review-tab:hover { background: rgba(109,40,217,0.06); color: var(--ink); }
.review-tab.is-active,
.review-tab[aria-selected="true"] {
  color: var(--accent);
  background: rgba(109,40,217,0.10);
}
.review-tab.is-active::after,
.review-tab[aria-selected="true"]::after {
  /* Underline indicator that aligns with the divider below the tabs. */
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -0.6rem;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}
/* Count badge — only rendered when there's something pending. */
.review-tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  height: 1.4em;
  padding: 0 0.45em;
  background: #DC2626;
  color: #fff;
  border-radius: 999px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 11px;
  line-height: 1;
}
.review-tab-panel[hidden] { display: none; }

/* ---------- Review admin (by_school + removal_requests) ---------- */
.review-admin-list { list-style: none; padding: 0; margin: 0; }
.review-admin-row {
  padding: 1rem 0;
  border-bottom: 1px solid var(--border);
}
.review-admin-row:last-child { border-bottom: 0; }
.review-admin-row.is-hidden {
  opacity: 0.65;
  background: rgba(202, 138, 4, 0.04);
  padding-left: 0.8rem;
  padding-right: 0.8rem;
  border-radius: 8px;
}
.review-admin-row-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}
.review-admin-row-stars {
  color: var(--gold, #D97706);
  letter-spacing: 1px;
  font-size: 14px;
}
.review-admin-row-meta {
  font-size: 12.5px;
  color: var(--ink-soft);
}
.review-admin-row-text {
  font-size: 14px; line-height: 1.6;
  background: rgba(0,0,0,0.02);
  padding: 0.7rem 0.95rem;
  border-radius: 8px;
  margin: 0 0 0.6rem;
}
.review-admin-reply {
  margin: 0 0 0.6rem 1.5rem;
  padding: 0.6rem 0.85rem;
  background: rgba(109,40,217,0.05);
  border-left: 3px solid var(--accent);
  border-radius: 0 6px 6px 0;
  font-size: 13.5px;
}
.review-admin-hidden-note {
  padding: 0.55rem 0.8rem;
  background: rgba(202, 138, 4, 0.10);
  border-left: 3px solid var(--gold, #D97706);
  border-radius: 0 6px 6px 0;
  font-size: 13px;
  margin: 0 0 0.7rem;
}
.review-admin-row-actions {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  margin-top: 0.4rem;
}
.review-admin-hide-form-body {
  margin-top: 0.5rem;
  padding: 0.7rem 0.85rem;
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: 8px;
  max-width: 460px;
}
.review-admin-hide-form-body textarea {
  width: 100%;
}

.removal-request-list { list-style: none; padding: 0; margin: 0; }
.removal-request {
  padding: 1rem 0;
  border-bottom: 1px solid var(--border);
}
.removal-request:last-child { border-bottom: 0; }
.removal-request-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.35rem;
  font-weight: 600;
}
.removal-request-reason {
  background: rgba(0,0,0,0.02);
  padding: 0.6rem 0.85rem;
  border-radius: 8px;
  font-size: 13.5px;
  line-height: 1.55;
  margin: 0 0 0.7rem;
}
.removal-request-actions {
  display: flex; flex-wrap: wrap; gap: 0.6rem;
  align-items: flex-start;
}
.removal-request-form-body {
  margin-top: 0.5rem;
  padding: 0.6rem 0.8rem;
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: 8px;
  max-width: 360px;
}

/* Portal-side "Request removal" partial. */
.review-removal-request {
  margin-top: 0.6rem;
}
.review-removal-request > summary {
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 12.5px;
}
.review-removal-form {
  margin-top: 0.6rem;
  padding: 0.85rem 1rem;
  background: rgba(220, 38, 38, 0.04);
  border-left: 3px solid #c0392b;
  border-radius: 0 8px 8px 0;
}
.review-removal-form textarea {
  width: 100%;
}
.review-removal-form-actions {
  display: flex; justify-content: flex-end; margin-top: 0.5rem;
}

/* Pill colour helpers used by the new admin templates */
.pill.pill-warning {
  background: rgba(202, 138, 4, 0.15);
  color: #B45309;
  border: 1px solid rgba(202, 138, 4, 0.30);
}
.pill.pill-success {
  background: rgba(22, 163, 74, 0.15);
  color: #15803D;
  border: 1px solid rgba(22, 163, 74, 0.30);
}
.pill.pill-other {
  background: rgba(120, 113, 108, 0.15);
  color: var(--ink-soft);
  border: 1px solid var(--border);
}
