:root {
  /* A teacher's planning notebook, not a finance dashboard: warm paper
     instead of clinical mint, ink-tinted neutrals instead of flat grays,
     and a single reserved amber for the one thing per screen that should
     actually stand out. */
  --bg: #F1F4EE;
  --surface: #FFFFFF;
  --primary: #1C5C4E;
  --primary-hover: #123E34;
  --primary-tint: #E4EFE9;
  --accent: #B8842E;
  --accent-tint: #FBF1DC;
  --text-heading: #16231E;
  --text-body: #55635B;
  --border: #DEE5DC;
  --warning-text: #92400E;
  --warning-bg: #FCEEDD;
  --danger: #AB3524;
  --danger-bg: #FBEAE5;
  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(22, 35, 30, 0.07), 0 1px 1px rgba(22, 35, 30, 0.04);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Space Grotesk", var(--font);
  /* .dash-topbar's resting height: 46px brand image + 12px padding top and
     bottom + 1px border. The sticky sidebar sits directly under it. */
  --topbar-h: 71px;

  /* One spacing step and one type step for everything laid out from here
     on, instead of a new pixel value per rule. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-md: 16px;
  --text-lg: 20px;
  --text-xl: 24px;
  /* Inputs, selects and buttons share one height so a filter row lines up. */
  --control-h: 42px;

  /* This app has one light theme; saying so keeps native controls (notably
     <select> on Windows) from being painted in the OS's dark scheme against
     a light page. */
  color-scheme: light;
}

* {
  box-sizing: border-box;
}

html, body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text-body);
  -webkit-font-smoothing: antialiased;
}

/* Kill the 300ms double-tap-to-zoom delay on every control, and replace the
   default grey flash with the brand tint. */
a,
button,
label,
select,
summary,
[role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: var(--primary-tint);
}

/* Headings are link targets in the guide/lesson views — keep one clear of
   the sticky topbar when jumped to. */
h1, h2, h3, h4, h5, h6 {
  scroll-margin-top: calc(var(--topbar-h) + 12px);
}

/* Skip link: first thing in the tab order on every dashboard page, injected
   by ensureMobileSidebarToggle() in icons.js so it exists on all of them
   without editing each file. Visible only while focused. */
.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 300;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  background: var(--primary);
  color: #FFFFFF;
  font-size: 14px;
  font-weight: 600;
  transform: translateY(-200%);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* Anything animated here is decoration, never the only way information is
   conveyed, so honouring a reduced-motion preference is a blanket opt-out
   rather than a set of per-component alternatives. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--text-heading);
  font-weight: 500;
  letter-spacing: -0.01em;
  margin: 0;
}

p {
  margin: 0;
  color: var(--text-body);
}

a {
  color: var(--primary);
  text-decoration: none;
}

a:hover {
  color: var(--primary-hover);
  text-decoration: underline;
}

button {
  font-family: inherit;
}

:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.centered-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 36px 32px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 28px;
}

.brand img {
  width: 34px;
  height: 34px;
  object-fit: contain;
  flex-shrink: 0;
}

.brand span {
  font-size: 18px;
  font-weight: 700;
  color: var(--text-heading);
  letter-spacing: -0.01em;
}

.app-shell {
  min-height: 100vh;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 14px 28px;
}

.topbar .brand {
  margin-bottom: 0;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

.topbar-user {
  font-size: 14px;
  color: var(--text-body);
}

.topbar-user strong {
  color: var(--text-heading);
}

.main {
  max-width: 1080px;
  margin: 0 auto;
  padding: 40px 28px 80px;
}

/* Every page opens the same way: the title with its one-line purpose under
   it, and the page's actions on the right. On a phone the actions follow the
   subtitle rather than wedging between the title and it. */
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4) var(--space-6);
  margin-bottom: var(--space-6);
  flex-wrap: wrap;
}

.page-heading {
  min-width: 0;
  flex: 1 1 320px;
}

.page-header h1,
.page-header .dash-page-title {
  font-size: var(--text-xl);
  line-height: 1.2;
  margin: 0;
}

.page-subtitle {
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--text-body);
  margin: var(--space-2) 0 0;
  max-width: 640px;
}

.page-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

@media (max-width: 640px) {
  .page-header {
    align-items: stretch;
    margin-bottom: var(--space-5);
  }

  .page-header h1,
  .page-header .dash-page-title {
    font-size: var(--text-lg);
  }

  .page-actions {
    width: 100%;
  }

  .page-actions .btn {
    flex: 1 1 auto;
  }
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--primary);
  margin-bottom: 16px;
}

.field {
  margin-bottom: 18px;
}

.field label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-heading);
  margin-bottom: 6px;
}

.hint,
.field .hint {
  font-size: 12px;
  color: var(--text-body);
  margin-top: 5px;
}

.role-toggle {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.role-option {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-body);
  margin: 0;
}

.role-option input {
  accent-color: var(--primary);
  width: auto;
}

.role-option:has(input:checked) {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--bg);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="file"],
input[type="search"],
select,
textarea {
  width: 100%;
  font-family: inherit;
  font-size: 14px;
  color: var(--text-heading);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  transition: border-color 0.15s ease;
}

/* Safari gives type="search" a rounded native shape and its own inner
   decorations, which would make the one search box on the site look unlike
   every other field. */
input[type="search"] {
  -webkit-appearance: none;
  appearance: none;
}

input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

/* iOS zooms the whole page in when a focused field's text is under 16px and
   never zooms back out. 14px is the deliberate density on a desktop form, so
   raise it only where that behaviour applies. */
@media (max-width: 640px) {
  /* Has to repeat the type selectors above: a media query adds no
     specificity, so a bare `input` rule would lose to `input[type="text"]`. */
  input[type="text"],
  input[type="email"],
  input[type="password"],
  input[type="date"],
  input[type="file"],
  input[type="search"],
  input[type="number"],
  input[type="tel"],
  select,
  textarea {
    font-size: 16px;
  }
}

textarea {
  resize: vertical;
  min-height: 90px;
  line-height: 1.5;
}

/* Applied to generated fields whose content is a bulleted list (objectives,
   references, materials, etc.) so each "• " line reads as a distinct item
   with breathing room, instead of one dense block of text. */
textarea.textarea-list {
  line-height: 1.85;
  white-space: pre-wrap;
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--primary);
}

input::placeholder,
textarea::placeholder {
  /* Was #9CA3AF, which measured 2.54:1 on white against a 4.5:1 requirement,
     so every field's example text failed contrast. Tinted from the body ink
     rather than a flat gray. */
  color: #6B7A72;
  opacity: 1;
}

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.checkbox-row input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--primary);
}

.checkbox-row label {
  font-size: 13px;
  color: var(--text-body);
  font-weight: 500;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  border-radius: var(--radius-sm);
  padding: 10px 18px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
  white-space: nowrap;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--primary);
  color: #FFFFFF;
}

.btn-primary:hover:not(:disabled) {
  background: var(--primary-hover);
  /* a:hover recolours links to --primary-hover, which on an <a class="btn
     btn-primary"> (Export as Word) made the label vanish into the fill. */
  color: #FFFFFF;
}

/* A button that is an <a> must not take the link hover colour, which is the
   same dark green as the hovered button behind it. */
a.btn:hover {
  text-decoration: none;
}

a.btn-primary:hover {
  color: #FFFFFF;
}

.btn-secondary {
  background: var(--surface);
  color: var(--text-heading);
  border-color: var(--border);
}

.btn-secondary:hover:not(:disabled) {
  border-color: var(--primary);
  color: var(--primary);
}

.btn-secondary.danger {
  color: var(--danger);
}

.btn-secondary.danger:hover:not(:disabled) {
  border-color: var(--danger);
  color: var(--danger);
  background: var(--danger-bg);
}

.btn-ghost {
  background: transparent;
  color: var(--text-body);
  border-color: transparent;
  padding: 8px 10px;
}

.btn-ghost:hover:not(:disabled) {
  color: var(--text-heading);
}

.btn-danger {
  background: transparent;
  color: var(--danger);
  border-color: var(--border);
}

.btn-danger:hover:not(:disabled) {
  border-color: var(--danger);
}

.btn-block {
  width: 100%;
}

.btn-sm {
  padding: 6px 12px;
  font-size: 13px;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 24px;
}

/* Caps a block's width for comfortable reading/form-filling (short labels,
   name fields, step indicators) inside a page that otherwise uses the full
   available width — e.g. the format builder, where the document canvas
   next to it needs to stay wide. */
.form-narrow {
  max-width: 640px;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

.format-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.format-card:hover {
  border-color: var(--primary);
}

/* Title + privacy badge on the left, a kebab menu for secondary actions
   (Edit / Delete / View original) on the right — keeps only ONE prominent
   action per card ("Use this format") instead of a row of same-weight
   buttons that has no room to breathe at typical card widths. */
.format-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.format-card-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.format-card h3 {
  font-size: 15.5px;
  line-height: 1.35;
  overflow-wrap: break-word;
}

.format-card-meta {
  font-size: 12.5px;
  color: var(--text-body);
}

.format-card-cta {
  margin-top: auto;
}

.format-card-skeleton {
  height: 148px;
}

.new-format-tile {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px;
  min-height: 140px;
  color: var(--text-body);
  background: transparent;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}

.new-format-tile:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--bg);
}

.new-format-tile .plus {
  font-size: 22px;
  line-height: 1;
  color: var(--primary);
}

/* The amber accent itself is too light to read as text on its tint (2.9:1),
   so the label uses a darker amber from the same hue. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--accent-tint);
  color: #7A5516;
  border: 1px solid transparent;
  white-space: nowrap;
}

.badge svg {
  width: 12px;
  height: 12px;
}

/* De-emphasized variant for a "default"/unremarkable state (e.g. a private
   format) so it doesn't compete for attention with the primary-colored
   badge used for a genuinely notable state (e.g. shared publicly). */
.badge-neutral {
  background: var(--bg);
  color: var(--text-body);
}

.empty-state {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 48px 24px;
  text-align: center;
  color: var(--text-body);
}

.empty-state h2,
.empty-state h3 {
  font-size: 16px;
  margin-bottom: 6px;
}

.empty-state p {
  font-size: 14px;
  margin-bottom: 18px;
}

.alert {
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-size: 13px;
  margin-bottom: 18px;
  border: 1px solid transparent;
}

.alert-error {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: #FCA5A5;
}

.alert-warning {
  background: var(--warning-bg);
  color: var(--warning-text);
  border-color: #FDE68A;
}

/* Information the student should act on, not a failure: calm, not red. */
.alert-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  background: var(--primary-tint);
  color: var(--text-heading);
  border-color: var(--border);
}

.alert[hidden] {
  display: none;
}

.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(12px);
  background: var(--text-heading);
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 500;
  padding: 12px 18px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 100;
}

.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.toast.toast-error {
  background: var(--danger);
}

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #FFFFFF;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

.btn-secondary .spinner,
.btn-ghost .spinner {
  border: 2px solid rgba(27, 110, 106, 0.25);
  border-top-color: var(--primary);
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.skeleton {
  background: var(--border);
  border-radius: var(--radius-sm);
  position: relative;
  overflow: hidden;
}

.step-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 24px;
}

.step-indicator .step {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-body);
}

.step-indicator .step .dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: var(--text-body);
  background: var(--surface);
}

.step-indicator .step.active .dot {
  background: var(--primary);
  border-color: var(--primary);
  color: #FFFFFF;
}

.step-indicator .step.active span.label {
  color: var(--text-heading);
}

.step-indicator .step.done .dot {
  background: var(--bg);
  border-color: var(--primary);
  color: var(--primary);
}

.step-indicator .divider {
  width: 32px;
  height: 1px;
  background: var(--border);
}

.field-row {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 14px;
  position: relative;
}

.field-row-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.field-row-grid .field {
  margin-bottom: 0;
}

.field-row-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.field-row-top .field-index {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-body);
}

.field-key-preview {
  font-size: 12px;
  color: var(--text-body);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.dropzone {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 32px 20px;
  text-align: center;
  color: var(--text-body);
  font-size: 14px;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

.dropzone:hover,
.dropzone.dragover {
  border-color: var(--primary);
}

.dropzone strong {
  color: var(--primary);
}

.file-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 13px;
  color: var(--text-heading);
}

.gen-tabs {
  display: flex;
  gap: 28px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 24px;
}

.gen-tabs button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: none;
  background: none;
  color: var(--text-body);
  font-size: 14px;
  font-weight: 600;
  padding: 12px 2px;
  margin-bottom: -1px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

.gen-tabs button.active {
  color: var(--primary);
  border-bottom-color: var(--primary);
}

.gen-tabs button .tab-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--border);
  color: var(--text-body);
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
}

.gen-tabs button.active .tab-step-num {
  background: var(--primary);
  color: #FFFFFF;
}

.tab-panel {
  animation: tab-fade-in 0.15s ease-out;
}

@keyframes tab-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.mode-switch {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.mode-switch button {
  border: none;
  background: var(--surface);
  color: var(--text-body);
  font-size: 13px;
  font-weight: 600;
  padding: 9px 16px;
  cursor: pointer;
}

.mode-switch button.active {
  background: var(--primary);
  color: #FFFFFF;
}

.context-grid {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.section-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
}

.section-pill {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-body);
  font-size: 12px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 999px;
  cursor: default;
}

.section-pill.active {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--bg);
}

.step-nav-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

.step-nav-select {
  flex: 1 1 260px;
  max-width: 420px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-heading);
}

.section-pill.filled::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
  margin-right: 6px;
}

.section-group {
  margin-bottom: 30px;
}

.section-group h2 {
  font-size: 16px;
  color: var(--primary);
  border-bottom: 1px solid var(--border);
  padding-bottom: 8px;
  margin-bottom: 16px;
}

.generator-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.generation-progress {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-muted, #f7f9f8);
  max-width: 420px;
}

.progress-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text-muted, #6b7280);
}

.progress-row.progress-done {
  color: var(--text, #1f2937);
}

.progress-row.progress-active,
.progress-row.progress-retrying {
  color: var(--primary);
  font-weight: 600;
}

.progress-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  font-size: 12px;
}

.progress-icon svg {
  width: 14px;
  height: 14px;
}

.progress-row.progress-done .progress-icon {
  color: var(--primary);
}

.progress-row.progress-active .progress-icon,
.progress-row.progress-retrying .progress-icon {
  animation: spin 1s linear infinite;
}

.progress-note {
  font-size: 12px;
  font-style: italic;
  opacity: 0.8;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.generator-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 32px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  flex-wrap: wrap;
}

hr.rule {
  border: none;
  border-top: 1px solid var(--border);
  margin: 28px 0;
}

.text-sm { font-size: 13px; }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.mb-0 { margin-bottom: 0; }
.flex { display: flex; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.gap-8 { gap: 8px; }
.gap-12 { gap: 12px; }
.two-col-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 860px) { .two-col-grid { grid-template-columns: 1fr; } }
[hidden] { display: none !important; }

