/* ===================================================================
   SQUIDDLR — ocean-depth admin theme
   Matches the Global Omni PanOpticon dark "ink" palette (deep-sea
   navy/teal + amber eye-glow), not the light Eat Those Frogs theme.
   Squiddlr the mascot is the visual anchor throughout.
   =================================================================== */
@import url('https://fonts.googleapis.com/css2?family=Pacifico&family=General+Sans:wght@500;600;700&family=Satoshi:wght@400;500&display=swap');

:root {
  /* Ink surfaces — deep sea, darkest at the "bottom" */
  --ink-000: #060B14;
  --ink-050: #0A1220;
  --ink-100: #101C2F;
  --ink-200: #182A44;
  --ink-300: #2A4263;

  /* Fog text tones — all four meet WCAG AA (>=4.5:1 normal text) on the
     ink card/panel surfaces they sit on. --fog-400 was #5A6B84 (only ~3.1-3.6:1
     on ink surfaces — failed AA for the meta/muted body text it drives); it is
     now lightened to #8291A8 so muted text still reads as "quiet" but clears
     4.5:1 everywhere (ink-050/100/200/000). */
  --fog-100: #E6EAF1;
  --fog-200: #B9C3D3;
  --fog-300: #8594AB;
  --fog-400: #8291A8;

  /* PanOpticon cyan/teal accent */
  --teal-400: #4FD1C5;
  --teal-500: #2BB6A8;
  --teal-700: #0D9488;

  /* Amber eye-glow, used sparingly */
  --amber-400: #F4B860;

  /* Semantic */
  --success: #34D399;
  --success-bg: rgba(52, 211, 153, 0.12);
  --error: #F87171;
  --error-bg: rgba(248, 113, 113, 0.12);
  --warn: var(--amber-400);
  --warn-bg: rgba(244, 184, 96, 0.12);

  /* Lifecycle status chips — one shared five-stage ramp for "how far along
     is this" chips everywhere (Content Studio lecture status, Tools
     generation status). Ramp reads cold -> warm as content moves toward
     published: fog (not started) -> teal (active work) -> amber (needs
     review) -> success (approved/live), success intensifying at published. */
  --status-contract-bg:  rgba(133, 148, 171, 0.14); /* fog-300 tint */
  --status-contract-fg:  var(--fog-200);            /* fog-200 (not fog-300) for AA: pill sits on ink-200 active/hover rows */
  --status-draft-bg:     rgba(79, 209, 197, 0.12);  /* teal-400 tint */
  --status-draft-fg:     var(--teal-400);
  --status-progress-bg:  rgba(244, 184, 96, 0.14);  /* amber-400 tint */
  --status-progress-fg:  var(--amber-400);
  --status-approved-bg:  rgba(52, 211, 153, 0.14);  /* success tint, dimmer than published */
  --status-approved-fg:  var(--success);
  --status-published-bg: rgba(52, 211, 153, 0.22);  /* success tint, strongest */
  --status-published-fg: var(--success);

  --f-display: "General Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-body: "Satoshi", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-script: "Pacifico", cursive;
  --f-mono: 'SFMono-Regular', 'JetBrains Mono', Consolas, 'Liberation Mono', Menlo, monospace;

  --radius:    10px;
  --radius-sm: 8px;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.25);
  --shadow:    0 2px 8px rgba(0,0,0,0.35);
  --shadow-md: 0 8px 24px rgba(0,0,0,0.45);
  --transition: 200ms ease;
}
* { box-sizing: border-box; }

body {
  font-family: var(--f-body);
  margin: 0;
  color: var(--fog-100);
  /* Ocean-depth background, site-wide — ONE shared rule, identical to the
     approved splash (welcome.html). A light scrim keeps text legible in the
     gutters while the full-bleed underwater scene shows through vibrantly;
     content itself sits on solid --ink card/panel surfaces so it stays
     readable regardless. This is the single source of truth for the page
     background — no page should redefine it. */
  background:
    linear-gradient(180deg, rgba(6, 11, 20, 0.30) 0%, rgba(6, 11, 20, 0.22) 45%, rgba(6, 11, 20, 0.55) 100%),
    url('/admin/img/ocean-background.jpg') center top / cover no-repeat fixed;
  background-color: var(--ink-000);
  min-height: 100vh;
  position: relative;
  /* Sticky-footer layout: body is a flex column so the content region can
     grow and the footer always pins to the bottom regardless of content
     height. Fixed overlays (#login-gate, #squiddlr-helper) are out of flow
     and unaffected. */
  display: flex;
  flex-direction: column;
}

main, header.app-header, .tabs { position: relative; z-index: 1; }

header.app-header {
  background: linear-gradient(180deg, var(--ink-200), var(--ink-100));
  border-bottom: 1px solid var(--ink-300);
  color: var(--fog-100); padding: 14px 24px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
header.app-header .brand {
  display: flex; align-items: center; gap: 12px;
  text-decoration: none; color: inherit; border-radius: var(--radius-sm);
  transition: opacity var(--transition);
}
header.app-header a.brand:hover { opacity: 0.82; }
header.app-header .mascot { height: 44px; width: auto; filter: drop-shadow(0 2px 6px rgba(79,209,197,0.4)); }
header.app-header .wordmark { font-family: var(--f-script); font-size: 1.7em; color: var(--teal-400); line-height: 1; }
header.app-header .subtitle { font-family: var(--f-display); font-size: 0.75em; color: var(--fog-300); font-weight: 500; margin-top: 2px; }

/* Accessible keyboard focus ring — applies to any interactive element,
   site-wide (links, buttons, inputs, tabs, nav items). */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 3px solid var(--teal-400); outline-offset: 2px;
}

/* Skip-to-content link — visually hidden until focused, for keyboard/
   screen-reader users to bypass the header/topnav. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--teal-500); color: #06281c; padding: 10px 16px;
  border-radius: 0 0 var(--radius-sm) 0; font-family: var(--f-display); font-weight: 700;
  text-decoration: none;
}
.skip-link:focus { left: 0; }

.tabs { display: flex; gap: 6px; padding: 14px 24px 0; }
.tab-btn {
  padding: 8px 18px; border: 1px solid var(--ink-300); background: var(--ink-100); color: var(--fog-200);
  border-bottom: none; border-radius: 8px 8px 0 0; cursor: pointer; font-size: 0.95em; font-family: var(--f-display);
  transition: color var(--transition), border-color var(--transition), background var(--transition);
}
.tab-btn.active { background: var(--ink-050); font-weight: 600; border-color: var(--teal-500); color: var(--teal-400); }

main { padding: 24px; max-width: 1280px; margin: 0 auto; }
.panel { display: none; }
.panel.active { display: block; }

.card {
  background: linear-gradient(180deg, var(--ink-100), var(--ink-050));
  border: 1px solid var(--ink-300); border-radius: var(--radius);
  padding: 18px; margin-bottom: 18px; box-shadow: var(--shadow-sm);
}
.card h3 { margin-top: 0; color: var(--teal-400); font-family: var(--f-display); }
.card h4 { color: var(--teal-400); font-family: var(--f-display); }

/* ---------------------------------------------------------------------
   Squiddlr nesting standard, level 3: .subcard
   The site's containment hierarchy is: page -> .card (level 2) ->
   .subcard (level 3, this) -> modal (a portal on top, not a nesting
   level). A .subcard groups ONE coherent unit of content living inside
   a .card -- e.g. "Upload Textbook Chapters", "Purchasing & Access Info",
   and "Supplies" as three siblings inside the Textbook & Supplies .card.
   Visually flatter and darker than .card (recessed, not another raised
   surface) so depth reads correctly: solid ink-000 fill, thinner
   ink-200 border, no drop-shadow. Switch between sibling .subcards with
   the existing .seg-toggle tab component -- do not invent a new tab
   style per page. */
.subcard {
  background: var(--ink-000);
  border: 1px solid var(--ink-200); border-radius: var(--radius-sm);
  padding: 16px; margin-bottom: 16px;
}
.subcard:last-child { margin-bottom: 0; }
.subcard h3, .subcard h4 { margin-top: 0; color: var(--teal-400); font-family: var(--f-display); }
.subcard > .subcard { background: var(--ink-050); }