/* A textured ink-green field instead of flat white or a trendy multi-stop
   gradient: one solid ground color, a faint dot grid for texture, and two
   soft flat-color rings for depth — nothing that shifts hue across the
   page. */
body.auth-page {
  position: relative;
  min-height: 100vh;
  background-color: #12271F;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Ccircle cx='2' cy='2' r='1.6' fill='%23FFFFFF' fill-opacity='0.08'/%3E%3C/svg%3E");
  overflow-x: hidden;
}

/* position:fixed (viewport-relative), not absolute (body-relative) — these
   are purely decorative full-viewport dressing, and an absolutely
   positioned circle bleeding past the body's own content-determined edge
   silently extends the page's scrollable area on any short viewport, even
   though nothing is actually visible in that extra space. Fixed positioning
   is excluded from document scroll size entirely, which is what a
   background decoration should be either way. */
body.auth-page::before,
body.auth-page::after {
  content: "";
  position: fixed;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}

body.auth-page::before {
  width: 620px;
  height: 620px;
  top: -220px;
  left: -220px;
  background: rgba(255, 255, 255, 0.035);
}

body.auth-page::after {
  width: 480px;
  height: 480px;
  bottom: -180px;
  right: -140px;
  background: rgba(184, 132, 46, 0.12);
}

.auth-shell {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 64px;
  padding: 40px;
}

.auth-illustration {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  flex: 1 1 420px;
  max-width: 480px;
}

.auth-illustration img {
  width: 100%;
  max-width: 280px;
  height: auto;
  filter: drop-shadow(0 18px 30px rgba(0, 0, 0, 0.25));
}

.auth-illustration .wordmark {
  font-size: 42px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #FFFFFF;
}

.auth-illustration .wordmark span {
  color: var(--accent);
}

.auth-illustration .tagline {
  margin: -12px 0 0;
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.72);
  text-align: center;
  max-width: 320px;
  line-height: 1.5;
}

.auth-panel {
  flex: 0 1 420px;
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border-radius: 20px;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.10);
  padding: 40px 36px;
}

.auth-panel h1 {
  font-size: 24px;
  margin-bottom: 6px;
}

.auth-panel .auth-subtitle {
  font-size: 14px;
  color: var(--text-body);
  margin-bottom: 28px;
}

.auth-panel .field {
  margin-bottom: 16px;
}

.auth-panel .field label {
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 6px;
}

.auth-panel input[type="text"],
.auth-panel input[type="email"],
.auth-panel input[type="password"] {
  padding: 12px 14px;
  border-radius: 10px;
  background: #FAFBFC;
}

.auth-row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 22px;
  font-size: 13px;
}

.auth-row-between a {
  font-weight: 600;
}

.auth-panel .btn-primary {
  border-radius: 10px;
  padding: 13px 18px;
  font-size: 15px;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0;
  color: var(--text-body);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Wraps every password input (login, signup, settings, admin account
   modal, ...) — see wirePasswordToggles() in api.js, which adds this
   wrapper and the toggle button to every password field on the page from
   one shared place. */
.password-field {
  position: relative;
}

.password-field input[type="password"],
.password-field input[type="text"] {
  padding-right: 42px;
}

.password-toggle-btn {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text-body);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.password-toggle-btn svg {
  width: 18px;
  height: 18px;
}

.password-toggle-btn:hover {
  color: var(--primary);
  background: var(--bg);
}

/* Width-independent: a short browser window (wide desktop layout included)
   needs the same "never scroll" treatment as a narrow one. Shrinks the
   illustration and the gap/padding around it rather than the form itself,
   so the fields stay full-size. */
@media (max-height: 700px) {
  .auth-shell {
    gap: 32px;
    padding: 24px 40px;
  }
  .auth-illustration {
    gap: 14px;
  }
  /* The form card is the taller of the two columns here, so the brand mark
     has slack to spend before it starts driving the page height — keep it
     at a readable size rather than shrinking it in step with the padding. */
  .auth-illustration img {
    max-width: 230px;
  }
  .auth-illustration .wordmark {
    font-size: 36px;
  }
  .auth-illustration .tagline {
    display: none;
  }
}

/* Only on a genuinely tiny window does the brand mark have to give way —
   and at that point the card's own padding and row spacing has to tighten
   too, since the card (not the illustration) is what sets the page height. */
@media (max-height: 520px) {
  .auth-shell {
    padding: 16px 40px;
  }
  .auth-illustration img {
    max-width: 150px;
  }
  .auth-illustration .wordmark {
    font-size: 26px;
  }
  .auth-panel {
    padding: 24px 32px;
  }
  .auth-panel .auth-subtitle {
    margin-bottom: 18px;
  }
  .auth-panel .field {
    margin-bottom: 10px;
  }
  .auth-row-between {
    margin-bottom: 14px;
  }
  .auth-divider {
    margin: 12px 0;
  }
}

@media (max-width: 900px) {
  .auth-shell {
    flex-direction: column;
    gap: 32px;
  }
  .auth-illustration img {
    max-width: 220px;
  }
  .auth-illustration .wordmark {
    font-size: 26px;
  }
}

/* At phone width, stacking the illustration above the form (the 900px rule
   above) pushes the actual login fields below the fold — the illustration
   alone can be taller than the viewport. Going back to a side-by-side row
   keeps the form in view immediately; the illustration just shrinks down to
   a small logo lockup (image + wordmark, tagline dropped) so it doesn't
   compete with the form for width. */
@media (max-width: 640px) {
  .auth-shell {
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 20px 16px;
  }
  .auth-illustration {
    flex: 0 0 auto;
    max-width: 84px;
    gap: 10px;
  }
  .auth-illustration img {
    max-width: 44px;
  }
  .auth-illustration .wordmark {
    font-size: 15px;
    text-align: center;
  }
  .auth-illustration .tagline {
    display: none;
  }
  .auth-panel {
    flex: 1 1 auto;
    max-width: none;
    min-width: 0;
    padding: 24px 18px;
  }
}

.scan-status {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  font-size: 14px;
  color: var(--text-heading);
  background: var(--bg);
}

.scan-status .spinner {
  border: 2px solid rgba(27, 110, 106, 0.25);
  border-top-color: var(--primary);
}

.setup-panel {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.generate-panel .mode-switch {
  margin-top: 4px;
}

.setup-panel .field {
  margin-bottom: 0;
}

.setup-panel .intake-grid {
  margin-bottom: 0;
}

.setup-intro h2 {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-heading);
  margin: 0 0 4px;
}

.setup-intro p {
  margin: 0;
  color: var(--text-body);
}

/* Each logical group (who/topic, course guide, optional details) is its own
   bordered "common region" so related fields read as one unit (proximity)
   and are clearly separated from unrelated groups. */
/* A headed group, not a card. These sit inside .section-card already, and
   boxing them again produced three nested borders around one form. Grouping
   comes from the heading plus the space around it; the rule only separates one
   group from the next. */
.setup-section + .setup-section {
  margin-top: 26px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
}

.setup-section-flush {
  border: none;
  background: transparent;
  padding: 0;
}

.setup-section-head {
  margin-bottom: 14px;
}

/* A short value does not need the full width of the form, and stretching it
   broke the two-column rhythm the rows above establish. */
.intake-grid .field select {
  max-width: 100%;
}

.setup-section-head h3 {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-heading);
  margin: 0 0 2px;
}

.setup-section-head p {
  font-size: 12px;
  color: var(--text-body);
  margin: 0;
}

.intake-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 18px;
}

.intake-grid .field.full-width {
  grid-column: 1 / -1;
}

.course-guide-picker {
  border: none;
  border-radius: var(--radius-sm);
  padding: 14px;
  background: var(--bg);
}

.course-guide-picker .cg-tabs {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 16px;
  background: var(--surface);
}

.course-guide-picker .cg-tabs button {
  border: none;
  background: var(--surface);
  color: var(--text-body);
  font-size: 12px;
  font-weight: 600;
  padding: 7px 14px;
  cursor: pointer;
  white-space: nowrap;
}

.course-guide-picker .cg-tabs button.active {
  background: var(--primary);
  color: #FFFFFF;
}

.cg-tab-content {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 16px;
}

.cg-search-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.cg-search-hint {
  margin: 0;
}

/* The two document pickers, one after the other, each with its own name. */
.guide-pickers {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.guide-picker-title {
  margin: 0 0 2px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text-heading);
}

.guide-picker-hint {
  margin: 0 0 12px;
}

/* A long result list scrolls inside its picker instead of pushing the next
   picker down the page. */
.cg-results {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 292px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

.cg-results:not(:empty) {
  margin-top: 14px;
}

/* Each result is a real button: full width, left-aligned, in the page's own
   type rather than the browser's button font. */
.cg-result-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  cursor: pointer;
  background: var(--surface);
  font: inherit;
  color: inherit;
  text-align: left;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.cg-result-card:hover {
  border-color: var(--primary);
}

.cg-result-card:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* The document in use: tinted, outlined in the brand green, and labelled
   with a check, so it reads as chosen at a glance in a list of near-identical
   titles. */
.cg-result-card.selected {
  border-color: var(--primary);
  background: var(--primary-tint);
  box-shadow: inset 0 0 0 1px var(--primary);
}

.cg-result-card .cg-title {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-heading);
}

.cg-result-card .cg-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--text-body);
}

.cg-result-card .cg-pick {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  color: var(--text-body);
}

.cg-result-card.selected .cg-pick {
  color: var(--primary);
  font-weight: 600;
}

.cg-result-card .cg-pick svg {
  width: 15px;
  height: 15px;
}

.cg-selected {
  margin-top: 12px;
}

.cg-selected-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--primary);
  background: var(--bg);
  color: var(--primary-hover);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
}

.cg-selected-chip svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.advanced-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 0;
}

.gate-lock {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: var(--space-7) var(--space-5);
  text-align: center;
  color: var(--text-body);
  font-size: var(--text-base);
}

.gate-lock p {
  max-width: 460px;
  margin: 0 auto var(--space-4);
}

@media (max-width: 640px) {
  .advanced-group-grid,
  .field-row-grid,
  .intake-grid {
    grid-template-columns: 1fr;
  }

  .topbar {
    padding: 12px 16px;
  }

  .main {
    padding: 28px 16px 64px;
  }
}

.dash-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

#announcement-banner-wrap {
  flex-shrink: 0;
}

.announcement-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 28px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}

.announcement-banner-label {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.6);
}

.announcement-banner-body {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  color: inherit;
}

.announcement-banner-body strong {
  color: inherit;
}

.announcement-banner-video {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---- A tutorial video on an announcement ---- */

.announcement-video {
  display: block;
  width: 100%;
  max-width: 640px;
  aspect-ratio: 16 / 9;
  margin-top: 10px;
  border-radius: var(--radius-sm);
  background: #000;
}

.video-tag,
.video-current {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-body);
}

.video-tag svg,
.video-current svg {
  width: 15px;
  height: 15px;
  color: var(--primary);
  flex: 0 0 auto;
}

.video-current {
  flex-wrap: wrap;
  margin: 0 0 8px;
  font-size: 13px;
  color: var(--text-heading);
}

.video-current[hidden] {
  display: none;
}

.upload-progress {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-body);
}

.upload-progress[hidden] {
  display: none;
}

.upload-progress-track {
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}

.upload-progress-bar {
  height: 100%;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.2s ease;
}

.announcement-banner-close {
  flex-shrink: 0;
  border: none;
  background: none;
  color: inherit;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.65;
  padding: 2px 4px;
}

.announcement-banner-close:hover {
  opacity: 1;
}

.announcement-info {
  background: #EAF3FF;
  color: #1D4E89;
}

.announcement-maintenance {
  background: var(--warning-bg);
  color: var(--warning-text);
}

.announcement-urgent {
  background: var(--danger-bg);
  color: var(--danger);
}

.dash-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 12px 28px;
  flex-shrink: 0;
  /* Sticky alongside the sidebar, so the sidebar can start below it
     (top: var(--topbar-h)) without the two overlapping once the page
     scrolls. Kept under .modal-overlay/.toast (100) and the phone drawer
     (210) so it never floats in front of them. */
  position: sticky;
  top: 0;
  z-index: 50;
}

.brand-block {
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand-block img {
  width: 46px;
  height: 46px;
  object-fit: contain;
  flex-shrink: 0;
}

.brand-block .brand-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--text-heading);
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.brand-block .brand-sub {
  font-size: 12px;
  color: var(--text-body);
  line-height: 1.2;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

.icon-btn {
  position: relative;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-body);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.icon-btn svg {
  width: 18px;
  height: 18px;
}

.icon-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
}

.sidebar-toggle-btn {
  display: inline-flex;
  flex-shrink: 0;
  margin-right: 6px;
}

/* ---- Sidebar collapse handle (ensureMobileSidebarToggle in icons.js) ----
   Pinned halfway down the sidebar's outer edge rather than sitting in the
   topbar, so the control reads as belonging to the panel it resizes. It is
   fixed to the viewport, not nested in .sidebar, because that panel is
   overflow-y:auto and would clip it — so its left offset has to track the
   sidebar's own width, in step with the width transition there. */
.sidebar-collapse-btn {
  display: none;
  position: fixed;
  top: calc(var(--topbar-h) + (100vh - var(--topbar-h)) / 2);
  /* Parked at the expanded sidebar's edge and moved by transform rather than
     by animating `left`, so the slide runs on the compositor instead of
     reflowing the page on every frame. --rail-shift is the distance between
     the expanded width and the collapsed rail. */
  left: 232px;
  --rail-shift: 0px;
  transform: translate(calc(-50% + var(--rail-shift)), -50%);
  z-index: 29;
  align-items: center;
  justify-content: center;
  /* 26px visual circle, but ::before pads the hit area out to the 24px
     minimum in every direction (44px total) for touch. */
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-body);
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(22, 35, 30, 0.12);
  transition: transform 0.18s ease, color 0.15s ease, border-color 0.15s ease;
}

.sidebar-collapse-btn::before {
  content: "";
  position: absolute;
  inset: -9px;
}

.sidebar-collapse-btn svg {
  width: 14px;
  height: 14px;
  transition: transform 0.18s ease;
}

.sidebar-collapse-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
}

/* The permanent icon rail below 861px is forced by width, not by the
   collapsed class, so the handle would do nothing there — it only appears
   at the widths where the sidebar can actually expand. The hamburger takes
   over below 641px for the off-canvas drawer. */
@media (min-width: 861px) {
  .sidebar-collapse-btn {
    display: inline-flex;
  }
  body.sidebar-collapsed .sidebar-collapse-btn {
    --rail-shift: -156px;
  }
  body.sidebar-collapsed .sidebar-collapse-btn svg {
    transform: rotate(180deg);
  }
}

@media (min-width: 641px) {
  .sidebar-toggle-btn {
    display: none;
  }
}

/* Desktop/tablet: collapse the sidebar to an icon rail
   (below 640px the hamburger opens the off-canvas drawer instead). */