label { display: block; font-size: 0.9em; font-weight: 600; color: var(--fog-200); margin-bottom: 5px; margin-top: 12px; font-family: var(--f-display); }
select, input[type=text], input[type=search], input[type=date], input[type=number], textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--ink-300); border-radius: var(--radius-sm);
  font-size: 1em; line-height: 1.5; font-family: var(--f-body); background: var(--ink-000); color: var(--fog-100);
}
select:focus, input:focus, textarea:focus { outline: none; border-color: var(--teal-500); box-shadow: 0 0 0 3px rgba(79,209,197,0.15); }
/* Textareas are writing surfaces, not one-liners — give every one a
   comfortable default height (rows= only sets a floor the browser can shrink
   past visually on some themes). Individual sections can grow this further. */
textarea { resize: vertical; min-height: 96px; }
.row { display: flex; gap: 16px; flex-wrap: wrap; }
.row > div { flex: 1; min-width: 220px; }

/* Below 640px, two side-by-side .row columns (min-width 220px each + gap)
   can outgrow narrow phone viewports before the browser's own wrap logic
   kicks in cleanly. Force a single stacked column so nothing runs off
   screen. Pure flexbox, no JS, no vendor prefixes — reflows safely for
   WCAG 1.4.10 (Reflow) and works identically across Safari/iOS, Chrome,
   Edge, Firefox. */
@media (max-width: 640px) {
  .row { flex-direction: column; }
  .row > div { min-width: 0; width: 100%; }
}

/* .row already stretches its direct children (.flex-1) to equal height by
   default (flex align-items: stretch), but each .card inside only grows to
   fit its own content, so shorter columns leave blank space at the bottom
   next to a taller sibling (e.g. Instructor's Your Info vs About You).
   Make a .card that is a direct .flex-1 child fill that stretched height
   and lay out as a column so its Save button can pin to the bottom,
   matching its sibling regardless of field count. Scoped to .flex-1 > .card
   so single-column/standalone cards elsewhere are unaffected. */