@media (min-width: 641px) {
  body.sidebar-collapsed .sidebar {
    width: 76px;
    padding: 16px 8px;
  }
  body.sidebar-collapsed .sidebar-nav a span,
  body.sidebar-collapsed .sidebar-footer .who {
    display: none;
  }
  body.sidebar-collapsed .sidebar-nav a {
    justify-content: center;
    padding: 12px;
  }
  body.sidebar-collapsed .sidebar-footer {
    justify-content: center;
  }
}

.sidebar-backdrop {
  display: none;
}

.icon-btn .dot {
  position: absolute;
  top: 7px;
  right: 8px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #F59E0B;
  border: 1.5px solid var(--surface);
}

/* ---- Notification bell dropdown (wireNotificationBell in api.js) ---- */

.notif-menu {
  position: relative;
  display: inline-flex;
}

.notif-panel {
  position: absolute;
  top: 46px;
  right: 0;
  width: 320px;
  max-width: 80vw;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 28px rgba(31, 41, 55, 0.14), 0 2px 8px rgba(31, 41, 55, 0.06);
  z-index: 30;
  overflow: hidden;
}

.notif-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  font-weight: 700;
  color: var(--text-heading);
}

.notif-mark-all {
  background: none;
  border: none;
  color: var(--primary);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
}

.notif-mark-all:hover {
  text-decoration: underline;
}

.notif-list {
  max-height: 360px;
  overflow-y: auto;
}

.notif-item {
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}

.notif-item:last-child {
  border-bottom: none;
}

.notif-item:hover {
  background: var(--bg);
}

.notif-item.unread {
  background: var(--primary-tint);
}

.notif-item.unread:hover {
  background: var(--primary-tint);
  filter: brightness(0.97);
}

.notif-item-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-heading);
  display: flex;
  align-items: center;
  gap: 6px;
}

.notif-item.unread .notif-item-title::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

.notif-item-message {
  font-size: 12.5px;
  color: var(--text-body);
  margin-top: 2px;
  line-height: 1.4;
}

.notif-item-time {
  font-size: 11px;
  color: var(--text-body);
  opacity: 0.75;
  margin-top: 4px;
}

.notif-empty {
  padding: 24px 16px;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-body);
}

@media (max-width: 640px) {
  .notif-panel {
    right: -60px;
    width: 280px;
  }
}

.settings-panel-head {
  display: flex;
  align-items: center;
  gap: 16px;
}

.settings-avatar {
  width: 52px;
  height: 52px;
  font-size: 18px;
}

#profile-role-badge {
  margin-right: 8px;
}

#profile-member-since {
  color: var(--text-body);
}

.avatar-menu {
  position: relative;
}

.avatar-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 999px;
}

.avatar-btn:hover {
  background: var(--bg);
}

.avatar-btn svg {
  width: 14px;
  height: 14px;
  color: var(--text-body);
}

.avatar-chip {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--bg);
  color: var(--primary);
  font-weight: 700;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-transform: uppercase;
}

.avatar-dropdown {
  position: absolute;
  top: 46px;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 28px rgba(31, 41, 55, 0.14), 0 2px 8px rgba(31, 41, 55, 0.06);
  min-width: 200px;
  padding: 8px;
  display: none;
  z-index: 30;
}

.avatar-dropdown.open {
  display: block;
}

.avatar-dropdown .dd-user {
  padding: 6px 10px 12px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
}

.avatar-dropdown .dd-user strong {
  display: block;
  font-size: 13px;
  color: var(--text-heading);
}

.avatar-dropdown .dd-user span {
  font-size: 12px;
  color: var(--text-body);
}

.avatar-dropdown .dd-item {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  font-size: 13px;
  font-weight: 500;
  border-radius: 6px;
  background: none;
  border: none;
  color: var(--text-heading);
  cursor: pointer;
  text-align: left;
}

.avatar-dropdown .dd-item svg {
  width: 15px;
  height: 15px;
  color: var(--text-body);
  flex-shrink: 0;
}

.avatar-dropdown .dd-item:hover {
  background: var(--bg);
  color: var(--primary);
}

.avatar-dropdown .dd-item:hover svg {
  color: var(--primary);
}

.avatar-dropdown .dd-item.danger:hover {
  background: var(--danger-bg);
  color: var(--danger);
}

.avatar-dropdown .dd-item.danger:hover svg {
  color: var(--danger);
}

.dash-body {
  display: flex;
  flex: 1;
  min-height: 0;
}

.sidebar {
  width: 232px;
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 20px 14px;
  display: flex;
  flex-direction: column;
  /* The document scrolls, not .dash-main (.dash-shell is min-height:100vh, so
     a long page grows the whole shell), which used to carry the sidebar
     off-screen. align-self:flex-start stops the flex row stretching it to the
     full body height — that stretch is what would otherwise defeat sticky. */
  position: sticky;
  top: var(--topbar-h);
  align-self: flex-start;
  height: calc(100vh - var(--topbar-h));
  overflow-y: auto;
  transition: width 0.18s ease;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.sidebar-nav a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-body);
}

.sidebar-nav a:hover {
  background: var(--bg);
  color: var(--primary);
  text-decoration: none;
}

.sidebar-nav a.active {
  background: var(--bg);
  color: var(--primary);
}

.sidebar-nav a svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.sidebar-footer {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
}

.sidebar-footer .avatar-chip {
  width: 38px;
  height: 38px;
  font-size: 14px;
}

.sidebar-footer .who strong {
  display: block;
  font-size: 13px;
  color: var(--text-heading);
  line-height: 1.3;
}

.sidebar-footer .who span {
  font-size: 12px;
  color: var(--text-body);
  line-height: 1.3;
}

.dash-main {
  flex: 1;
  min-width: 0;
  padding: 28px 28px 60px;
  overflow-y: auto;
}

.dash-page-title {
  font-size: 20px;
  margin-bottom: 20px;
}

/* The illustration is a full-bleed backdrop rather than a boxed-off panel,
   so it reads as the banner itself instead of a photo placed inside it. A
   flat dark scrim (not a gradient) sits between the image and the text for
   general contrast, but the chalkboard art's own white icon linework is
   close enough to white text that a shadow alone isn't reliable — so the
   headline gets a solid chip behind it too, guaranteeing contrast no matter
   what part of the artwork lands behind it. */
.hero-banner {
  position: relative;
  border-radius: 20px;
  padding: 40px 44px;
  min-height: 240px;
  display: flex;
  align-items: center;
  margin-bottom: 28px;
  overflow: hidden;
}

.hero-image-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero-image-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(8, 18, 22, 0.68);
}

.hero-image-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.hero-text {
  position: relative;
  z-index: 1;
  max-width: 560px;
}

.hero-text h1 {
  display: inline-block;
  font-size: 32px;
  font-weight: 700;
  letter-spacing: 0.2px;
  margin-bottom: 26px;
  padding: 10px 20px;
  color: var(--text-heading);
  background: #FFFFFF;
  border-radius: 12px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.28);
}

.hero-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.hero-actions .btn {
  font-size: 15px;
  padding: 13px 22px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
}

.hero-actions .btn svg {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
}

/* A single ledger band, not a grid of repeated cards — the numbers carry
   the information, so there's nothing for an icon-in-a-tinted-square to add
   except visual noise. Segments read left to right like line items in a
   register. The 1px gap filled with the border color (rather than a
   border-left on every item but the first) draws a hairline between every
   pair of neighbors even once auto-fit wraps them onto a second row — a
   plain border-left would only ever separate items within one row. */
.stat-ledger {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 28px;
  overflow: hidden;
}

.stat-ledger-item {
  background: var(--surface);
  padding: 18px 24px;
}

.stat-ledger-value {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  color: var(--text-heading);
  line-height: 1.15;
}

.stat-ledger-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-heading);
  margin-top: 4px;
}

.stat-ledger-sub {
  font-size: 12px;
  color: var(--text-body);
  margin-top: 2px;
}

.dash-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 24px;
  align-items: start;
}

.section-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 20px 6px;
}

.section-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.section-card-header h2 {
  font-size: 16px;
}

.section-link {
  font-size: 13px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.data-table th {
  text-align: left;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-body);
  padding: 0 10px 10px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.data-table td {
  padding: 13px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text-heading);
  vertical-align: middle;
  /* Names and emails are user-supplied and can be a single unbroken 80
     character string, so a long word still breaks. break-word rather than
     anywhere: "anywhere" also lowers each column's minimum width to one
     character, which let a narrow screen squeeze titles to a letter per line
     instead of scrolling or stacking. */
  overflow-wrap: break-word;
}

/* Dates and counts are read down the column and compared, so the digits
   need to share a width. */
.data-table td:not(:first-child) {
  font-variant-numeric: tabular-nums;
}

.data-table tr:last-child td {
  border-bottom: none;
}

.plan-title-cell {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
}

.plan-title-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* A draft's progress under its title, so the list says what is left to do. */
.plan-progress {
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--text-body);
}

.row-actions .row-continue {
  margin-right: var(--space-1);
}

/* Right-aligned so the icon buttons line up down the column whether or not a
   row also has Continue. */
@media (min-width: 641px) {
  #plans-body .row-actions {
    justify-content: flex-end;
  }
}

/* On a phone card, Continue is the draft's main action: its own full-width
   line, with the icon actions wrapping underneath. */
@media (max-width: 640px) {
  #plans-body .row-actions {
    flex-wrap: wrap;
  }

  #plans-body .row-actions .row-continue {
    flex: 1 1 100%;
    margin-right: 0;
  }
}

.plan-title-cell .file-ico {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--bg);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.plan-title-cell .file-ico svg {
  width: 14px;
  height: 14px;
}

.row-menu {
  position: relative;
  display: inline-block;
}

.row-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  background: none;
  border: none;
  color: var(--text-body);
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  line-height: 1;
}

.row-menu-btn svg {
  width: 18px;
  height: 18px;
}

.row-menu-btn:hover {
  background: var(--bg);
  color: var(--primary);
}

.row-menu-dropdown {
  position: absolute;
  top: 30px;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 28px rgba(31, 41, 55, 0.14), 0 2px 8px rgba(31, 41, 55, 0.06);
  min-width: 150px;
  padding: 6px;
  display: none;
  z-index: 25;
}

.row-menu-dropdown.open {
  display: block;
}

.row-menu-dropdown button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 8px 10px;
  font-size: 13px;
  border-radius: 6px;
  color: var(--text-heading);
  cursor: pointer;
}

.row-menu-dropdown button:hover {
  background: var(--bg);
  color: var(--primary);
}

.row-menu-dropdown button.danger:hover {
  background: var(--danger-bg);
  color: var(--danger);
}

.row-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.row-action-btn {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-body);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.row-action-btn svg {
  width: 16px;
  height: 16px;
}

.row-action-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--bg);
}

.row-action-btn.danger:hover {
  border-color: var(--danger);
  color: var(--danger);
  background: var(--danger-bg);
}

.table-empty-row td {
  text-align: center;
  color: var(--text-body);
  padding: 30px 10px;
}

.modal-dialog {
  overscroll-behavior: contain;
}

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(31, 41, 55, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 100;
}

.modal-overlay[hidden] {
  display: none;
}

.modal-dialog {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: 0 24px 48px rgba(31, 41, 55, 0.22);
  width: 100%;
  max-width: 640px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 22px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.modal-header h2 {
  font-size: 17px;
  margin: 0;
  color: var(--text-heading);
}

.modal-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: none;
  color: var(--text-body);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-close:hover {
  background: var(--bg);
  color: var(--primary);
}

.modal-body {
  padding: 20px 22px;
  overflow-y: auto;
}

.preview-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  padding-bottom: 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-body);
}

.preview-meta strong {
  color: var(--text-heading);
}

.preview-section-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--primary);
  margin: 18px 0 8px;
}

.preview-section-title:first-child {
  margin-top: 0;
}

.preview-field {
  margin-bottom: 12px;
}

.preview-field-label {
  font-weight: 600;
  font-size: 13px;
  color: var(--text-heading);
  margin-bottom: 2px;
}

.preview-field-value {
  font-size: 13.5px;
  color: var(--text-body);
  white-space: pre-wrap;
}

.preview-field-value ul {
  margin: 4px 0 0;
  padding-left: 18px;
}

.preview-loading,
.preview-error {
  text-align: center;
  color: var(--text-body);
  padding: 30px 10px;
}

.preview-error {
  color: var(--danger);
}

/* ---- Lesson-plan document editor: mirrors the real reference .docx ---- */

.modal-dialog-doc {
  max-width: 920px;
}

.doc-toolbar-views {
  display: flex;
  gap: 6px;
}

.doc-view-btn {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-body);
  border-radius: var(--radius-sm);
  padding: 6px 12px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

.doc-view-btn.active {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--bg);
}

.doc-view-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.doc-warning {
  background: #FFF7ED;
  border: 1px solid #FDBA74;
  color: #9A3412;
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-size: 12.5px;
  line-height: 1.5;
  margin-bottom: 14px;
}

.doc-hint {
  font-size: 12.5px;
  color: var(--text-body);
  margin: -4px 0 14px;
}

.lp-doc-wrap {
  background: #E9EBEE;
  border-radius: var(--radius-sm);
  padding: 22px;
  max-height: 55vh;
  overflow: auto;
}

/* The page itself. Its width, margins and default text style come inline from
   the .docx (docx_layout.Layout), in points, so 100% zoom is the file's true
   size. Nothing here may set typography, spacing or borders, or the page
   stops looking like the file. */
.lp-doc {
  background: #fff;
  margin: 0 auto;
  box-shadow: 0 1px 3px rgba(31, 41, 55, 0.12), 0 8px 20px rgba(31, 41, 55, 0.08);
  color: #000;
  zoom: var(--doc-zoom, 1);
}

.lp-doc .lp-p {
  margin: 0;
  /* Word keeps runs of spaces, and its tabs stop every half inch. */
  white-space: pre-wrap;
  tab-size: 36pt;
  /* Pictures placed "in front of text" position against their paragraph. */
  position: relative;
}

/* A list number or bullet, hanging in the paragraph's indent the way Word
   draws it. Drawn here rather than written into the paragraph, so it is never
   read back and saved as typed text. */
.lp-doc .lp-p[data-marker]::before {
  content: attr(data-marker);
  display: inline-block;
  min-width: var(--lp-marker-w, 0);
  text-indent: 0;
  white-space: pre;
}

.lp-doc .lp-table {
  border-collapse: collapse;
}

.lp-doc .lp-td {
  padding: 0;
  vertical-align: top;
  overflow-wrap: break-word;
}

.lp-doc a {
  color: inherit;
  text-decoration: none;
}

.lp-doc img {
  max-width: none;
}

.lp-field {
  display: block;
  min-height: 18px;
  white-space: pre-wrap;
  border-radius: 3px;
}

/* These are contenteditable cells inside a document-like layout, where the
   default outline sits awkwardly over the page rules — but it has to be
   replaced, not just removed, or there is no caret context at all. */
.lp-field:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.lp-field-inline {
  display: inline;
}

.lp-field:empty::before {
  content: attr(data-placeholder);
  color: #9CA3AF;
  font-style: italic;
}