.flex-1 > .card {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.flex-1 > .card > .toolbar:last-child {
  margin-top: auto;
}

/* Standard form convention: a single primary submit action (Save, Create,
   etc.) reads as the form's end-point and sits bottom-right in left-to-right
   UIs; secondary/destructive actions (Cancel, Back) stay to its left in the
   same toolbar. Applied page-by-page as toolbars are reviewed — not a
   sitewide default, since many .toolbar instances are multi-button rows
   (Save + Cancel, Back + mode switch, etc.) that intentionally read
   left-to-right. */
.toolbar-end {
  justify-content: flex-end;
}

/* Group of action elements (buttons, badges) clustered at one end of a
   .toolbar. Reusable lego block — prefer this over inline flex styles. */
.toolbar-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

button {
  cursor: pointer; border: none; border-radius: var(--radius-sm); padding: 8px 14px;
  font-size: 0.9em; font-weight: 600; font-family: var(--f-display); transition: filter var(--transition), transform var(--transition);
}
button:hover { filter: brightness(1.1); transform: translateY(-1px); }
.btn-primary   { background: var(--teal-600, var(--teal-700)); color: #fff; }
.btn-secondary { background: var(--ink-300); color: var(--fog-100); }
.btn-success   { background: var(--success); color: #06281c; }
.btn-warning   { background: var(--warn-bg); color: var(--amber-400); border: 1px solid var(--amber-400); }
.btn-danger    { background: var(--error); color: #2b0a0a; }
.btn-sm { padding: 4px 9px; font-size: 0.8em; }

/* Wrap any data table in .table-scroll so a wide table (many columns) scrolls
   horizontally inside its own container on narrow viewports instead of pushing
   the whole page wide. Data tables are an explicit exception to WCAG 1.4.10
   Reflow, so an in-container horizontal scroll is the accessible pattern here.
   Reusable across every page that renders a table. */
.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 0.9em; }
th, td { border: 1px solid var(--ink-300); padding: 6px 8px; text-align: left; color: var(--fog-200); }
th { background: var(--ink-200); color: var(--teal-400); font-family: var(--f-display); }
tr.archived { background: rgba(90,107,132,0.15); color: var(--fog-400); }

/* Inline-editable table cells — inputs styled to read as cell content until
   focused, so the Table View doubles as a quick editor. Reusable lego block:
   any <td><input class="cell-edit" data-field=…> participates. */
.cell-edit {
  width: 100%; min-width: 0; box-sizing: border-box;
  background: transparent; border: 1px solid transparent;
  color: inherit; font: inherit; font-size: 0.92em;
  padding: 3px 6px; border-radius: var(--radius-sm); transition: border-color 0.15s, background 0.15s;
}
.cell-edit:hover { border-color: var(--ink-300); }
.cell-edit:focus { border-color: var(--teal-400); background: var(--ink-100); outline: none; color: var(--fog-100); }
.cell-edit:disabled { opacity: 0.6; cursor: not-allowed; }
.cell-edit.cell-num { width: 64px; text-align: center; }
.cell-edit.cell-date { width: 150px; }
.cell-edit.cell-topic { min-width: 180px; }
.row-handle { cursor: grab; color: var(--fog-400); user-select: none; text-align: center; }
tr.dragging .row-handle { cursor: grabbing; }
tr.selected { background: rgba(79,209,197,0.10); }
tr.drag-over { outline: 2px dashed var(--teal-400); outline-offset: -2px; }
tr[draggable="true"] { cursor: grab; }
tr.dragging { opacity: 0.4; }

.badge { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 0.75em; }
.badge-warn { background: var(--warn-bg); color: var(--amber-400); }
.badge-ok   { background: var(--success-bg); color: var(--success); }

/* Shared lifecycle status pill — used by Content Studio's lecture chips
   (.status-contract/.status-draft/.status-in_progress/.status-approved/
   .status-published) and Tools' generation chips (.status-draft/
   .status-generated). One vocabulary, one place to change the ramp. */
.status-pill {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 0.72em; font-weight: 600; letter-spacing: 0.02em;
  text-transform: uppercase; font-family: var(--f-display);
}
.status-contract   { background: var(--status-contract-bg);  color: var(--status-contract-fg); }
.status-draft      { background: var(--status-draft-bg);     color: var(--status-draft-fg); }
.status-in_progress{ background: var(--status-progress-bg);  color: var(--status-progress-fg); }
.status-approved   { background: var(--status-approved-bg);  color: var(--status-approved-fg); }
.status-published  { background: var(--status-published-bg); color: var(--status-published-fg); }
.status-generated  { background: var(--status-published-bg); color: var(--status-published-fg); }

.note {
  background: rgba(79,209,197,0.08); border: 1px solid var(--teal-700); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 0.85em; margin-bottom: 10px; color: var(--teal-400);
}
/* Links inside a .note otherwise fall back to the browser's default
   blue/purple, which reads as low-contrast and off-brand against the
   teal-tinted note background. Match the surrounding note text's teal
   accent instead, with an underline so it still reads as a link. */
.note a { color: var(--teal-400); text-decoration: underline; }
.note a:hover { color: var(--fog-100); }
.note-danger {
  background: var(--error-bg); border-color: var(--error); color: var(--error);
}

/* LinkedSelect — shared DB-backed multi-select widget (js/linked-select.js).
   Used for every "Linked SLO IDs" / "Chapter Topics" field so the pattern
   is styled once. Reuses the app's ink/teal tokens; no per-page overrides. */
.linked-select { margin-bottom: 4px; }
.linked-select .ls-chips {
  display: flex; flex-wrap: wrap; gap: 6px; min-height: 20px; margin-bottom: 8px;
}
.linked-select .ls-empty { color: var(--fog-400); font-size: 0.85em; font-style: italic; }
.linked-select .ls-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--success-bg); color: var(--success);
  border: 1px solid var(--teal-700); border-radius: 999px;
  padding: 3px 6px 3px 10px; font-size: 0.82em; line-height: 1.3;
}
.linked-select .ls-chip-x {
  border: none; background: transparent; color: inherit; cursor: pointer;
  font-size: 1.1em; line-height: 1; padding: 0 2px; border-radius: 50%;
}
.linked-select .ls-chip-x:hover { background: rgba(0,0,0,0.25); }
.linked-select .ls-controls { display: flex; gap: 8px; align-items: center; }
.linked-select .ls-picker { flex: 1; }
.linked-select .ls-addnew {
  white-space: nowrap; cursor: pointer; border: 1px dashed var(--teal-500);
  background: transparent; color: var(--teal-400); border-radius: var(--radius-sm);
  padding: 8px 12px; font-size: 0.85em; font-weight: 600; text-decoration: none;
  font-family: var(--f-display);
}
.linked-select .ls-addnew:hover { background: rgba(79,209,197,0.12); }
.linked-select .ls-addrow { display: flex; gap: 8px; align-items: center; }
.linked-select .ls-addrow .ls-addinput { flex: 1; }

/* Danger-zone collapsible — the repeated "Admin: Purge/Delete This X"
   <details> pattern on Worksheets, Storylines, Communications, Schedule.
   One reusable component instead of four hand-copied inline-style sets. */
.danger-zone { border: 2px solid var(--error); }
.danger-zone summary { cursor: pointer; color: var(--error); font-weight: bold; }

/* Text utilities — covers the handful of inline font-weight/display/color
   one-offs that recur across every page (form sub-labels, muted helper
   text, disabled-looking controls). */
.text-normal { font-weight: normal; }
.text-dim    { color: var(--fog-300); }
.text-muted  { color: var(--fog-400); }
.text-error  { color: var(--error); }
.text-accent { color: var(--teal-400); }
.inline      { display: inline; }
.hidden      { display: none; }
.is-disabled { opacity: 0.5; cursor: not-allowed; }

/* A checkbox sitting inline next to its own label text (e.g. "[ ] Required")
   should size to its box, not stretch to the full input width the base
   `input` rule gives text fields. */
.checkbox-inline { width: auto; }

/* Inline course/context picker rendered at the top of a .card instead of the
   shell's canonical sidebar/sub-tabs slot — the label sits beside the select
   and the whole row is separated from the card body by a hairline, so the
   picker reads as the heading of the content it drives. Opt a shell picker
   into this by marking it data-shell-picker="keep" (see shell.js). */
.card-picker {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-bottom: 14px; margin-bottom: 16px; border-bottom: 1px solid var(--ink-300);
}
/* When a .card-picker is the whole card (e.g. a course picker shared across
   multiple sibling .panel sections, so it can't live inside just one of
   their .card wrappers), it has no card content below it -- drop the
   separator hairline/margin it normally needs to divide itself from that
   content. */
.card-picker-card .card-picker { padding-bottom: 0; margin-bottom: 0; border-bottom: none; }
.card-picker label.shell-picker-label {
  margin: 0; white-space: nowrap;
  font-size: 0.72em; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--fog-400); font-family: var(--f-display);
}
.card-picker select { margin: 0; }