.lp-field[contenteditable="true"]:hover {
  background: #F3F4F6;
}

.lp-field[contenteditable="true"]:focus {
  background: #ECFDF5;
  box-shadow: 0 0 0 1px var(--primary) inset;
}

.lp-field.lp-filled {
  background: transparent;
}

/* ---- Guided mode: one field unlocked at a time ---- */

.lp-field.step-locked {
  pointer-events: none;
  cursor: not-allowed;
  border-radius: 3px;
  background: repeating-linear-gradient(135deg, #F3F4F6, #F3F4F6 6px, #E9EBEE 6px, #E9EBEE 12px);
}

/* The lock is icons.js's lock drawn in the body text colour, rather than an
   emoji that renders differently on every OS. */
.lp-field.step-locked:empty::before {
  content: "Locked. Finish the current field first.";
  padding-left: 20px;
  color: var(--text-body);
  font-style: italic;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355635B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") left center / 14px 14px no-repeat;
}

.lp-field.step-active {
  border-radius: 3px;
  background: #ECFDF5;
  box-shadow: 0 0 0 2px var(--primary) inset;
}

.field textarea.step-locked,
.field input.step-locked {
  cursor: not-allowed;
  background: repeating-linear-gradient(135deg, #F3F4F6, #F3F4F6 6px, #E9EBEE 6px, #E9EBEE 12px);
}

.field textarea.step-active,
.field input.step-active {
  box-shadow: 0 0 0 2px var(--primary) inset;
}

/* ---- Format builder: click-to-define document editor ---- */

#doc-field-editor {
  max-width: 1400px;
}

.doc-builder-layout {
  display: flex;
  gap: 20px;
  align-items: flex-start;
}

.doc-builder-canvas {
  flex: 1 1 auto;
  min-width: 0;
  height: 72vh;
  min-height: 360px;
  max-height: 90vh;
  resize: vertical;
}

.doc-builder-sidebar {
  flex: 0 0 260px;
  position: sticky;
  top: 16px;
}

.doc-builder-sidebar h3 {
  font-size: 13px;
  margin: 0 0 10px;
  color: var(--text-heading);
}

.doc-field-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 64vh;
  overflow-y: auto;
}

.doc-field-list-row {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  cursor: pointer;
  background: var(--surface);
}

.doc-field-list-row:hover {
  border-color: var(--primary);
  background: var(--bg);
}

.doc-field-list-info {
  flex: 1 1 auto;
  min-width: 0;
}

.doc-field-list-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-heading);
}

.doc-field-list-meta {
  font-size: 11.5px;
  color: var(--text-body);
  margin-top: 2px;
}

.doc-field-list-delete {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--text-body);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.doc-field-list-delete:hover {
  background: #FEE2E2;
  color: var(--danger);
}

.doc-builder-canvas .lp-anchor {
  cursor: pointer;
  border-radius: 3px;
  transition: background-color 0.1s ease;
}

.doc-builder-canvas .lp-anchor:hover {
  background: #ECFDF5;
  outline: 1px dashed var(--primary);
  outline-offset: 1px;
}

.doc-builder-canvas .lp-candidate {
  border-bottom: 1px dashed #9CA3AF;
}

.doc-builder-canvas .lp-anchor-defined {
  background: #D1FAE5;
  outline: 1px solid #059669;
  outline-offset: 1px;
}

/* ---- Edit-content mode: formatting toolbar + in-canvas previews ---- */

.doc-mode-hint {
  margin: 10px 0 12px;
}

/* One toolbar for both document screens. It wraps rather than pushing the
   document sideways, and every control is a 40px target. */
.doc-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  margin-bottom: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.doc-toolbar-group {
  display: flex;
  align-items: center;
  gap: 4px;
}

.doc-toolbar-sep {
  width: 1px;
  align-self: stretch;
  margin: 6px 4px;
  background: var(--border);
}

.doc-tool-btn {
  min-width: 40px;
  height: 40px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--text-heading);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.doc-tool-btn:focus-visible,
.doc-tool-select:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.doc-tool-btn svg {
  width: 20px;
  height: 20px;
}

.doc-tool-btn:hover {
  background: var(--bg);
}

.doc-tool-btn.active {
  background: var(--bg);
  border-color: var(--primary);
  color: var(--primary);
}

.doc-tool-btn.danger {
  color: var(--danger);
}

.doc-tool-btn.danger:hover {
  background: var(--danger-bg);
  border-color: var(--danger);
}

.doc-tool-select {
  height: 40px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 10px;
  font-size: 14px;
  background: var(--surface);
  color: var(--text-heading);
}

.doc-toolbar-save {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: 4px;
}

.doc-builder-canvas.doc-edit-active {
  outline: 2px solid var(--primary);
  outline-offset: -1px;
  cursor: text;
}

.doc-builder-canvas .doc-preview-h1 {
  font-size: 1.55em;
  font-weight: 700;
}

.doc-builder-canvas .doc-preview-h2 {
  font-size: 1.3em;
  font-weight: 700;
}

.doc-builder-canvas .doc-preview-h3 {
  font-size: 1.12em;
  font-weight: 700;
}

.doc-builder-canvas .doc-preview-bullet,
.doc-builder-canvas .doc-preview-number {
  padding-left: 1.4em;
  position: relative;
}

.doc-builder-canvas .doc-preview-bullet::before {
  content: "•";
  position: absolute;
  left: 0.35em;
}

.doc-builder-canvas .doc-preview-number::before {
  content: "1.";
  position: absolute;
  left: 0;
}

.doc-builder-canvas .doc-marked-delete {
  text-decoration: line-through;
  opacity: 0.45;
  background: var(--danger-bg);
}

@media (max-width: 860px) {
  .doc-builder-layout {
    flex-direction: column;
  }
  .doc-builder-sidebar {
    flex: 1 1 auto;
    width: 100%;
    position: static;
  }
  .doc-toolbar-save {
    width: 100%;
    justify-content: space-between;
    margin-left: 0;
    margin-top: 4px;
  }
}

.widget-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 20px;
}

.widget-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.widget-header .icon-badge {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--bg);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.widget-header .icon-badge svg {
  width: 15px;
  height: 15px;
}

.widget-header h3 {
  font-size: 14px;
}

.todo-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  font-size: 13px;
  color: var(--text-heading);
  border-bottom: 1px solid var(--border);
}

.todo-item:last-child {
  border-bottom: none;
}

.todo-item input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--primary);
  flex-shrink: 0;
}

.todo-item span {
  flex: 1;
}

.todo-item.done span {
  text-decoration: line-through;
  color: var(--text-body);
}

.todo-empty {
  font-size: 13px;
  color: var(--text-body);
  padding: 4px 0 8px;
}

.tip-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  padding: 6px 0;
  color: var(--text-heading);
  line-height: 1.4;
}

.tip-item svg {
  width: 15px;
  height: 15px;
  color: var(--primary);
  flex-shrink: 0;
  margin-top: 1px;
}

@media (max-width: 1080px) {
  .dash-grid {
    grid-template-columns: 1fr;
  }
  .stats-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 860px) {
  .sidebar {
    width: 76px;
    padding: 16px 8px;
  }
  .sidebar-nav a span,
  .sidebar-footer .who {
    display: none;
  }
  .sidebar-nav a {
    justify-content: center;
    padding: 12px;
  }
  .sidebar-footer {
    justify-content: center;
  }
  .hero-banner {
    padding: 32px 28px;
    min-height: 0;
  }
}

@media (max-width: 640px) {
  .dash-topbar {
    padding: 12px 16px;
  }
  .dash-main {
    padding: 20px 16px 48px;
  }
  .stats-grid {
    grid-template-columns: 1fr;
  }
  .hero-banner {
    padding: 24px;
  }
  /* A fixed minmax() floor can force a card grid narrower than the phone's
     remaining width (after the icon-only sidebar) to overflow horizontally.
     A single flexible column has no such floor. */
  .card-grid,
  .class-card-grid {
    grid-template-columns: 1fr;
  }

  /* Below the tablet icon-rail breakpoint, the sidebar becomes a full
     off-canvas drawer instead — there just isn't room for even a slim
     always-on rail next to usable content on a phone screen. It's taken
     out of the flex flow entirely (position:fixed) so .dash-main reclaims
     the full width when the drawer is closed, which is the default. */
  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    /* Undo the sticky rail's sizing: the calc() height would over-constrain
       a top+bottom pinned drawer, and align-self:flex-start still applies to
       an out-of-flow flex child, shrinking it to its content height instead
       of letting top:0/bottom:0 stretch it to the full screen. */
    height: auto;
    align-self: stretch;
    z-index: 210;
    width: 250px;
    max-width: 82vw;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: none;
  }

  .sidebar.open {
    transform: translateX(0);
    box-shadow: 12px 0 32px rgba(22, 35, 30, 0.22);
  }

  /* The icon-rail rules above (max-width:860px) strip the text labels and
     center everything for a slim always-visible rail — none of that applies
     to an expanded slide-in drawer, so restore the normal, fully-labeled
     nav layout here. */
  .sidebar-nav a span,
  .sidebar-footer .who {
    display: block;
  }
  .sidebar-nav a {
    justify-content: flex-start;
    padding: 10px 12px;
  }
  .sidebar-footer {
    justify-content: flex-start;
  }

  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: 205;
    background: rgba(15, 23, 18, 0.45);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .sidebar-backdrop.open {
    display: block;
    opacity: 1;
    pointer-events: auto;
  }

  body.sidebar-lock-scroll {
    overflow: hidden;
  }

  /* Two tab buttons with long labels ("Search the shared library") don't
     fit an inline-flex row at phone width — split them into an even,
     wrapping pair instead of letting the row overflow the card. */
  .course-guide-picker .cg-tabs {
    display: flex;
    width: 100%;
  }
  .course-guide-picker .cg-tabs button {
    flex: 1 1 0;
    white-space: normal;
    text-align: center;
    padding: 8px 6px;
  }

  /* .page-header itself already wraps its own direct children (the title
     and the action-button group) onto separate lines, but the button group
     is a plain, non-wrapping .flex row internally — with three real button
     labels (e.g. the admin dashboard's "View documents" / "Announcements" /
     "Manage users") that still overflows the viewport at phone width. */
  .page-header .flex {
    flex-wrap: wrap;
  }
}

/* ---- Sections & submissions (teacher/student classroom features) ---- */

.class-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

.class-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  background: var(--surface);
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.class-card:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
}

.class-card h3 {
  font-size: 16px;
  margin-bottom: 4px;
}

.class-card .class-meta {
  font-size: 12px;
  color: var(--text-body);
  margin-bottom: 12px;
}

.class-card .class-stats {
  display: flex;
  gap: 14px;
  font-size: 12px;
  color: var(--text-body);
}

.class-card .class-stats strong {
  color: var(--text-heading);
  font-size: 14px;
  display: block;
}

.join-code-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--primary);
  background: var(--bg);
  border: 1px dashed var(--primary);
  border-radius: var(--radius-sm);
  padding: 4px 10px;
}

.join-code-display {
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 34px;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--primary);
  background: var(--bg);
  border: 1px dashed var(--primary);
  border-radius: var(--radius);
  padding: 18px 20px;
  text-align: center;
}

.status-pill {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}

.status-pill.draft {
  background: var(--bg);
  color: var(--text-body);
}

.status-pill.submitted {
  background: var(--warning-bg);
  color: var(--warning-text);
}

.status-pill.reviewed {
  background: #E3F7E9;
  color: #1A7A3D;
}

.score-row {
  margin-top: 10px;
}

.score-pill {
  display: inline-block;
  font-size: 13px;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: 999px;
}

.score-pill.score-great {
  background: #E3F7E9;
  color: #1A7A3D;
}

.score-pill.score-good {
  background: #E6F4F1;
  color: var(--primary);
}

.score-pill.score-ok {
  background: var(--warning-bg);
  color: var(--warning-text);
}

.score-pill.score-low {
  background: var(--danger-bg);
  color: var(--danger);
}

.roster-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

.roster-row:last-child {
  border-bottom: none;
}

.roster-who strong {
  display: block;
  font-size: 13px;
  color: var(--text-heading);
}

.roster-who span {
  font-size: 12px;
  color: var(--text-body);
}

.submission-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  background: var(--surface);
  margin-bottom: 14px;
}

.submission-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.submission-card-header h3 {
  font-size: 15px;
  margin-bottom: 2px;
}

.submission-meta {
  font-size: 12px;
  color: var(--text-body);
}

.feedback-box {
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 13px;
  color: var(--text-heading);
  margin-top: 10px;
}

/* ---- Page transition: a brief full-screen mask shown while navigating
   between pages (this is a multi-page app — every sidebar click is a real
   navigation) and while the destination page's first data fetch is still in
   flight, so the reflow as the sidebar/banner settle into place happens
   behind a curtain instead of in view. Kept deliberately short (see the
   MIN_MS/MAX_MS constants in api.js) — it's meant to smooth over a few
   hundred milliseconds, not add a real loading step. ---- */
.page-transition {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  opacity: 1;
  transition: opacity 0.16s ease;
}

.page-transition.page-transition-hide {
  opacity: 0;
  pointer-events: none;
}

/* Alan with his lesson plan. A slow, small bob reads as calm work rather
   than impatience; the loader is on screen only for a moment. */
.page-transition img {
  width: 88px;
  height: auto;
  animation: page-transition-bob 1.6s ease-in-out infinite;
}

@keyframes page-transition-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.page-transition span {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-body);
}

@media (prefers-reduced-motion: reduce) {
  .page-transition img { animation: none; }
}

/* ---- Guide owl: a companion that reacts to where you are in building the
   lesson plan, not a static piece of decoration. Fixed in the corner so it
   never competes with the form for layout space; pointer-events is off so
   it can never sit in front of something clickable. ---- */
/* ---- Alan, the guide owl ----
   Injected by OwlGuide in api.js, so every page gets it without its own
   markup. It opens each step of format building and lesson plan making with
   one fixed line, then leaves after five seconds — the guided-mode chat is
   what answers questions; this only says where you are. Draggable, because
   the one corner it can sit in is sometimes the corner you need. */
.owl-guide {
  position: fixed;
  right: 28px;
  bottom: 20px;
  z-index: 40;
  display: flex;
  align-items: flex-end;
  gap: 10px;
  max-width: min(420px, calc(100vw - 32px));
  /* Moved by --owl-x/--owl-y so dragging runs on the compositor and never
     reflows the page underneath. */
  transform: translate(var(--owl-x, 0px), var(--owl-y, 0px));
  transition: opacity 0.2s ease;
  /* The container itself never takes pointer events, so the empty space
     around the owl and his bubble cannot swallow a click meant for the page
     underneath. The two children opt back in individually. */
  pointer-events: none;
}

.owl-guide[hidden] {
  display: none;
}

.owl-guide.is-dragging {
  transition: none;
}

.owl-guide.is-dragging .owl-guide-img {
  cursor: grabbing;
}

.owl-guide.is-leaving {
  opacity: 0;
}

/* The owl is the handle: you drag him, not his speech bubble. His artwork is
   cropped tight to the drawing, so the area that responds is the owl you can
   see. */
.owl-guide-img {
  width: 150px;
  height: auto;
  flex-shrink: 0;
  filter: drop-shadow(0 8px 14px rgba(22, 35, 30, 0.2));
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
}

.owl-guide-bubble {
  position: relative;
  /* Takes pointer events for its close button and to hold the dismiss timer
     while the message is being read — but it is not a drag handle, so the
     text stays selectable. */
  pointer-events: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 11px 34px 11px 15px;
  margin-bottom: 56px;
  box-shadow: var(--shadow);
}

.owl-guide-bubble::after {
  content: "";
  position: absolute;
  bottom: -7px;
  right: 26px;
  width: 13px;
  height: 13px;
  background: var(--surface);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  transform: rotate(45deg);
}

.owl-guide-bubble p {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-heading);
}

.owl-guide-close {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-body);
  cursor: pointer;
  line-height: 1;
}

.owl-guide-close svg {
  width: 13px;
  height: 13px;
}

.owl-guide-close:hover {
  background: var(--bg);
  color: var(--text-heading);
}

/* The bubble is small, so the visible X stays 24px but its hit area is
   padded out to the 44px touch minimum. */
.owl-guide-close::before {
  content: "";
  position: absolute;
  inset: -10px;
}

@media (max-width: 640px) {
  /* At phone width there is no corner it can sit in without covering a field
     or the primary button, and its line always repeats text already on the
     page, so it stays out of the way entirely. */
  .owl-guide {
    display: none;
  }
}

/* ---- Guided mode: chat with the owl ----
   A docked conversation in the corner, so it stays in reach while the
   teacher scrolls through the document they're filling in. */
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Width is a custom property because two things depend on it: the panel
   itself, and the right-hand padding .dash-main uses to keep the document
   clear of it. The user's chosen width is restored from localStorage in
   generator.js. */
:root {
  --owl-chat-w: 460px;
}

/* The document and the open chat share one row: the chat is a column beside
   the plan, never a panel over it. The document side takes what is left and
   its Fit zoom follows (doc-toolbar.js watches the panel's size). */
/* Wraps rather than squeezing: when the panel can't hold both, the chat
   drops under the plan. Decided by the panel's own width (a container query
   below), not the window's, since the sidebar takes a share of the window. */
.doc-chat-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 20px;
  container-type: inline-size;
}

.doc-chat-main {
  flex: 1 1 480px;
  min-width: 0;
}

/* Sticky, so it stays beside whatever part of the plan is on screen, and
   never taller than the space under the sticky top bar, which would
   otherwise cover the chat's header and its Hide button. */
.owl-chat {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  flex: 0 0 var(--owl-chat-w);
  display: flex;
  flex-direction: column;
  width: var(--owl-chat-w);
  height: min(760px, calc(100vh - var(--topbar-h) - 32px));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 2px 6px rgba(22, 35, 30, 0.06);
  overflow: hidden;
}

/* Too narrow for the plan (480px at least) and the chat side by side: the
   chat opens under the plan, full width. */
@container (max-width: 900px) {
  .owl-chat {
    position: static;
    flex: 1 1 100%;
    width: 100%;
    height: min(70vh, 640px);
  }

  .owl-chat-resizer {
    display: none;
  }
}

/* Minimized: the chat is gone entirely and only Alan is left on screen.
   Clicking him brings it back (see OwlGuide.dock). */
.owl-chat.is-collapsed {
  display: none;
}

/* A reply waiting behind the collapsed bar: an amber dot on Open, the one
   colour this app reserves for "look here". */
.owl-chat-toggle {
  position: relative;
}

body.owl-chat-shown .dash-main {
  padding-bottom: 140px;
}

/* ---- The docked owl: a companion beside the chat in Guided mode ---- */
.owl-guide.is-docked {
  z-index: 56;
}

.owl-guide-figure {
  position: relative;
  display: block;
  flex-shrink: 0;
}

.owl-guide.is-docked .owl-guide-img {
  width: 96px;
  cursor: pointer;
}

/* Docked, Alan is the chat's open/close control, so he takes focus like one. */
.owl-guide.is-docked:focus-visible {
  outline: none;
}

.owl-guide.is-docked:focus-visible .owl-guide-figure {
  outline: 3px solid var(--primary);
  outline-offset: 4px;
  border-radius: 50%;
}

/* A reply that arrived while the chat was minimized. */
.owl-guide.has-unread .owl-guide-figure::after {
  content: "";
  position: absolute;
  top: 6px;
  right: 6px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #FFFFFF;
}

@media (max-width: 640px) {
  /* The transient guide stays hidden on phones; in Guided mode he sits
     beside the chat bar, smaller. */
  .owl-guide.is-docked {
    display: flex;
    right: 12px;
    bottom: 12px;
  }

  .owl-guide.is-docked .owl-guide-img {
    width: 64px;
  }
}

/* The panel is anchored to the right edge, so it grows leftwards and the
   grab strip has to live on its left side. Native `resize` cannot do this:
   it only ever drags the bottom-right corner, which here runs off-screen. */
.owl-chat-resizer {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 10px;
  z-index: 2;
  cursor: ew-resize;
  touch-action: none;
}

.owl-chat-resizer::after {
  content: "";
  position: absolute;
  left: 3px;
  top: 50%;
  width: 3px;
  height: 46px;
  margin-top: -23px;
  border-radius: 999px;
  background: var(--border);
  transition: background 0.15s ease;
}

.owl-chat-resizer:hover::after,
.owl-chat-resizer:focus-visible::after,
.owl-chat.is-resizing .owl-chat-resizer::after {
  background: var(--primary);
}

.owl-chat.is-resizing {
  user-select: none;
}

.owl-chat-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px 10px 10px;
  background: var(--primary);
  color: #FFFFFF;
}

.owl-chat-avatar {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
  background: #FFFFFF;
  border-radius: 50%;
  padding: 3px;
}

.owl-chat-title {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}

.owl-chat-title strong {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
}

.owl-chat-title span {
  font-size: 12px;
  opacity: 0.85;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.owl-chat-toggle {
  border: 1px solid rgba(255, 255, 255, 0.4);
  background: transparent;
  color: #FFFFFF;
  border-radius: 999px;
  padding: 4px 12px;
  min-height: 32px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  flex-shrink: 0;
}

.owl-chat-toggle:hover { background: rgba(255, 255, 255, 0.14); }

.owl-chat-body {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}


.owl-chat-log {
  flex: 1;
  min-height: 180px;
  overflow-y: auto;
  padding: 14px 12px 6px;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  gap: 10px;
  overscroll-behavior: contain;
}

.owl-chat-history {
  flex: 1;
  min-height: 180px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

.owl-chat-history-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-body);
  background: var(--surface);
  position: sticky;
  top: 0;
}

.owl-chat-back {
  border: 0;
  background: transparent;
  color: var(--primary);
  font: inherit;
  cursor: pointer;
  padding: 0;
}

.owl-chat-history-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
}

.owl-chat-thread-btn {
  text-align: left;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  cursor: pointer;
  font: inherit;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.owl-chat-thread-btn:hover {
  border-color: var(--primary);
}

.owl-chat-thread-btn strong {
  font-size: 13px;
  color: var(--text-heading);
}

.owl-chat-thread-btn span {
  font-size: 12px;
  color: var(--text-body);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.owl-chat-history-empty {
  padding: 26px 16px;
  text-align: center;
  font-size: 13px;
  color: var(--text-body);
}

.owl-msg { display: flex; gap: 8px; align-items: flex-end; max-width: 100%; }
.owl-msg-teacher { justify-content: flex-end; }

.owl-msg-avatar {
  width: 30px;
  height: 30px;
  object-fit: contain;
  flex-shrink: 0;
  align-self: flex-start;
}

.owl-msg-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; max-width: calc(100% - 38px); }

.owl-bubble {
  padding: 9px 12px;
  border-radius: 14px;
  font-size: 13.5px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.owl-msg-owl .owl-bubble {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top-left-radius: 4px;
  color: var(--text-heading);
}

.owl-msg-teacher .owl-bubble {
  max-width: 82%;
  background: var(--primary);
  color: #FFFFFF;
  border-bottom-right-radius: 4px;
}

.owl-msg.is-error .owl-bubble {
  background: var(--danger-bg);
  border-color: transparent;
  color: var(--danger);
}

.owl-choices { display: flex; flex-direction: column; gap: 6px; }

.owl-choice {
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 12px;
  transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}

.owl-choice-ask {
  align-self: flex-start;
  padding: 6px 12px;
  border: 1px solid var(--primary);
  border-radius: 999px;
  background: var(--surface);
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
}

.owl-choice-ask:hover:not(:disabled) { background: var(--primary-tint); }

.owl-choice-use {
  display: grid;
  gap: 3px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-body);
}

.owl-choice-use:hover:not(:disabled) { border-color: var(--primary); background: var(--primary-tint); }

.owl-choice-label { font-size: 13px; font-weight: 700; color: var(--text-heading); }

.owl-choice-text {
  font-size: 12.5px;
  line-height: 1.4;
  white-space: pre-wrap;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.owl-choice-action { font-size: 12px; font-weight: 700; color: var(--primary); }

.owl-choice:disabled { cursor: default; opacity: 0.55; }
.owl-choice.is-used { opacity: 1; border-color: var(--primary); background: var(--primary-tint); }
.owl-choice.is-used .owl-choice-action { color: var(--primary-hover); }

.owl-chat-note {
  align-self: center;
  max-width: 90%;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--primary-tint);
  color: var(--primary-hover);
  font-size: 12px;
  text-align: center;
}

.owl-dots { display: inline-flex; gap: 4px; padding: 3px 0; }
.owl-dots i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-body);
  opacity: 0.35;
  animation: owl-dot 1.1s ease-in-out infinite;
}
.owl-dots i:nth-child(2) { animation-delay: 0.15s; }
.owl-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes owl-dot { 0%, 80%, 100% { opacity: 0.3; transform: translateY(0); } 40% { opacity: 0.9; transform: translateY(-3px); } }

.owl-chat-form {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  background: var(--surface);
}

.owl-chat-form input {
  flex: 1;
  min-width: 0;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font: inherit;
  font-size: 14px;
  color: var(--text-heading);
}

.owl-chat-form input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-tint); }
.owl-chat-form .btn { border-radius: 999px; }

@media (prefers-reduced-motion: reduce) {
  .owl-dots i { animation: none; opacity: 0.6; }
}

/* ---------------------------------------------------------------------------
   Bulk selection (admin accounts + sections tables)
   --------------------------------------------------------------------------- */

.bulk-cell {
  width: 34px;
  padding-right: 0 !important;
}

.bulk-cell input[type="checkbox"],
.bulk-select-all {
  width: 15px;
  height: 15px;
  accent-color: var(--primary);
  cursor: pointer;
  margin: 0;
  vertical-align: middle;
}

.bulk-select-all:disabled {
  cursor: default;
  opacity: 0.4;
}

.data-table tr.is-selected td {
  background: var(--primary-tint);
}

/* Sits above the table and only appears once something is ticked, so the
   table reads normally until there is actually a batch to act on. A complete
   border on all four sides — the selected-count text carries the state, not a
   coloured edge. */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 14px;
  background: var(--primary-tint);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.bulk-bar-count {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-heading);
  font-variant-numeric: tabular-nums;
}

.bulk-bar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-left: auto;
}

@media (max-width: 640px) {
  .bulk-bar-actions {
    margin-left: 0;
    width: 100%;
  }
}

/* ---------------------------------------------------------------------------
   Fields the AI could not fill
   --------------------------------------------------------------------------- */

/* Marks the fields named in the "couldn't be generated" message so they can be
   found without hunting. A complete border on all four sides plus a tinted
   fill; the state is never carried by colour alone, since the same fields are
   listed by name in the message above. */
.field-needs-answer {
  border: 1px solid var(--warning-text) !important;
  background: var(--warning-bg) !important;
  border-radius: var(--radius-sm);
}

/* In the live document the slot is a contenteditable span rather than a form
   control, so it needs the padding to show the tint at all. */
.lp-doc .field-needs-answer {
  padding: 1px 4px;
}

/* ---------------------------------------------------------------------------
   Shared document toolbar: zoom, fullscreen, colour menus, and the fixed
   size/colour vocabulary that the Word export also understands.
   --------------------------------------------------------------------------- */

.doc-tool-menu-wrap {
  position: relative;
  display: inline-flex;
}

.doc-color-menu {
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  z-index: 30;
  min-width: 132px;
  padding: 5px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 18px rgba(22, 35, 30, 0.16);
}

.doc-color-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 36px;
  padding: 6px 10px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13.5px;
  color: var(--text-heading);
  text-align: left;
  cursor: pointer;
}

.doc-color-option:hover {
  background: var(--primary-tint);
}

.doc-color-swatch {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  border: 1px solid var(--border);
  border-radius: 3px;
}