/* Layout utilities — the recurring flex/width one-offs. Small, generic,
   and reused across many pages instead of re-typing raw values inline. */
.flex-row       { display: flex; align-items: center; gap: 8px; }
.flex-row-wrap  { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.flex-between   { display: flex; justify-content: space-between; align-items: center; }
.flex-end       { display: flex; justify-content: flex-end; }
.flex-1  { flex: 1; }
.flex-1-4 { flex: 1.4; }
.m-0     { margin: 0; }
.mt-xs   { margin-top: 4px; }
.mt-sm   { margin-top: 8px; }
.mt-md   { margin-top: 12px; }
.mt-lg   { margin-top: 18px; }
/* Class Calendar's month label needs a fixed minimum width so ‹ Prev / Next ›
   don't visibly shift left/right as the label text length changes month to
   month (e.g. "May 2026" vs "September 2026"). */
.cal-month-label { min-width: 150px; text-align: center; display: inline-block; }
/* Live chapter_topic preview under the Textbook Chapters picker in the
   Design-the-Class-Day dialog — small, success-tinted helper text. */
.chapter-topic-preview { font-size: 0.85em; color: var(--success); }
.field-narrow  { width: 170px; }
.field-medium  { width: 220px; }
.field-wide    { width: 260px; }
.prose-narrow  { max-width: 640px; }
.prose-medium  { max-width: 760px; }
.divider-hr {
  height: 1px; background: var(--ink-300); margin: 6px 4px; border: none;
}
.toolbar { display: flex; gap: 8px; align-items: center; margin: 8px 0; flex-wrap: wrap; }

/* Content Studio "Actions" panel — 1 row x 4 columns (Save Contract,
   Mark Approved, Generate Draft, Publish HTML) so the four core lecture/
   slide/tool actions read as one clear workflow strip instead of a
   stacked column. Wraps to 2x2 on narrow columns rather than squeezing. */
.actions-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
}
.actions-grid button { width: 100%; }
.actions-grid-generate { position: relative; display: inline-flex; width: 100%; }
.actions-grid-generate .dink-trigger {
  position: absolute; top: -10px; right: -10px; margin-left: 0;
  background: var(--ink-050);
}
@media (max-width: 560px) {
  .actions-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---------------------------------------------------------------------
   Login gate — full ocean-scene background, mascot front and center.
   --------------------------------------------------------------------- */
#login-gate {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 12px;
  background:
    linear-gradient(180deg, rgba(6, 11, 20, 0.6), rgba(6, 11, 20, 0.82)),
    url('/admin/img/ocean-background.jpg') center / cover no-repeat;
  background-color: var(--ink-000);
}
#login-gate .box {
  text-align: center; background: rgba(16,28,47,0.85); backdrop-filter: blur(6px);
  padding: 36px 40px; border-radius: var(--radius); box-shadow: var(--shadow-md);
  border: 1px solid var(--ink-300);
}
#login-gate .mascot { height: 120px; margin-bottom: 8px; filter: drop-shadow(0 6px 18px rgba(79,209,197,0.5)); }
#login-gate #secretInput, #login-gate #secret-input { width: 260px; }
#login-gate h2 { font-family: var(--f-script); font-size: 2.1em; color: var(--teal-400); margin: 0 0 4px; font-weight: 400; }
#login-gate p.tagline { color: var(--fog-300); font-family: var(--f-display); font-size: 0.85em; margin: 0 0 16px; }