.doc-zoom-readout {
  min-width: 56px;
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Zoom scales the page with CSS zoom, which rescales layout as well as
   drawing, so scroll size, caret and selection stay right at any scale.
   doc-toolbar.js and fitDocPage() set --doc-zoom; the wrapper scrolls both
   ways once the page is wider than it. */
.lp-doc-wrap {
  --doc-zoom: 1;
}

/* --- The fixed formatting vocabulary ---
   Every one of these class names is preserved by the field sanitizer and turned
   into a real Word run property on export, so nothing a teacher applies here is
   lost when the plan leaves the browser. Free-form inline styles are not kept,
   which is why the choices are a closed set. */

.lp-doc .fs-sm,
.doc-builder-canvas .fs-sm { font-size: 0.85em; }
.lp-doc .fs-md,
.doc-builder-canvas .fs-md { font-size: 1em; }
.lp-doc .fs-lg,
.doc-builder-canvas .fs-lg { font-size: 1.2em; }
.lp-doc .fs-xl,
.doc-builder-canvas .fs-xl { font-size: 1.45em; }

.lp-doc .fc-default,
.doc-builder-canvas .fc-default { color: #16231E; }
.lp-doc .fc-red,
.doc-builder-canvas .fc-red { color: #AB3524; }
.lp-doc .fc-amber,
.doc-builder-canvas .fc-amber { color: #B8842E; }
.lp-doc .fc-green,
.doc-builder-canvas .fc-green { color: #1C5C4E; }
.lp-doc .fc-blue,
.doc-builder-canvas .fc-blue { color: #1D4ED8; }

.lp-doc .hl-none,
.doc-builder-canvas .hl-none { background: transparent; }
.lp-doc .hl-yellow,
.doc-builder-canvas .hl-yellow { background: #FDE68A; }
.lp-doc .hl-green,
.doc-builder-canvas .hl-green { background: #BBF7D0; }
.lp-doc .hl-cyan,
.doc-builder-canvas .hl-cyan { background: #A5F3FC; }

/* ---------------------------------------------------------------------------
   Document stage: toolbar plus canvas, and the unit that goes fullscreen
   --------------------------------------------------------------------------- */

.doc-stage {
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin-top: 16px;
}

/* Sticky rather than fixed, so the toolbar stays reachable while the document
   scrolls under it both on the page and in fullscreen. */
.doc-stage .doc-toolbar {
  position: sticky;
  top: 0;
  z-index: 20;
  margin-top: 0;
  background: var(--surface);
}

/* In fullscreen the stage IS the screen, so it supplies the page ground and
   owns the scrolling; the canvas inside it scrolls, the toolbar does not. */
.doc-stage:fullscreen {
  padding: 0;
  background: var(--bg);
}

/* The base .lp-doc-wrap rule caps the canvas at 55vh and gives it a grey
   card background/radius so it doesn't dominate the normal page. Fullscreen
   is exactly the case where that cap must not apply, so every property the
   base rule sets that would otherwise clamp or frame the canvas has to be
   reset here explicitly — flex/overflow/padding alone cannot override a
   sibling property like max-height. */
.doc-stage:fullscreen .lp-doc-wrap {
  flex: 1;
  overflow: auto;
  padding: 24px;
  margin: 0;
  max-height: none;
  background: var(--bg);
  border-radius: 0;
}

.doc-stage.is-pseudo-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 1000;
  margin: 0;
  background: var(--bg);
}

.doc-stage.is-pseudo-fullscreen .lp-doc-wrap {
  flex: 1;
  overflow: auto;
  padding: 24px;
  margin: 0;
  max-height: none;
  background: var(--bg);
  border-radius: 0;
}

/* ---------------------------------------------------------------------------
   Format builder: which mode writes each field
   --------------------------------------------------------------------------- */

.field-roles-panel {
  padding: 16px;
  margin-top: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.field-roles-title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-heading);
}

.field-role-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
}

.field-role-row:last-child {
  border-bottom: none;
}

.field-role-label {
  flex: 1;
  font-size: 13px;
  color: var(--text-heading);
  overflow-wrap: anywhere;
}

.field-role-select {
  flex: 0 0 auto;
  max-width: 240px;
}

@media (max-width: 560px) {
  .field-role-row {
    flex-direction: column;
    align-items: stretch;
    gap: 5px;
  }

  .field-role-select {
    max-width: none;
  }
}

/* ---------------------------------------------------------------------------
   Layout pass: placeholder contrast, checklist density, toolbar on a phone
   --------------------------------------------------------------------------- */

/* Placeholders were #9CA3AF on white, 2.54:1 against a 4.5:1 requirement, so
   the example text in every field was failing contrast. Tinted from the body
   ink rather than a flat gray, and measured at 4.6:1. */
/* The toolbar carries 21 controls. On a narrow screen it was wrapping into five
   rows, 188px of chrome before the document appeared, with every target under
   32px. It now scrolls sideways as one row and the targets meet 36px, which is
   the ordinary pattern for an editor toolbar and keeps the document in view.
   The page itself still never scrolls sideways. */
@media (max-width: 720px) {
  .doc-stage .doc-toolbar {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
    /* Room for the scrollbar so it cannot sit on top of the last control. */
    padding-bottom: 8px;
  }

  .doc-toolbar-group {
    flex: 0 0 auto;
  }

  .doc-tool-btn {
    min-width: 36px;
    min-height: 36px;
  }

  .doc-tool-select {
    min-height: 36px;
  }
}

/* Icon spans sit next to label text in links and buttons. Without an explicit
   size the inline SVG collapses and the control loses its arrow entirely. */
.back-link,
.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.back-link [data-icon] svg,
.btn [data-icon] svg {
  width: 15px;
  height: 15px;
  display: block;
}

.back-link [data-icon],
.btn [data-icon] {
  display: inline-flex;
  flex: 0 0 auto;
}

/* ---------------------------------------------------------------------------
   Whole-document editing
   --------------------------------------------------------------------------- */

/* The document body is the teacher's to edit, so the caret has to be welcome
   anywhere in it, not only in the AI's slots. */
.lp-doc [data-anchor-index] {
  cursor: text;
}

.lp-doc [data-anchor-index]:focus,
.lp-doc [data-anchor-index]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
  border-radius: 2px;
}

/* The AI's slots stay marked so it is obvious which parts regenerating will
   overwrite. A tint rather than a box, since everything around them is now
   editable too and boxing the slots would imply the rest is not. */
.lp-doc .lp-field {
  background: var(--primary-tint);
  border-radius: 3px;
}

.lp-doc .lp-field.lp-filled {
  background: transparent;
  box-shadow: inset 0 -1px 0 var(--primary-tint);
}

/* ---------------------------------------------------------------------------
   Shared layout pass (2026-09-25)
   --------------------------------------------------------------------------- */

/* ---- Create Lesson Plan: three shelves of formats ---- */
.format-section {
  margin-top: var(--space-7);
}

.format-section:first-of-type {
  margin-top: var(--space-5);
}

.format-section-head {
  margin-bottom: var(--space-3);
}

.section-title {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-heading);
  margin: 0;
}

.section-note {
  font-size: var(--text-sm);
  color: var(--text-body);
  margin: var(--space-1) 0 0;
  max-width: 640px;
}

/* Search sits in the header beside New format rather than on a row of its
   own, so the formats start higher up the page. */
.format-search {
  position: relative;
  flex: 0 0 auto;
  width: 260px;
}

.format-search input {
  min-height: var(--control-h);
  padding-left: 36px;
}

.format-search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  color: var(--text-body);
  pointer-events: none;
}

.format-search-icon svg {
  width: 16px;
  height: 16px;
}

/* Built-ins are compact rows, two to a line on a desktop: the top of page
   one as a small sheet beside the name, so all five fit on one screen. */
.format-grid-builtin {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 440px), 1fr));
  gap: var(--space-4);
}

.format-card.is-builtin {
  flex-direction: row;
  align-items: stretch;
  padding: 0;
  gap: 0;
  overflow: hidden;
}

/* A button centres its content; the sheet has to hang from the top edge so
   the header table of page one is what shows. */
.format-thumb-frame {
  flex: 0 0 124px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-3) var(--space-3) 0;
  overflow: hidden;
  background: var(--bg);
  border: 0;
  border-right: 1px solid var(--border);
  cursor: pointer;
}

.format-thumb {
  display: block;
  width: 100%;
  height: auto;
  background: #FFFFFF;
  border-radius: 2px 2px 0 0;
  box-shadow: 0 1px 6px rgba(22, 35, 30, 0.12);
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

.format-card.is-builtin:hover .format-thumb {
  transform: translateY(-2px);
}

.format-card-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
}

.format-card-title-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.format-card-title-row h3 {
  margin: 0;
}

.badge-lock {
  background: var(--bg);
  color: var(--text-heading);
  border-color: var(--border);
}

.format-card-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* The same footer on every format card: what it holds on the left, its
   actions on the right. */
.format-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-1);
}

.format-card-foot .format-card-meta {
  margin: 0 auto 0 0;
  font-variant-numeric: tabular-nums;
}

.new-format-tile-icon svg {
  width: 22px;
  height: 22px;
  color: var(--primary);
}

.new-format-tile {
  min-height: 112px;
}

.empty-state-compact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-5);
  padding: var(--space-5) var(--space-6);
}

.empty-state-compact p {
  margin: 0;
  max-width: 520px;
  font-size: var(--text-sm);
  color: var(--text-body);
}

@media (max-width: 640px) {
  .format-search {
    flex: 1 1 100%;
    width: auto;
  }

  .format-thumb-frame {
    flex-basis: 88px;
    padding: var(--space-2) var(--space-2) 0;
  }

  .format-card-body {
    padding: var(--space-3) var(--space-4);
  }

  .new-format-tile {
    min-height: 88px;
  }
}

/* ---- Curriculum and course guides ---- */
.guide-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-4) var(--space-6);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--border);
}

.guide-filters .field {
  margin: 0;
}

.guide-search {
  flex: 1 1 240px;
  max-width: 340px;
}

.guide-type {
  flex: 0 1 190px;
}

.guide-filter-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.guide-filter-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-heading);
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  min-height: var(--control-h);
  padding: 0 var(--space-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-heading);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.chip:hover {
  border-color: var(--primary);
}

.chip[aria-pressed="true"] {
  background: var(--primary);
  border-color: var(--primary);
  color: #FFFFFF;
}

.chip:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Guides are documents, so they list like documents: one line each, what
   it is and where it came from, and a way to open it. */
.guide-list {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.guide-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
}

.guide-card + .guide-card {
  border-top: 1px solid var(--border);
}

.guide-icon {
  display: inline-flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text-body);
}

.guide-card.is-official .guide-icon {
  background: var(--primary-tint);
  color: var(--primary);
}

.guide-icon svg {
  width: 18px;
  height: 18px;
}

.guide-body {
  min-width: 0;
}

.guide-title {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.35;
  margin: 0;
  overflow-wrap: break-word;
}

.guide-meta {
  font-size: var(--text-sm);
  color: var(--text-body);
  margin: 2px 0 0;
}

.badge-official {
  background: var(--primary-tint);
  color: var(--primary);
}

.upload-panel {
  margin-top: var(--space-5);
}

#results-empty {
  margin-top: var(--space-6);
}

#results-empty .btn {
  margin-top: var(--space-3);
}

@media (max-width: 640px) {
  .guide-search,
  .guide-type {
    flex: 1 1 100%;
    max-width: none;
  }

  .guide-card {
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-4);
  }

  .guide-card .guide-open {
    grid-column: 1 / -1;
    width: 100%;
  }
}

/* ---- Panels: one title style and one rhythm for every settings-like page ---- */
.panel-title {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-heading);
  margin: 0 0 var(--space-3);
}

.panel-note {
  margin: calc(var(--space-3) * -1 + var(--space-1)) 0 var(--space-4);
  color: var(--text-body);
}

.field-last {
  margin-bottom: 0;
}

.settings-main {
  max-width: 680px;
}

.settings-panel + .settings-panel,
.settings-panel + form.settings-panel,
.settings-main > .panel + .panel {
  margin-top: var(--space-5);
}

.settings-panel .hint {
  margin-top: var(--space-2);
}

.banner-preview {
  display: none;
  width: 100%;
  max-height: 140px;
  object-fit: cover;
  border-radius: var(--radius);
  margin-bottom: var(--space-3);
}

.join-panel {
  max-width: 520px;
  margin-bottom: var(--space-7);
}

.join-form {
  margin-bottom: 0;
}

.section-title-spaced {
  margin-bottom: var(--space-4);
}

/* A weekly field in the plain form view: one labelled box per day. */
.weekly-parts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 180px), 1fr));
  gap: var(--space-2);
}

.weekly-part {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-weight: 400;
}

.weekly-part-name {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-body);
}

/* A short lead-in paragraph at the top of a panel or section. */
.section-intro {
  margin-bottom: var(--space-5);
  max-width: 640px;
}

/* A table that is wider than its column scrolls inside this box, never the
   page. At phone width tables become cards instead (below). */
.table-scroll {
  overflow-x: auto;
}

/* Filters above a list: one row on a desktop, wrapping on a phone, every
   control the same height so labels and bottoms line up. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}

.filter-bar .field {
  flex: 1 1 180px;
  max-width: 280px;
  margin: 0;
}

.filter-bar .field-wide {
  flex-basis: 260px;
  max-width: 420px;
}

.filter-bar input,
.filter-bar select,
.filter-bar .btn {
  min-height: var(--control-h);
}

@media (max-width: 640px) {
  .filter-bar .field {
    max-width: none;
  }
}

/* Phone tables read as a stack of cards: the row's title on top, then each
   value beside its column name (data-label, set by labelTableCells in
   api.js), then the row's actions along the bottom. */
@media (max-width: 640px) {
  .data-table,
  .data-table tbody,
  .data-table tr,
  .data-table td {
    display: block;
    width: 100%;
  }

  .data-table thead tr {
    display: flex;
    border: 0;
  }

  /* The rows are cards now, so the card around the table steps back: no
     second border and padding boxing the first. */
  .section-card:has(> .table-scroll),
  .section-card:has(> div > .table-scroll),
  .panel:has(> .table-scroll) {
    background: transparent;
    border: 0;
    box-shadow: none;
    padding: 0;
  }

  .data-table thead th {
    display: none;
  }

  .data-table thead th.bulk-cell {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0 0 var(--space-3);
    border: 0;
  }

  .data-table thead th.bulk-cell::after {
    content: "Select all";
    font-size: var(--text-sm);
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
  }

  .data-table tbody tr {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
  }

  /* Each value sits in a flex row beside its label, where a long unbroken
     email would keep its full width and push the card sideways; in this
     one-column card breaking anywhere is the right trade. */
  .data-table td,
  .data-table tr:last-child td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    min-width: 0;
    padding: var(--space-1) 0;
    border: 0;
    text-align: right;
    overflow-wrap: anywhere;
  }

  .data-table td[data-label]::before {
    content: attr(data-label);
    flex-shrink: 0;
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-body);
    text-align: left;
  }

  /* The row's name: first cell, or the first after the selection box. */
  .data-table td:first-child:not(.bulk-cell),
  .data-table td.bulk-cell + td {
    display: block;
    text-align: left;
    font-size: var(--text-base);
    font-weight: 600;
    padding: 0 0 var(--space-2);
  }

  .data-table td:first-child:not(.bulk-cell)::before,
  .data-table td.bulk-cell + td::before {
    content: none;
  }

  .data-table td.bulk-cell {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    width: auto;
    padding: 0;
  }

  .data-table td.bulk-cell + td {
    padding-right: 44px;
  }

  /* Actions: a full-width strip along the bottom of the card. */
  .data-table td:last-child:has(button, a.btn, .row-menu) {
    justify-content: flex-start;
    flex-wrap: wrap;
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--border);
  }

  .data-table td:last-child:has(button, a.btn, .row-menu)::before {
    content: none;
  }

  /* An empty-state or loading row spans every column. */
  .data-table td.cell-full {
    display: block;
    text-align: center;
  }

  .data-table tbody tr:has(td.cell-full) {
    border-style: dashed;
  }
}

/* Touch: every control a finger has to hit gets a 44px target on a phone. */
@media (max-width: 640px) {
  .row-action-btn,
  .row-menu-btn,
  .btn-sm,
  .icon-btn,
  .password-toggle-btn,
  .announcement-banner-close,
  .owl-chat-toggle {
    min-width: 44px;
    min-height: 44px;
  }

  .announcement-banner-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  input[type="checkbox"] {
    width: 20px;
    height: 20px;
  }
}

/* ---------------------------------------------------------------------------
   Help and FAQ (2026-10-05)
   A help centre inside the app: a header with the search and two ways in
   (the tutorial video, the tour), then a topic list beside grouped answers.
   --------------------------------------------------------------------------- */

#help-btn[aria-current="page"] {
  color: var(--primary);
}