iframe#previewFrame { width: 100%; height: 900px; border: 1px solid var(--ink-300); border-radius: var(--radius-sm); background: #fff; }

/* ---------------------------------------------------------------------
   Shared image picker (openAssetPicker) — a portal modal used by the
   Slides "Attach art…" button and the Lectures "Insert image" toolbar
   button. Dark overlay + centered card, scrollable, theme vars only.
   --------------------------------------------------------------------- */
.asset-picker-overlay {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(6, 11, 20, 0.72);
}
.asset-picker-modal {
  width: 100%; max-width: 640px; max-height: 85vh; overflow-y: auto;
  background: var(--ink-100); border: 1px solid var(--ink-300);
  border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 20px;
}
.asset-picker-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 14px;
}
.asset-picker-title {
  margin: 0; font-family: var(--f-display); color: var(--teal-400); font-size: 1.1em;
}
.asset-picker-close {
  cursor: pointer; background: transparent; border: none; color: var(--fog-300);
  font-size: 1.6em; line-height: 1; padding: 0 4px; border-radius: var(--radius-sm);
}
.asset-picker-close:hover { color: var(--fog-100); }

/* Per-card "hide from this deck" affordance on Art & Visuals thumbnails.
   Solid ink-on-fog keeps it legible over arbitrary images (light or dark). */
.asset-hide-btn {
  position: absolute; top: 6px; right: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  background: var(--ink-000); color: var(--fog-100);
  border: 1px solid var(--ink-300); border-radius: 6px;
  font-size: 12px; line-height: 1; cursor: pointer;
}
.asset-hide-btn:hover { background: var(--ink-100); }
.asset-hide-btn:focus-visible { outline: 2px solid var(--fog-300); outline-offset: 1px; }
.asset-grid-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 0 8px; font-size: 12px; color: var(--fog-300);
}
.asset-picker-upload {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px;
}
.asset-picker-grid { min-height: 80px; }

/* Shared monospace console/log output block — used for Tools' generation
   output (#genOutput) and Content Studio's publish log. One dark surface,
   one mono stack, one teal-tinted readout color so both feel like the same
   "machine talking back" affordance. */
.console-output {
  background: var(--ink-000); border: 1px solid var(--ink-300); border-radius: var(--radius);
  padding: 14px; max-height: 360px; overflow-y: auto;
  font-family: var(--f-mono);
  font-size: 12.5px; line-height: 1.5; white-space: pre-wrap; color: var(--teal-400);
}
.console-output .log-line { color: var(--fog-100); }
.console-output .log-err  { color: var(--error); }
.console-output .log-ok   { color: var(--success); font-weight: 700; }

#toast {
  position: fixed; bottom: 20px; right: 20px; background: var(--ink-200); color: var(--fog-100);
  padding: 10px 16px; border-radius: var(--radius-sm); display: none; z-index: 200;
  box-shadow: var(--shadow-md); border: 1px solid var(--teal-700); font-family: var(--f-display);
}

/* ---------------------------------------------------------------------
   Squiddlr helper — floating mascot that offers tooltip guidance.
   Click to open/close a small speech bubble with contextual tips.
   --------------------------------------------------------------------- */
#squiddlr-helper {
  position: fixed; bottom: 24px; left: 24px; z-index: 150;
  display: flex; align-items: flex-end; gap: 10px;
}
#squiddlr-helper img {
  height: 68px; cursor: pointer; filter: drop-shadow(0 4px 14px rgba(79,209,197,0.45));
  transition: transform var(--transition);
  animation: squiddlr-bob 4s ease-in-out infinite;
}
#squiddlr-helper img:hover { transform: scale(1.08); }
@keyframes squiddlr-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}
#squiddlr-bubble {
  display: none; max-width: 260px; background: var(--ink-100); color: var(--fog-100);
  border: 1px solid var(--teal-700); border-radius: var(--radius); padding: 12px 14px;
  font-size: 0.85em; box-shadow: var(--shadow-md); position: relative; margin-bottom: 10px;
}
#squiddlr-bubble.open { display: block; }
#squiddlr-bubble::after {
  content: ''; position: absolute; bottom: -8px; left: 24px;
  border-width: 8px 8px 0; border-style: solid; border-color: var(--ink-100) transparent transparent;
}
#squiddlr-bubble strong { color: var(--teal-400); font-family: var(--f-display); }

/* Inline mascot tooltip helper, usable next to any field/button. */
.squiddlr-tip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; background: rgba(79,209,197,0.15);
  color: var(--teal-400); font-size: 0.75em; font-weight: 700; cursor: help;
  margin-left: 6px; position: relative; vertical-align: middle;
}
.squiddlr-tip:hover::after {
  content: attr(data-tip);
  position: absolute; bottom: 130%; left: 50%; transform: translateX(-50%);
  background: var(--ink-200); color: var(--fog-100); border: 1px solid var(--teal-700);
  padding: 8px 10px; border-radius: var(--radius-sm); font-size: 0.85em; font-weight: 400;
  white-space: normal; width: 220px; box-shadow: var(--shadow-md); z-index: 50;
}

/* ---------------------------------------------------------------------
   Visual calendar (month grid) — ocean-toned meeting/no-class cells.
   --------------------------------------------------------------------- */
.cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal-header h4 { margin: 0; }
.cal-nav button { background: var(--ink-200); color: var(--fog-100); }
/* Full width of its .subcard now that Class Calendar is a standalone tab
   (no longer sharing a row with a side-by-side table) -- the old 480px cap
   was a leftover from that retired .row-cal layout and just made every
   day cell (and the topic text inside it) cramped for no reason. */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.cal-dow { text-align: center; font-size: 0.75em; font-weight: 600; color: var(--fog-400); padding: 4px 0; font-family: var(--f-display); }
.cal-day {
  aspect-ratio: 1 / 1; min-height: 0; border: 1px solid var(--ink-300); border-radius: var(--radius-sm);
  padding: 4px 5px; font-size: 0.78em; background: var(--ink-050); position: relative; color: var(--fog-300); overflow: hidden;
}

/* Schedule & Topics now uses the .seg-toggle / .subcard tab pattern
   (Class Calendar / No-Class Dates / Schedule-Topics Bank as sibling
   tabs in one .card) instead of the old side-by-side .row-cal/.row-tables
   layout, so those column-width rules are retired along with the
   Class Schedule (computed) card they supported. */