.help-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 320px);
  grid-template-areas:
    "copy actions"
    "search actions";
  gap: 18px 28px;
  align-items: start;
  padding: 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.help-hero-copy {
  grid-area: copy;
}

.help-hero-copy .page-subtitle {
  margin-top: 6px;
  max-width: 58ch;
}

.help-search {
  grid-area: search;
  position: relative;
}

.help-search-icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-body);
  pointer-events: none;
  display: flex;
}

.help-search-icon svg {
  width: 18px;
  height: 18px;
}

.help-search input {
  width: 100%;
  height: 52px;
  padding: 0 16px 0 46px;
  font: inherit;
  font-size: 15px;
  color: var(--text-heading);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.help-search input::placeholder {
  color: var(--text-body);
}

.help-search input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-tint);
  background: var(--surface);
}

.help-actions {
  grid-area: actions;
  display: grid;
  gap: 10px;
}

.help-action {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-heading);
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.help-action[hidden] {
  display: none;
}

.help-action:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
}

.help-action:active {
  transform: translateY(0);
}

.help-action:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.help-action strong {
  display: block;
  font-size: 14px;
  font-weight: 600;
}

.help-action-note {
  display: block;
  font-size: 12px;
  color: var(--text-body);
  margin-top: 1px;
}

.help-action-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  background: var(--primary-tint);
  color: var(--primary);
}

.help-action-icon svg {
  width: 19px;
  height: 19px;
}

.help-layout {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
  gap: 32px;
  align-items: start;
  margin-top: 28px;
}

.help-topics {
  position: sticky;
  top: 92px;
  display: grid;
  gap: 2px;
}

.help-topic {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--radius);
  color: var(--text-body);
  font-size: 13.5px;
  text-decoration: none;
}

.help-topic[hidden] {
  display: none;
}

.help-topic:hover {
  background: var(--surface);
  color: var(--text-heading);
}

.help-topic.is-current {
  background: var(--primary-tint);
  color: var(--text-heading);
  font-weight: 600;
}

.help-topic:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.help-topic-icon {
  display: flex;
  color: var(--text-body);
}

.help-topic.is-current .help-topic-icon {
  color: var(--primary);
}

.help-topic-icon svg {
  width: 17px;
  height: 17px;
}

.help-topic-label {
  flex: 1;
  min-width: 0;
}

.help-topic-count {
  font-size: 12px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--text-body);
}

.help-content {
  min-width: 0;
  max-width: 860px;
}

.faq {
  display: grid;
  gap: 30px;
}

.faq-group {
  scroll-margin-top: 92px;
}

.faq-group[hidden],
.faq details[hidden] {
  display: none;
}

.faq-group-title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--text-heading);
  margin: 0 0 10px;
}

.faq-list {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.faq-list details + details {
  border-top: 1px solid var(--border);
}

.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 16px 52px 16px 18px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-heading);
  position: relative;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary:hover {
  background: var(--bg);
}

.faq details[open] summary {
  color: var(--primary);
}

/* A chevron drawn with borders: no icon font, no emoji. */
.faq summary::after {
  content: "";
  position: absolute;
  right: 20px;
  top: 50%;
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  opacity: 0.6;
  transform: translateY(-70%) rotate(45deg);
  transition: transform 0.15s ease;
}

.faq details[open] summary::after {
  transform: translateY(-30%) rotate(225deg);
}

.faq summary:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
}

.faq details p {
  margin: 0;
  padding: 0 18px 18px;
  max-width: 68ch;
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-body);
}

.faq-empty {
  font-size: 14px;
  color: var(--text-body);
  padding: 24px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

.faq-empty[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .help-action,
  .faq summary::after {
    transition: none;
  }
  .help-action:hover {
    transform: none;
  }
}

/* Tablets and phones: one column; the topics become a row of chips that
   scrolls sideways, so the answers start near the top. */
@media (max-width: 900px) {
  .help-hero {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "copy"
      "search"
      "actions";
    padding: 20px;
  }

  .help-actions {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  }

  .help-layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 18px;
    margin-top: 20px;
  }

  .help-topics {
    position: static;
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: thin;
  }

  .help-topic {
    flex: 0 0 auto;
    background: var(--surface);
    border: 1px solid var(--border);
    padding: 7px 12px;
  }

  .help-topic-count {
    display: none;
  }
}

/* ---- The owl's onboarding tour (2026-10-05) ---- */

/* Wide enough during a tour for the counter, Skip, Back and Next on one row. */
.owl-guide.is-touring .owl-guide-bubble {
  width: min(340px, calc(100vw - 32px));
}

.owl-tour-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.owl-tour-controls[hidden] {
  display: none;
}

.owl-tour-count {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-body);
  margin-right: auto;
}

.owl-tour-skip {
  border: none;
  background: none;
  padding: 4px 2px;
  font: inherit;
  font-size: 12px;
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.owl-tour-skip:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* The menu item (or Help button) the owl is describing right now. */
.tour-target {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 6px var(--primary-tint);
}

/* ---- Pictures inside the document canvas ---- */
.lp-img { display: block; position: relative; max-width: 100%; margin: 8px 0; line-height: 0; }
.lp-img:not(.lp-img-docx) img { width: 100%; height: auto; display: block; }
.lp-img.img-align-center { margin-left: auto; margin-right: auto; }
.lp-img.img-align-right { margin-left: auto; }
.lp-img.img-wrap-left { float: left; margin: 4px 16px 8px 0; }
.lp-img.img-wrap-right { float: right; margin: 4px 0 8px 16px; }
.lp-img.img-border img { outline: 1px solid #404040; }
.lp-img-cap { display: block; line-height: 1.4; font-size: 0.82em; font-style: italic; padding-top: 4px; }
.lp-img.img-align-center .lp-img-cap { text-align: center; }
.lp-img.img-align-right .lp-img-cap { text-align: right; }
.lp-img-selected { outline: 2px solid var(--primary); outline-offset: 2px; cursor: default; }
.lp-img-handle { position: absolute; right: -7px; bottom: -7px; width: 14px; height: 14px; border-radius: 3px; background: var(--primary); border: 2px solid var(--surface); cursor: nwse-resize; touch-action: none; }

/* A picture straight from the Word file keeps the layout's exact size and
   position (its <img> carries them inline); the wrapper only marks it as
   editable. Once the teacher restyles it, the wrapper loses .lp-img-docx and
   it previews with the rules above. Kept after them so it wins on ties. */
.lp-img.lp-img-docx { display: inline; position: static; float: none; margin: 0; max-width: none; line-height: inherit; }
.lp-img-docx.lp-img-selected { outline: none; }
.lp-img-docx.lp-img-selected > img { outline: 2px solid var(--primary); outline-offset: 2px; }
.lp-img-docx .lp-img-handle { display: none; }

/* The floating bar for the selected picture. Fixed, so it can live inside the
   document stage and stay visible when the stage goes fullscreen. */
.doc-img-bar { position: fixed; z-index: 1001; display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 4px; max-width: min(560px, calc(100vw - 16px)); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12); }
.doc-img-bar[hidden] { display: none; }
.doc-img-btn { min-width: 36px; height: 36px; padding: 0 8px; border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--text-heading); font-size: 13px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.doc-img-btn svg { width: 18px; height: 18px; }
.doc-img-btn:hover { background: var(--bg); }
.doc-img-btn[aria-pressed="true"] { border-color: var(--primary); color: var(--primary); background: var(--bg); }
.doc-img-btn[data-act="delete"] { color: var(--danger); }
.doc-img-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.doc-img-sep { width: 1px; align-self: stretch; margin: 4px; background: var(--border); }

/* ---- Pre-generate field review: which fields Alan writes ---- */
.gen-review-dialog { max-width: 520px; }
.gen-review-intro { margin: 0 0 12px; font-size: 13.5px; line-height: 1.5; color: var(--text-body); }
.gen-review-bulk { display: flex; gap: 16px; margin: 0 0 12px; }
.link-btn { padding: 0; border: none; background: none; color: var(--primary); font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.link-btn:hover { text-decoration-thickness: 2px; }
.link-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 2px; }
.gen-review-group { border: 0; padding: 0; margin: 0 0 16px; min-width: 0; }
.gen-review-group legend { padding: 0; margin-bottom: 4px; font-weight: 700; font-size: 12px; letter-spacing: 0.02em; color: var(--text-heading); }
.gen-review-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.gen-review-label { font-size: 14px; line-height: 1.35; color: var(--text-heading); }
.gen-review-note { margin-left: 8px; font-size: 11.5px; color: var(--text-body); font-style: italic; white-space: nowrap; }
.seg { display: inline-flex; flex-shrink: 0; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.seg label { position: relative; cursor: pointer; }
.seg input { position: absolute; opacity: 0; pointer-events: none; }
.seg span { display: inline-block; min-height: 36px; padding: 8px 12px; font-size: 13px; font-weight: 600; line-height: 20px; color: var(--text-body); }
.seg label + label span { border-left: 1px solid var(--border); }
.seg input:checked + span { background: var(--primary); color: #fff; }
.seg input[value="static"]:checked + span { background: #475569; }
.seg input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: -3px; }
.gen-review-footer { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 14px 22px; border-top: 1px solid var(--border); flex-shrink: 0; }
.gen-review-footer #gen-review-hint { margin-right: auto; }

/* On a wide screen the popup docks right, so the highlighted document stays
   in view beside it rather than hidden behind it. */
@media (min-width: 1100px) {
  .gen-review-overlay { justify-content: flex-end; padding: 16px; background: rgba(31, 41, 55, 0.18); }
  .gen-review-dialog { height: 100%; max-height: none; }
  .gen-review-dialog .modal-body { flex: 1; }
}

.lp-field-review-gen { outline: 2px solid var(--primary); outline-offset: 2px; }
.lp-field-review-static,
.lp-field-static:not(.lp-filled) {
  background: rgba(71, 85, 105, 0.06);
  outline: 1px dashed #64748B;
  outline-offset: 2px;
}
.lp-field-review-pulse { animation: review-pulse 0.9s ease-out 1; }
@keyframes review-pulse {
  0% { box-shadow: 0 0 0 0 rgba(28, 92, 78, 0.45); }
  100% { box-shadow: 0 0 0 12px rgba(28, 92, 78, 0); }
}
@media (prefers-reduced-motion: reduce) { .lp-field-review-pulse { animation: none; } }

/* ---- Generation loader: Alan beside the per-section progress ---- */
.gen-loader { display: flex; align-items: center; gap: 24px; padding: 20px 24px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.gen-loader[hidden] { display: none; }
.gen-loader-owl { width: 88px; height: auto; flex-shrink: 0; animation: page-transition-bob 1.6s ease-in-out infinite; }
.gen-loader-body { flex: 1; min-width: 0; }
.gen-loader-title { display: block; margin-bottom: 10px; font-family: var(--font-display); font-size: 17px; font-weight: 600; color: var(--text-heading); }
.gen-loader .generation-progress { padding: 0; border: none; background: none; max-width: none; }
@media (prefers-reduced-motion: reduce) { .gen-loader-owl { animation: none; } }
@media (max-width: 520px) {
  .gen-loader { flex-direction: column; align-items: flex-start; gap: 12px; }
  .gen-loader-owl { width: 64px; }
}

/* Alan steps aside from the action buttons: a small peek in his corner that
   never takes a click, and no bubble. See OwlGuide._watchCovering(). */
.owl-guide .owl-guide-figure,
.owl-guide .owl-guide-bubble { transition: transform 0.25s ease, opacity 0.2s ease, visibility 0.2s; }
.owl-guide.is-peeking .owl-guide-bubble { opacity: 0; visibility: hidden; }
.owl-guide.is-peeking .owl-guide-figure { transform: translate(12%, 34%) scale(0.5); transform-origin: bottom right; }
.owl-guide.is-peeking .owl-guide-figure,
.owl-guide.is-peeking .owl-guide-figure * { pointer-events: none; }
/* Docked in Guided mode he is how the chat opens, so even shrunk into his
   corner beside the action row he stays clickable. */
.owl-guide.is-docked.is-peeking .owl-guide-img { pointer-events: auto; }
@media (prefers-reduced-motion: reduce) {
  .owl-guide .owl-guide-figure, .owl-guide .owl-guide-bubble { transition: none; }
}

/* ---- Create Lesson Plan flow: Alan asks one question at a time ----
   Question on the left, the big 3D Alan on the right (js/setup-flow.js).
   One authored motion moment: each new question rises in out of a soft blur. */
.dash-main:has(> .flow:not([hidden])) {
  display: flex;
  padding: 0;
  /* The page scrolls, not this column, so the sticky Back/Next can follow it. */
  overflow: visible;
}
.dash-main:has(> .flow:not([hidden])) > :not(.flow) { display: none; }
body:has(.flow:not([hidden])) .owl-guide { display: none; }

.flow {
  --flow-ease: cubic-bezier(0.32, 0.72, 0, 1);
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  min-height: 100%;
}
.flow-ask {
  display: flex;
  flex-direction: column;
  gap: 28px;
  padding: clamp(28px, 5vh, 56px) clamp(24px, 5vw, 72px);
}
.flow-top { display: flex; align-items: center; gap: 14px; }
.flow-progress {
  flex: 1;
  height: 4px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--border);
}
.flow-progress > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--primary);
  transform-origin: left;
  transition: transform 0.6s var(--flow-ease);
}
.flow-count {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-body);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.flow-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 32px;
  max-width: 560px;
}
.flow-step {
  display: flex;
  flex-direction: column;
  gap: 14px;
  transition: opacity 0.5s var(--flow-ease), transform 0.6s var(--flow-ease), filter 0.5s var(--flow-ease);
}
.flow-step.is-entering { opacity: 0; transform: translateY(14px); filter: blur(6px); }
.flow-question {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(28px, 3vw, 40px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--text-heading);
  text-wrap: balance;
}
.flow-question:focus { outline: none; }
.flow-help {
  margin: 0;
  max-width: 46ch;
  font-size: var(--text-md);
  line-height: 1.55;
  color: var(--text-body);
}
.flow-answer { display: flex; flex-direction: column; gap: 14px; margin-top: 18px; }
.flow-label { margin: 6px 0 -4px; font-size: var(--text-sm); font-weight: 600; color: var(--text-heading); }

/* A field sits in a soft tray: the tray carries the focus state. */
.flow-field {
  padding: 5px;
  border-radius: 18px;
  background: rgba(28, 92, 78, 0.05);
  box-shadow: inset 0 0 0 1px rgba(28, 92, 78, 0.08);
  transition: background-color 0.3s var(--flow-ease), box-shadow 0.3s var(--flow-ease);
}
.flow-field:focus-within {
  background: rgba(28, 92, 78, 0.08);
  box-shadow: inset 0 0 0 1px rgba(28, 92, 78, 0.4), 0 0 0 4px rgba(28, 92, 78, 0.1);
}
.flow-field input {
  width: 100%;
  height: 56px;
  padding: 0 18px;
  border: 0;
  border-radius: 13px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(22, 35, 30, 0.06);
  font: 400 18px var(--font);
  color: var(--text-heading);
}
.flow-field input:focus { outline: none; }
.flow-field input::placeholder { color: #66736b; }
.flow-field input:disabled { background: transparent; box-shadow: none; color: var(--text-body); }
/* Dropdowns sit in the same tray as the text fields, with a drawn chevron. */
.flow-select select {
  width: 100%;
  height: 56px;
  padding: 0 48px 0 18px;
  border: 0;
  border-radius: 13px;
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%231C5C4E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 18px center;
  box-shadow: 0 1px 2px rgba(22, 35, 30, 0.06);
  font: 400 18px var(--font);
  color: var(--text-heading);
  appearance: none;
  cursor: pointer;
}
.flow-select select:focus { outline: none; }
.flow-select select:disabled { background-color: transparent; box-shadow: none; color: var(--text-body); cursor: default; }
.flow-select select:invalid, .flow-select select option[value=""] { color: #66736b; }

/* Supplementary sources: one quiet row per uploaded file. */
.flow-sources {
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--border);
}
.flow-source {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 6px 8px 6px 14px;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-base);
  color: var(--text-heading);
}
.flow-source:last-child { border-bottom: 0; }
.flow-source > span:not([aria-hidden]) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flow-source > [aria-hidden] { flex: none; width: 18px; height: 18px; color: var(--primary); }
.flow-source > [aria-hidden] svg { width: 100%; height: 100%; }
.flow-source-remove {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-body);
  cursor: pointer;
}
.flow-source-remove:hover { background: rgba(171, 53, 36, 0.08); color: var(--danger); }
.flow-source-remove svg { width: 16px; height: 16px; }
.flow-source-kind { flex: none; font-size: var(--text-xs); font-weight: 600; color: var(--primary); }

/* Step 6's dropdown that takes several picks: looks like the other dropdowns,
   opens a checklist grouped under Curriculum Guide and Budget of Work. */
.flow-multi { position: relative; }
.flow-multi-summary {
  display: block;
  min-height: 56px;
  padding: 10px 48px 10px 18px;
  border-radius: 13px;
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%231C5C4E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 18px center;
  box-shadow: 0 1px 2px rgba(22, 35, 30, 0.06);
  font: 400 18px var(--font);
  color: var(--text-heading);
  list-style: none;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 36px;
}
.flow-multi-summary::-webkit-details-marker { display: none; }
.flow-multi-summary:focus { outline: none; }
.flow-multi-summary.is-empty { color: #66736b; }
.flow-multi-panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 10px);
  left: -5px;
  right: -5px;
  max-height: min(340px, 50vh);
  overflow-y: auto;
  padding: 8px;
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--border), 0 18px 40px -12px rgba(22, 35, 30, 0.28);
}
.flow-multi-head {
  margin: 8px 10px 4px;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--primary);
}
.flow-multi-item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 17px;
  color: var(--text-heading);
  cursor: pointer;
}
.flow-multi-item:hover { background: rgba(28, 92, 78, 0.06); }
/* Outranks the text-field rules (.flow-field input), which would size it as a field. */
.flow-multi .flow-multi-item input {
  flex: none;
  width: 20px;
  height: 20px;
  padding: 0;
  background: none;
  box-shadow: none;
  accent-color: var(--primary);
}

.flow-choices {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
}
.flow-choice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 52px;
  padding: 12px 16px;
  border: 0;
  border-radius: 14px;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--border), 0 1px 2px rgba(22, 35, 30, 0.04);
  font: 500 var(--text-md) var(--font);
  color: var(--text-heading);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.25s var(--flow-ease), color 0.25s var(--flow-ease), box-shadow 0.25s var(--flow-ease), transform 0.2s var(--flow-ease);
}
.flow-choice:hover { box-shadow: inset 0 0 0 1px rgba(28, 92, 78, 0.45), 0 6px 18px -10px rgba(22, 35, 30, 0.25); }
.flow-choice:active { transform: scale(0.985); }
.flow-choice[aria-pressed="true"] {
  background: var(--primary);
  color: #fff;
  box-shadow: 0 8px 22px -12px rgba(28, 92, 78, 0.7);
}
.flow-choice-tick { display: none; width: 18px; height: 18px; flex: none; }
.flow-choice-tick svg { width: 100%; height: 100%; }
.flow-choice[aria-pressed="true"] .flow-choice-tick { display: block; }
.flow-alt { align-self: flex-start; min-height: 44px; font-size: var(--text-base); }

/* Step 1: format cards carry a name and a quiet second line. */
.flow-choices-formats { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.flow-choices-stack { grid-template-columns: minmax(0, 1fr); }
.flow-format { align-items: flex-start; min-height: 64px; }
.flow-format > [aria-hidden] { flex: none; width: 18px; height: 18px; margin-top: 2px; }
.flow-format > [aria-hidden] svg { width: 100%; height: 100%; }
.flow-format-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.flow-format-text strong { font-weight: 600; }
.flow-format-text small {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-size: var(--text-sm);
  font-weight: 400;
  line-height: 1.4;
  color: var(--text-body);
}
.flow-choice[aria-pressed="true"] .flow-format-text small { color: rgba(255, 255, 255, 0.82); }
.flow-upload {
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(28, 92, 78, 0.45);
  color: var(--primary);
}
.flow-upload:hover { background: rgba(28, 92, 78, 0.05); }
.flow-drop {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 28px 24px;
  border: 0;
  border-radius: 18px;
  background: rgba(28, 92, 78, 0.04);
  box-shadow: inset 0 0 0 1.5px rgba(28, 92, 78, 0.35);
  font: inherit;
  color: var(--text-heading);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.25s var(--flow-ease), box-shadow 0.25s var(--flow-ease);
}
.flow-drop > [aria-hidden] { flex: none; width: 28px; height: 28px; color: var(--primary); }
.flow-drop > [aria-hidden] svg { width: 100%; height: 100%; }
.flow-drop:hover, .flow-drop.is-over { background: rgba(28, 92, 78, 0.09); box-shadow: inset 0 0 0 1.5px var(--primary); }
.flow-drop:disabled { opacity: 0.6; cursor: progress; }
.flow-more { align-self: flex-start; height: 40px; color: var(--primary); }
/* Long lists scroll in place so Next stays on screen. */
.flow-scroll { max-height: 38vh; overflow-y: auto; padding: 3px 6px 3px 3px; margin: -3px -6px -3px -3px; }
/* A capped grid squeezes its rows below their content; a column of
   non-shrinking cards scrolls instead. */
.flow-choices.flow-scroll { display: flex; flex-direction: column; }
.flow-choices.flow-scroll > * { flex: none; }
/* Budget of Work and supplementary sources: two short groups in one step. */
.flow-guide-kind { display: flex; flex-direction: column; gap: 10px; }
.flow-guide-kind + .flow-guide-kind { margin-top: 10px; }
.flow-upload-link { gap: 8px; }
.flow-upload-link svg { width: 16px; height: 16px; }

/* Lesson details: every answer, one row each. */
.flow-details {
  display: flex;
  flex-direction: column;
  max-height: 52vh;
  overflow-y: auto;
  border-radius: 16px;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--border), 0 1px 2px rgba(22, 35, 30, 0.04);
}
.flow-detail {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  border: 0;
  border-bottom: 1px solid var(--border);
  background: transparent;
  font: inherit;
  color: var(--text-heading);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.2s var(--flow-ease);
}
.flow-detail:last-child { border-bottom: 0; }
.flow-detail:hover { background: rgba(28, 92, 78, 0.05); }
.flow-detail > [aria-hidden] { flex: none; width: 18px; height: 18px; color: var(--primary); }
.flow-detail > [aria-hidden] svg { width: 100%; height: 100%; }
.flow-detail .flow-format-text small { -webkit-line-clamp: 1; }
.flow-detail.is-fixed { cursor: default; }
.flow-detail.is-fixed:hover { background: transparent; }

/* The review list and the progress list move in from the document view. */
.flow .gen-review-intro { display: none; }
.flow #gen-review-list { max-height: 46vh; overflow-y: auto; padding-right: 6px; }
.flow .gen-loader { padding: 0; border: 0; background: transparent; }
.flow .gen-loader-owl, .flow .gen-loader-title { display: none; }

/* Back and Next stay in reach on short screens: they stick to the bottom of
   the column with a soft fade, so long answers scroll beneath them. */
.flow-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.flow-body > .flow-actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  margin-bottom: -16px;
  padding: 14px 0 16px;
  background: linear-gradient(to bottom, rgba(241, 244, 238, 0), var(--bg) 40%);
}
.flow-next {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 52px;
  padding: 0 8px 0 24px;
  border: 0;
  border-radius: 999px;
  background: var(--primary);
  box-shadow: 0 10px 24px -14px rgba(28, 92, 78, 0.9);
  font: 600 var(--text-md) var(--font);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.2s var(--flow-ease), transform 0.2s var(--flow-ease), opacity 0.2s var(--flow-ease);
}
.flow-next-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  transition: transform 0.35s var(--flow-ease);
}
.flow-next-icon svg { width: 18px; height: 18px; }
.flow-next:hover { background: var(--primary-hover); }
.flow-next:hover .flow-next-icon { transform: translateX(3px); }
.flow-next:active { transform: scale(0.98); }
.flow-next:disabled { opacity: 0.45; box-shadow: none; cursor: not-allowed; }
.flow-next:disabled .flow-next-icon { transform: none; }
.flow-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 52px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: 500 var(--text-md) var(--font);
  color: var(--text-heading);
  cursor: pointer;
}
.flow-back svg { width: 18px; height: 18px; }
.flow-back:hover { background: rgba(28, 92, 78, 0.07); }
.flow-hint { font-size: var(--text-sm); color: var(--text-body); }
.flow-error { margin: 0; font-size: var(--text-sm); color: var(--danger); }

.flow-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: radial-gradient(120% 80% at 50% 38%, #fbfcfa 0%, #eef3ec 55%, #e1ece5 100%);
}
.flow-say {
  position: absolute;
  top: clamp(20px, 4vh, 40px);
  left: 50%;
  z-index: 1;
  width: min(420px, calc(100% - 48px));
  margin: 0;
  padding: 14px 18px;
  border-radius: 18px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(22, 35, 30, 0.05), 0 18px 40px -20px rgba(22, 35, 30, 0.28);
  font-size: var(--text-md);
  line-height: 1.45;
  color: var(--text-heading);
  transform: translateX(-50%);
}
.flow-say::after {
  content: "";
  position: absolute;
  bottom: -7px;
  left: 50%;
  width: 14px;
  height: 14px;
  background: var(--surface);
  border-radius: 0 0 4px 0;
  transform: translateX(-50%) rotate(45deg);
}
.flow-alan { position: relative; flex: 1; }
.flow-alan canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.flow-alan img { position: absolute; inset: 0; max-width: 80%; max-height: 70%; margin: auto; object-fit: contain; }

@media (min-width: 861px) and (max-height: 820px) {
  .flow-ask { gap: 18px; padding-block: 20px; }
  .flow-body { gap: 22px; }
  .flow-question { font-size: clamp(24px, 2.4vw, 32px); }
  .flow-answer { margin-top: 8px; }
  .flow-scroll { max-height: 30vh; }
  .flow #gen-review-list { max-height: 34vh; }
  .flow-details { max-height: 44vh; }
}
@media (max-width: 860px) {
  .flow { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; }
  .flow-stage { order: -1; height: 36svh; min-height: 240px; }
  .flow-say { top: 12px; width: calc(100% - 32px); padding: 10px 14px; font-size: var(--text-base); }
  .flow-ask { gap: 22px; padding: 22px 16px 32px; }
  .flow-question { font-size: 26px; }
  .flow-hint { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .flow-step, .flow-progress > span, .flow-choice, .flow-next, .flow-next-icon, .flow-field { transition: none; }
}

/* Larger type and fields for the flow (the user's request, 2026-10-24):
   the questions are read at arm's length, often on a classroom laptop. */
.flow-body { max-width: 640px; gap: 30px; }
.flow-count { font-size: 15px; }
.flow-question { font-size: clamp(32px, 3.4vw, 48px); }
.flow-help { max-width: 48ch; font-size: 18px; }
.flow-label { margin: 10px 0 -2px; font-size: 16px; }
.flow-field input, .flow-select select { height: 62px; font-size: 20px; }
.flow-multi-summary { min-height: 62px; font-size: 20px; }
.flow-choice { min-height: 56px; font-size: 18px; }
.flow-format-text small { font-size: 15px; }
.flow-alt { font-size: 16px; }
.flow-next, .flow-back { height: 56px; font-size: 18px; }
.flow-say { font-size: 18px; }
.flow-source { font-size: 16px; }
@media (min-width: 861px) and (max-height: 820px) {
  .flow-question { font-size: clamp(28px, 2.8vw, 38px); }
  .flow-field input, .flow-select select { height: 56px; }
  .flow-multi-summary { min-height: 56px; }
}
@media (max-width: 860px) {
  .flow-question { font-size: 28px; }
  .flow-field input, .flow-select select { height: 56px; font-size: 18px; }
  .flow-multi-summary { min-height: 56px; font-size: 18px; }
  .flow-say { font-size: var(--text-base); }
}

/* Wide screens: Alan stays put while the questions use the room (the user's
   request, 2026-10-24). Fields sit side by side so most steps fit without
   scrolling. Phones are unchanged: the row wrappers dissolve there. */
@media (max-width: 860px) {
  .flow-row, .flow-cell { display: contents; }
}
@media (min-width: 861px) {
  .flow { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
  .flow-stage {
    position: sticky;
    top: var(--topbar-h);
    align-self: start;
    height: calc(100dvh - var(--topbar-h));
    /* A glow behind Alan that fades out before the edges, so he and the
       questions share one surface with no seam between them. */
    background: radial-gradient(closest-side at 50% 48%, #fbfcfa 0%, rgb(251 252 250 / 0.55) 55%, transparent 100%);
  }
  .flow-ask { gap: 22px; padding-block: clamp(22px, 4vh, 44px); }
  .flow-body { max-width: 860px; gap: 26px; }
  .flow-answer { gap: 18px; margin-top: 10px; }
  .flow-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 16px 22px;
    align-items: start;
  }
  .flow-cell { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
  .flow-cell > .flow-label { margin: 0; }
  /* Step 6: a compact upload link, and a long list of picks scrolls inside
     itself so the step still fits the screen. */
  .flow-guide-kind > .flow-more { height: 44px; padding: 0 12px; }
  .flow-guide-kind > .flow-sources { max-height: 26vh; overflow-y: auto; }
  .flow-mode-choices { grid-template-columns: 1fr 1fr; }
  .flow-mode-choices .flow-mode { min-height: 112px; padding: 18px 20px; }
  .flow-choices-formats { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}
@media (min-width: 861px) and (max-height: 820px) {
  .flow-ask { gap: 16px; }
  .flow-body { gap: 18px; }
  .flow-answer { gap: 14px; margin-top: 4px; }
  .flow-ask { padding-block: 14px; }
}