.cal-day.empty { background: transparent; border: none; }
.cal-day .cal-date { font-weight: 600; color: var(--fog-200); }
.cal-day.meeting { background: rgba(79,209,197,0.10); border-color: var(--teal-500); }
.cal-day.meeting .cal-date { color: var(--teal-400); }
.cal-day.noclass { background: rgba(244,184,96,0.10); border-color: var(--amber-400); }
.cal-day.noclass .cal-date { color: var(--amber-400); }
.cal-day.today { box-shadow: inset 0 0 0 2px var(--error); }
.cal-chip { display: block; margin-top: 2px; font-size: 0.72em; line-height: 1.2; color: var(--fog-200); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-legend { display: flex; gap: 14px; margin-top: 10px; font-size: 0.8em; color: var(--fog-300); }
.cal-legend span { display: inline-flex; align-items: center; gap: 5px; }
.cal-legend .dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.dot-meeting { background: var(--teal-500); }
.dot-noclass { background: var(--amber-400); }

/* ===== Design a Class Day — split view (calendar drop targets + library) =====
   Two-column lego pattern: .day-split (grid) > .day-split-cal (calendar +
   day detail) | .day-split-lib (8 type chips + typeahead + draggable cards).
   Library cards are dragged onto calendar day cells (data-date drop targets).
   General enough to reuse for the Assignments builder (same drag-deck layer). */
.day-split { display: grid; grid-template-columns: 1.4fr 1fr; gap: 16px; margin-top: 12px; align-items: start; }
.day-split-cal, .day-split-lib {
  background: var(--ink-050); border: 1px solid var(--ink-300); border-radius: var(--radius-sm);
  padding: 12px; display: flex; flex-direction: column; gap: 10px;
}
.day-split-cal .cal-grid { gap: 4px; }
.day-split-cal .cal-day { min-height: 52px; }
.day-detail { border-top: 1px solid var(--ink-300); padding-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.day-detail-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.day-detail-empty { text-align: center; padding: 18px 8px; color: var(--fog-300); font-size: 0.9em; }
.text-small { font-size: 0.78em; }

/* library panel */
.catalog-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.catalog-chip {
  font-size: 0.78em; padding: 4px 10px; border-radius: 999px; cursor: pointer;
  background: transparent; border: 1px solid var(--ink-300); color: var(--fog-200);
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.catalog-chip:hover { border-color: var(--teal-400); color: var(--teal-400); }
.catalog-chip.active { background: var(--teal-500); border-color: var(--teal-500); color: var(--ink-000); font-weight: 600; }
.catalog-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; padding-right: 4px; }
.catalog-card {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 6px 8px;
  background: var(--ink-100); border: 1px solid var(--ink-300); border-radius: var(--radius-sm);
  padding: 8px 10px; cursor: grab; transition: border-color 0.15s, background 0.15s;
}
.catalog-card:hover { border-color: var(--teal-400); }
.catalog-card.dragging { opacity: 0.5; cursor: grabbing; }
.catalog-card-type { grid-row: span 2; font-size: 0.66em; text-transform: uppercase; letter-spacing: 0.04em;
  padding: 2px 6px; border-radius: var(--radius-sm); background: var(--ink-300); color: var(--fog-100); white-space: nowrap; }
.catalog-card-label { font-weight: 600; color: var(--fog-100); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.catalog-card-sub { grid-column: 2 / 4; font-size: 0.74em; color: var(--fog-300); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.catalog-card-open { grid-row: span 2; font-size: 0.78em; white-space: nowrap; }
.catalog-empty { text-align: center; padding: 20px 8px; font-size: 0.88em; }

/* drag-over highlight on calendar day cells */
.cal-day.drag-over { outline: 2px solid var(--teal-400); outline-offset: -2px; background: rgba(79,209,197,0.22); }
@media (max-width: 920px) {
  .day-split { grid-template-columns: 1fr; }
}

/* ===== Course workflow dashboard — stepper tiles + summary =====
   Lego-block pattern: .stepper-grid (responsive auto-fill) > .stepper-tile
   (a nav <a> or in-page <button>). Reused on the Course Builder landing's
   post-selection dashboard; general enough for any step/launch surface. */
.dash-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.dash-summary > div { display: flex; flex-direction: column; gap: 2px; }
.dash-label { font-size: 0.72em; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fog-400); }
.dash-value { font-weight: 600; color: var(--fog-100); }
.stepper-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; margin-top: 12px; }
.stepper-tile {
  display: flex; flex-direction: column; gap: 4px; text-align: left; text-decoration: none;
  background: var(--ink-050); border: 1px solid var(--ink-300); border-radius: var(--radius-sm);
  padding: 14px 16px; color: var(--fog-100); cursor: pointer; transition: border-color 0.15s, background 0.15s;
}
.stepper-tile:hover { border-color: var(--teal-500); background: rgba(79,209,197,0.08); }
.stepper-badge {
  display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px;
  border-radius: 50%; background: var(--teal-500); color: var(--ink-900); font-weight: 700; font-size: 0.85em;
  font-family: var(--f-display); margin-bottom: 4px;
}
.stepper-title { font-weight: 600; color: var(--teal-400); font-family: var(--f-display); }
.stepper-desc { font-size: 0.82em; color: var(--fog-300); line-height: 1.3; }
