@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", ui-sans-serif, sans-serif;
  color-scheme: light;
  --bg: #f7f6f3;
  --bg-desk: #efede8;
  --surface: #ffffff;
  --surface-glass: rgba(255, 255, 255, 0.88);
  --surface-subtle: #f3f2ee;
  --surface-active: #eae8e1;
  --ink: #141413;
  --ink-2: #4a4945;
  --ink-3: #6b6964;
  --muted: #6b6964;
  --line: rgba(20, 20, 19, 0.08);
  --line-strong: rgba(20, 20, 19, 0.13);
  --accent: #141413;
  --accent-contrast: #ffffff;
  --accent-soft: #f3f2ee;
  --accent-brand: #1e40af;
  --status-ok: #15803d;
  --status-warn: #b45309;
  --status-err: #b91c1c;
  --shadow: 0 1px 2px rgba(20, 20, 19, 0.05), 0 8px 24px -4px rgba(20, 20, 19, 0.08);
  --shadow-modal: 0 4px 12px rgba(20, 20, 19, 0.08), 0 24px 48px -12px rgba(20, 20, 19, 0.18);
  --r: 10px;
  --r-sm: 6px;
  --r-lg: 12px;
  --font-mono: "SFMono-Regular", "Cascadia Mono", "Consolas", monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  width: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  color: var(--ink);
  background: var(--bg);
  font-size: 13px;
}

body[data-theme=dark] {
  color-scheme: dark;
  --bg: #0d0e11;
  --bg-desk: #111215;
  --surface: #181a1f;
  --surface-glass: rgba(24, 26, 31, 0.86);
  --surface-subtle: #22252b;
  --surface-active: #2b2f37;
  --ink: #f3f2ee;
  --ink-2: #c2c0ba;
  --ink-3: #94928d;
  --muted: #94928d;
  --line: rgba(255, 255, 255, 0.08);
  --line-strong: rgba(255, 255, 255, 0.14);
  --accent: #f3f2ee;
  --accent-contrast: #141413;
  --accent-soft: #22252b;
  --status-ok: #4ade80;
  --status-warn: #fbbf24;
  --status-err: #f87171;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -4px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --shadow-modal: 0 8px 24px rgba(0, 0, 0, 0.5), 0 24px 60px -12px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

button, input, select, textarea { font: inherit; }

button { cursor: pointer; }

button:disabled { opacity: .45; cursor: default; }

button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid #7daaff;
  outline-offset: 2px;
}

.hidden { display: none !important; }

.view-screen { height: 100dvh; width: 100vw; overflow: auto; }

.btn {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  min-height: 38px;
  border-radius: 9px;
  padding: 9px 14px;
  font-weight: 600;
  white-space: nowrap;
  transition: background .12s, border .12s;
}

.btn:hover { background: var(--accent-soft); }

.btn-primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.btn-primary:hover { background: #1e55c9; }

.btn-secondary { background: var(--surface); }

.btn-ghost { border-color: transparent; background: transparent; }

.btn-danger { color: #b52945; }

.btn-sm { min-height: 32px; padding: 6px 10px; }

.btn-xs { min-height: 29px; padding: 5px 8px; font-size: 12px; }

.btn-icon { min-width: 37px; text-align: center; font-size: 16px; padding: 6px; }

.btn-block { width: 100%; }

.field-label { display: block; font-weight: 600; margin: 5px 0 8px; }

.text-input, .select-input {
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 9px;
  min-height: 40px;
  padding: 8px 11px;
  min-width: 0;
}

.text-input:focus, .select-input:focus { border-color: #81a5f3; }

.text-input::placeholder { color: #9ca7b8; }

.select-xs { min-height: 30px; padding: 3px 8px; font-size: 12px; }

.subtitle { color: var(--muted); margin: 4px 0; }

.brand-mark {
  height: 42px;
  width: 42px;
  display: block;
  flex: 0 0 42px;
  border-radius: 10px;
  overflow: hidden;
}

.brand-mark img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.view-screen h1, .view-screen h2, .view-screen h3 {
  margin: 0;
  letter-spacing: -.035em;
}

#login-view, #student-link-view, #student-join-view {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: radial-gradient(ellipse at 50% 0%, #e0eafc 0%, var(--bg) 60%);
}

.auth-card {
  max-width: 420px;
  width: 100%;
  padding: 34px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  box-shadow: var(--shadow);
}

.auth-brand { display: flex; align-items: center; gap: 14px; margin-bottom: 30px; }

.auth-brand h1 { font-size: 20px; }

.auth-card .text-input { width: 100%; margin-bottom: 20px; }

.error-banner {
  background: #ffe9ed;
  color: #9e1f39;
  border-radius: 9px;
  padding: 9px 12px;
  margin: 4px 0 12px;
}

.info-banner { padding: 10px; border: 1px solid var(--line); border-radius: 9px; margin: 12px 0; }

.dash-header {
  height: 85px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 clamp(20px, 5vw, 74px);
  gap: 16px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.dash-brand { display: flex; align-items: center; gap: 14px; }

.dash-brand h1 { font-size: 21px; }

.dash-header-actions { display: flex; gap: 9px; align-items: center; }

.dash-container { max-width: 1260px; margin: auto; padding: 28px 30px 65px; }

.create-notebook-bar {
  padding: 20px;
  border-radius: 15px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 3px 16px #182c4510;
  margin-bottom: 26px;
}

.create-nb-form { display: flex; gap: 14px; align-items: end; }

.form-group { display: flex; flex-direction: column; gap: 7px; flex: 1; min-width: 0; }

.form-group-sm { flex: .72; }

.form-group label { font-weight: 650; font-size: 12px; }

.list-filter-bar { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 17px; }

.search-input { width: min(400px, 100%); }

.filter-tabs { display: flex; gap: 3px; background: #e8edf5; border-radius: 11px; padding: 4px; }

.tab-btn { border: 0; background: transparent; color: #6c7b91; border-radius: 8px; padding: 8px 15px; font-weight: 650; }

.notebooks-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }

.notebook-card {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 22px;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  box-shadow: 0 3px 12px #1020350a;
}

.notebook-card h3 { font-size: 19px; }

.notebook-card p { margin: 0; color: var(--muted); }

.notebook-card small { margin-top: 12px; color: var(--muted); }

.card-actions { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 13px; }

.empty-state { text-align: center; color: var(--muted); padding: 42px; }

.follow-group { display: flex; align-items: center; gap: 6px; }

.modal-backdrop {
  position: fixed;
  z-index: 50;
  inset: 0;
  background: #101a2a99;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 20px;
}

.modal-card {
  background: var(--surface);
  border-radius: 17px;
  box-shadow: 0 25px 100px #0006;
  max-height: 94dvh;
  display: flex;
  flex-direction: column;
  width: min(1100px, 98vw);
  overflow: hidden;
}

/* Destructive confirmations stay narrow: one sentence and two buttons. */
.modal-sm {
  width: min(420px, calc(100vw - 32px));
  max-width: 420px;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: start;
  gap: 12px;
  padding: 18px 24px 14px;
  border-bottom: 1px solid var(--line);
}

.modal-header h2 { font-size: 19px; }

.pdf-modal-body { display: flex; gap: 0; padding: 0; overflow: hidden; min-height: 220px; }

.btn-group { display: flex; gap: 3px; }

.pdf-thumb {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 5px;
  color: var(--ink);
  font-size: 11px;
  font-weight: 650;
}

.pdf-clipper-pane { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 9px; }

.pdf-clipper-header { display: flex; justify-content: space-between; gap: 10px; align-items: center; }

.pdf-preview-stage {
  overflow: auto;
  max-height: min(62dvh, 720px);
  text-align: center;
  background: #dfe4ed;
  border-radius: 10px;
  position: relative;
  padding: 10px;
}

.pdf-preview-stage canvas {
  max-width: 100%;
  height: auto;
  touch-action: none;
  cursor: crosshair;
  display: block;
  margin: auto;
}

.pdf-crop-box {
  position: absolute;
  pointer-events: none;
  border: 2px dashed #ec5390;
  background: #ec53901c;
}

.modal-footer {
  padding: 14px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  border-top: 1px solid var(--line);
}

.modal-footer-actions { display: flex; gap: 8px; }

.checkbox-label { display: flex; align-items: center; gap: 7px; font-weight: 600; }

/* Position toasts above the bottom tool dock so they never obscure drawing tools */

.toast-container {
  position: fixed;
  z-index: 100;
  right: 18px;
  bottom: 72px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  pointer-events: none;
}

/* ==========================================================================
   Editorial refresh — warm paper, carbon ink, hairline structure.
   Component overrides live last so they win over the recovered legacy layer.
   ========================================================================== */

.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.icon {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
}

.icon-chevron { width: 11px; height: 11px; opacity: .55; }

#dash-theme-btn .icon-moon { display: block; }

#dash-theme-btn .icon-sun { display: none; }

body[data-theme=dark] #dash-theme-btn .icon-moon { display: none; }

body[data-theme=dark] #dash-theme-btn .icon-sun { display: block; }

html, body { background: var(--bg); }

body {
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", sans-serif;
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--ink); color: var(--accent-contrast); }

button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 32px; padding: 6px 10px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--ink);
  font-size: 12px; font-weight: 500; letter-spacing: -.005em;
  transition: background 100ms cubic-bezier(.2,0,0,1), border-color 100ms, color 100ms;
}

.btn:hover { background: var(--surface-subtle); }

.btn-primary { background: var(--ink); color: var(--accent-contrast); border-color: var(--ink); }

.btn-primary:hover { background: var(--ink-2); border-color: var(--ink-2); }

.btn-secondary { background: var(--surface); border-color: var(--line-strong); }

.btn-secondary:hover { background: var(--surface-subtle); }

.btn-ghost { background: transparent; border-color: transparent; }

.btn-ghost:hover { background: var(--surface-subtle); }

.btn-danger { color: var(--status-err); }

.btn-sm { min-height: 28px; padding: 4px 8px; }

.btn-xs { min-height: 26px; padding: 3px 7px; font-size: 11.5px; }

.btn-icon { min-width: 28px; width: 28px; height: 28px; padding: 0; font-size: 13px; }

.btn-block { width: 100%; }

button:disabled { opacity: .45; cursor: default; }

.field-label { display: block; margin: 0 0 6px; font-size: 11.5px; font-weight: 500; color: var(--ink-2); }

.text-input, .select-input {
  min-height: 32px; padding: 6px 9px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink);
  font-size: 12.5px; transition: border-color 100ms, box-shadow 100ms;
}

.text-input::placeholder { color: var(--ink-3); }

.text-input:focus, .select-input:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 8%, transparent);
  outline: none;
}

.select-xs { min-height: 28px; padding: 3px 7px; font-size: 11.5px; }

.subtitle { color: var(--ink-3); margin: 2px 0; font-size: 12px; }

.brand-mark { border-radius: 8px; overflow: hidden; background: transparent; }

.brand-mark img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* Login */

#login-view, #student-link-view, #student-join-view {
  display: flex; align-items: center; justify-content: center;
  padding: 24px; background: var(--bg);
}

.auth-card {
  width: 100%; max-width: 360px; padding: 28px;
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--shadow);
}

.auth-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 26px; }

.auth-brand .brand-mark { width: 32px; height: 32px; flex: 0 0 32px; }

.auth-brand h1 { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -.025em; }

.auth-brand .subtitle { margin-top: 2px; font-size: 11.5px; color: var(--ink-3); }

.auth-card .text-input { width: 100%; height: 38px; margin-bottom: 16px; font-size: 13px; }

.auth-card .btn-primary { width: 100%; height: 38px; font-size: 13px; }

.auth-hint { margin: 14px 0 0; color: var(--ink-3); font-size: 11.5px; text-align: center; }

.auth-status { margin: 0 0 12px; color: var(--ink-2); font-size: 12px; line-height: 1.5; }

.auth-status:empty { display: none; }

#google-signin-button { display: flex; justify-content: center; min-height: 40px; }

#google-signin-button:empty { min-height: 0; }

#google-login-retry { margin-top: 12px; }

.student-link-message { margin: 8px 0 0; color: var(--ink-2); font-size: 14px; line-height: 1.6; }

.error-banner {
  border: 1px solid color-mix(in srgb, var(--status-err) 22%, transparent);
  border-radius: var(--r-sm); padding: 8px 10px; margin: 0 0 12px;
  background: color-mix(in srgb, var(--status-err) 9%, var(--surface));
  color: var(--status-err); font-size: 12px;
}

.info-banner { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px; margin: 12px 0; }

/* Dashboard */

#dashboard-view { background: var(--bg); }

.dash-header {
  height: 52px; min-height: 52px; padding: 0 24px;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--line); background: var(--surface);
}

.dash-brand { display: flex; align-items: center; gap: 10px; }

.dash-brand .brand-mark { width: 26px; height: 26px; flex: 0 0 26px; border-radius: 6px; }

.dash-brand h1, .dash-brand-title { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.025em; }

.dash-header-actions { display: flex; align-items: center; gap: 2px; }

.dash-header-actions .btn { min-height: 28px; font-size: 11.5px; }

.dash-container { max-width: 1020px; margin: 0 auto; padding: 24px 24px 72px; }

.create-notebook-bar {
  margin: 0 0 26px; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface); box-shadow: none;
}

.create-nb-form { display: flex; align-items: flex-end; gap: 10px; }

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

.create-nb-form .form-group-name { flex: 1.1; min-width: 150px; }

.create-nb-form .form-group-subject { flex: 1.4; min-width: 180px; }

.create-nb-form .form-group-sm { flex: 0 0 126px; }

.create-nb-form label {
  margin: 0 0 5px; font-size: 10.5px; font-weight: 500;
  color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em;
}

.create-nb-form .text-input, .create-nb-form .select-input { width: 100%; height: 32px; }

.create-nb-form .btn-primary { height: 32px; padding: 0 16px; }

.list-filter-bar { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; }

.search-input { max-width: 280px; height: 32px; }

.filter-tabs {
  margin-left: auto; display: flex; gap: 0; padding: 2px;
  border-radius: var(--r-sm); background: var(--surface-subtle);
}

.tab-btn {
  padding: 5px 12px; border: 0; border-radius: 4px;
  background: transparent; color: var(--ink-3);
  font-size: 11.5px; font-weight: 500; box-shadow: none;
}

/* The applied filter must be visible; an empty list is otherwise unreadable. */
.tab-btn.active, .tab-btn[aria-selected="true"] {
  background: var(--surface); color: var(--ink); font-weight: 600;
  box-shadow: 0 1px 2px rgb(0 0 0 / .06);
}

.notebooks-grid {
  display: flex; flex-direction: column; gap: 1px;
  max-width: 1000px; border: 1px solid var(--line);
  border-radius: var(--r); background: var(--line); overflow: visible;
}

.notebook-card {
  display: flex; flex-direction: row; align-items: center; gap: 20px;
  min-height: 66px; padding: 14px 16px;
  border: 0; border-radius: 0; background: var(--surface); box-shadow: none;
}

.notebook-card:first-child { border-radius: calc(var(--r) - 1px) calc(var(--r) - 1px) 0 0; }

.notebook-card:last-child { border-radius: 0 0 calc(var(--r) - 1px) calc(var(--r) - 1px); }

.notebook-card:only-child { border-radius: calc(var(--r) - 1px); }

.notebook-card:hover { background: color-mix(in srgb, var(--surface-subtle) 55%, var(--surface)); }

.notebook-main { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 12px; }

.notebook-card h3 { margin: 0; min-width: 170px; font-size: 14px; font-weight: 600; letter-spacing: -.01em; }

.notebook-card p { margin: 0; color: var(--ink-2); font-size: 12px; }

.notebook-card small {
  flex-basis: 100%; margin: 0; color: var(--ink-3);
  font-family: var(--font-mono); font-size: 10.5px; font-variant-numeric: tabular-nums;
}

.notebook-card small.is-online { color: var(--status-ok); }

.card-actions { display: flex; flex-wrap: nowrap; align-items: center; gap: 1px; margin: 0; }

.nb-action { color: var(--ink-2); }

.nb-action:hover { color: var(--ink); background: var(--surface-subtle); }

.nb-action.btn-primary, .nb-action.btn-primary:hover { color: var(--accent-contrast); }

.notebook-card:has(.row-menu:not(.hidden)) {
  position: relative;
  z-index: 45;
}

.row-menu-wrap { position: relative; display: inline-flex; }

.row-menu-btn { color: var(--ink-3); font-size: 17px; padding: 0; }

.row-menu {
  top: calc(100% + 6px); right: 0; min-width: 164px;
  padding: 4px; z-index: 20;
}

.row-menu button { padding: 7px 8px; border-radius: 4px; font-size: 11.5px; }

.row-menu button.danger, #dash-tools-menu button { color: var(--ink); }

.row-menu button.danger { color: var(--status-err); }

#dash-tools-menu { top: calc(100% + 8px); right: 0; min-width: 190px; }

.empty-state {
  padding: 38px 24px; border: 1px dashed var(--line-strong); border-radius: var(--r);
  color: var(--ink-3); text-align: center; font-size: 12.5px; background: var(--surface);
}

/* Workspace chrome */

.back-btn span { font-size: 11.5px; }

.palm-btn, .export-btn { gap: 5px; }

.paper-select { max-width: 98px; }

/* Sidebar */

/* Canvas desk */

/* Contextual bars */

/* Text editor */

/* Dropdowns */

/* Modals and PDF clipper */

.modal-backdrop { background: rgba(20,20,19,.42); }

.modal-card {
  border: 1px solid var(--line-strong); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--shadow-modal);
}

.modal-header { padding: 14px 18px; border-bottom: 1px solid var(--line); }

.modal-header h2 { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: -.01em; }

.modal-header .subtitle { margin-top: 2px; font-size: 11.5px; color: var(--ink-3); }

.modal-footer { border-top: 1px solid var(--line); padding: 10px 14px; }

.pdf-modal-body { background: var(--surface); padding: 0; gap: 0; }

.pdf-thumbs-pane {
  width: 228px; flex: none; display: flex; flex-direction: column; overflow: hidden;
  padding: 10px; border-right: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface-subtle) 60%, var(--surface));
}

.pdf-thumbs-header {
  display: flex; flex-direction: column; align-items: stretch; gap: 6px;
  padding: 0 0 8px; margin-bottom: 10px; font-size: 11px;
  font-weight: 650; color: var(--ink-3);
}

.pdf-thumbs-header .btn-group { justify-content: flex-start; margin-left: -4px; }

.pdf-thumbs-grid {
  position: relative; display: block; flex: 1; min-height: 0; overflow: auto; padding: 0; overscroll-behavior: contain;
}

.pdf-thumb {
  position: relative; min-height: 0; padding: 0; overflow: hidden;
  border: 1px solid var(--line-strong); border-radius: 4px;
  background: #fff; box-shadow: none;
  display: flex; flex-direction: column;
}

.pdf-thumb-canvas { display: block; width: 100%; height: auto; background: #fff; }

.pdf-clipper-pane { background: var(--surface); }

.pdf-clipper-header { padding: 8px 14px; border-bottom: 1px solid var(--line); font-size: 11.5px; color: var(--ink-3); }

.pdf-preview-stage { background: var(--bg-desk); border-radius: 4px; margin: 12px 16px 16px; overflow: hidden; position: relative; }

#pdf-preview-canvas { border: 1px solid var(--line-strong); box-shadow: 0 2px 8px rgba(20, 20, 19, 0.08); }

.pdf-crop-box { position: absolute; pointer-events: none; border: 1.5px dashed #2563eb; background: transparent; box-shadow: 0 0 0 9999px rgba(20, 20, 19, 0.22); }

#pdf-clip-snippet-btn:disabled, .btn:disabled { background: var(--surface-subtle); color: var(--ink-3); border-color: var(--line); opacity: 1; }

/* Feedback */

.toast-container { position: fixed; right: 14px; bottom: 20px; z-index: 100; }

/* POL-30: one owning .toast rule. The recovered layer had a second copy that this
   one already overrode in every property except max-width and line-height, so
   those two move in here and that copy is gone. The look that painted: ink
   surface, accent-contrast text, 6 px radius, 8/11 px padding. --radius-sm also
   resolves outside the Workspace section: it is declared on :root, and there are
   two of those blocks. */
.toast {
  padding: 8px 11px; border-radius: var(--radius-sm);
  background: var(--ink); color: var(--accent-contrast);
  max-width: min(360px, 86vw); line-height: 1.35;
  font-size: 11.5px; box-shadow: var(--shadow);
}

.toast-error { background: var(--status-err); color: #fff; }

/* BUG-6: one theme-styled tooltip, positioned by bindTooltips(). POL-29: the
   label and its shortcut keycap stay on one line, so the box is one 24 px row;
   `max-content` keeps the width tied to the text wherever the tip is placed (a
   fixed box would otherwise shrink-to-fit the space left of its own edge), and
   the 320 px ceiling holds the longest control tip without wrapping it. The
   viewport term keeps that ceiling inside a phone: 16 px is the 8 px page gutter
   at each edge, the same number tipCeiling() in app.js applies. */
.tooltip {
  position: fixed; z-index: 110; width: max-content; max-width: min(320px, calc(100vw - 16px)); padding: 4px 8px;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); color: var(--ink);
  font-size: 12px; line-height: 1.2; box-shadow: var(--shadow);
  pointer-events: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  /* POL-29: ignored while `nowrap` applies; once a .prose row wraps, it lets a
     pasted title with no spaces ("TrigonometricIdentities…") break inside the
     box instead of running under the ellipsis. */
  overflow-wrap: anywhere;
  transform: translateX(-50%);
}
/* POL-29: only the switch rows' explanations are wider than the 320 px row, and
   their sentence exists nowhere else, so those wrap instead of being cut. */
.tooltip.prose { white-space: normal; }
.tooltip kbd {
  margin-left: 6px; padding: 1px 4px; border-radius: 3px;
  background: var(--surface-subtle); color: var(--ink-3);
  font-family: var(--font-mono); font-size: 10px;
}

/* Theme adjustments */

body[data-theme=dark] .notebook-card:hover { background: color-mix(in srgb, var(--surface-subtle) 55%, var(--surface)); }

body[data-theme=dark] .pdf-thumb-canvas { background: #fff; }

body[data-theme=dark] .auth-card { box-shadow: var(--shadow-modal); }

body[data-theme=dark] .text-input, body[data-theme=dark] .select-input {
  background: var(--bg);
  border-color: var(--line-strong);
}

input[type="checkbox"] { accent-color: var(--ink); }

.btn-ghost[aria-expanded="true"] {
  background: var(--surface-subtle);
  color: var(--ink);
}

/* ==========================================================================
   Canvas-first shell & unified production UI polish
   ========================================================================== */

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

@keyframes menuIn {
  from { opacity: 0; transform: translateY(-3px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes popUpIn {
  from { opacity: 0; transform: translate(-50%, 3px) scale(0.98); }
  to { opacity: 1; transform: translate(-50%, 0) scale(1); }
}

@keyframes modalCardIn {
  from { opacity: 0; transform: translateY(6px) scale(0.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes googleSkelShimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Login polish & skeleton */

.auth-status {
  margin: 0 0 12px;
  color: var(--ink-3);
  font-size: 12px;
  font-weight: 500;
  text-align: center;
  line-height: 1.45;
}

.auth-status:empty { display: none; }

.google-btn-skeleton {
  width: 240px;
  max-width: 100%;
  height: 40px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: linear-gradient(90deg, var(--surface-subtle) 25%, var(--surface-active) 50%, var(--surface-subtle) 75%);
  background-size: 200% 100%;
  animation: googleSkelShimmer 1.4s ease-in-out infinite;
}

/* Dashboard hierarchy, cards, and notebook-creation dialog */

#dashboard-view { overflow-y: auto; }

.dash-container { max-width: 1040px; padding: 38px 24px 72px; }

.dash-title-row {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; margin: 0 0 24px;
}

.dash-title-row h1 {
  margin: 0; font-size: 26px; font-weight: 600;
  letter-spacing: -.04em; line-height: 1.1;
}

.dash-meta { margin: 5px 0 0; color: var(--ink-3); font-size: 12px; }

#new-notebook-btn { height: 34px; padding: 0 13px; gap: 6px; }

#new-notebook-btn .icon { width: 14px; height: 14px; }

.notebooks-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 1040px;
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 0;
  overflow: visible;
}

.notebook-card, .notebook-card:first-child, .notebook-card:last-child, .notebook-card:only-child {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: 14px;
  min-height: 64px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(20, 20, 19, 0.03);
  transition: border-color 120ms ease, background 120ms ease, box-shadow 120ms ease;
  cursor: pointer;
}

.notebook-card:hover {
  border-color: var(--line-strong);
  background: var(--surface-subtle);
  box-shadow: 0 2px 8px rgba(20, 20, 19, 0.05);
}

.student-avatar {
  width: 36px;
  height: 36px;
  min-width: 36px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.02em;
  user-select: none;
  flex-shrink: 0;
}

.student-avatar[data-palette="0"] { background: rgba(37, 99, 235, 0.12); color: #1d4ed8; }

.student-avatar[data-palette="1"] { background: rgba(5, 150, 105, 0.12); color: #047857; }

.student-avatar[data-palette="2"] { background: rgba(217, 119, 6, 0.13); color: #b45309; }

.student-avatar[data-palette="3"] { background: rgba(124, 58, 237, 0.12); color: #6d28d9; }

.student-avatar[data-palette="4"] { background: rgba(219, 39, 119, 0.12); color: #be185d; }

.student-avatar[data-palette="5"] { background: rgba(2, 132, 199, 0.12); color: #0369a1; }

body[data-theme=dark] .student-avatar[data-palette="0"] { background: rgba(96, 165, 250, 0.16); color: #93c5fd; }

body[data-theme=dark] .student-avatar[data-palette="1"] { background: rgba(52, 211, 153, 0.16); color: #6ee7b7; }

body[data-theme=dark] .student-avatar[data-palette="2"] { background: rgba(251, 191, 36, 0.16); color: #fcd34d; }

body[data-theme=dark] .student-avatar[data-palette="3"] { background: rgba(192, 132, 252, 0.16); color: #d8b4fe; }

body[data-theme=dark] .student-avatar[data-palette="4"] { background: rgba(244, 114, 182, 0.16); color: #f9a8d4; }

body[data-theme=dark] .student-avatar[data-palette="5"] { background: rgba(56, 189, 248, 0.16); color: #7dd3fc; }

.notebook-card p.notebook-subject.notebook-subject-pill, .notebook-subject-pill {
  margin: 0;
  display: inline-block;
  background: transparent;
  padding: 0;
  border-radius: 0;
  font-size: 11.5px;
  color: var(--ink-2);
  font-weight: 500;
  line-height: 1.4;
}

.notebook-main {
  flex: 1 1 200px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

.notebook-title-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  min-width: 0;
  max-width: 100%;
}

.notebook-card h3 {
  margin: 0;
  min-width: 0;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.notebook-card p.notebook-subject {
  margin: 0;
  color: var(--ink-3);
  font-size: 12.5px;
  font-weight: 400;
}

.notebook-card small, .notebook-card small.is-online {
  flex-basis: auto;
  margin: 0;
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
  color: var(--ink-3);
  font-family: inherit;
  font-size: 12px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

.meta-dot-sep {
  white-space: pre;
  color: var(--ink-3);
}

.online-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--status-ok);
  font-weight: 500;
}

.online-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--status-ok);
  flex: none;
}

.card-actions {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 6px;
  margin: 0 0 0 auto;
}

.nb-action {
  height: 30px;
  min-height: 30px;
  padding: 0 11px;
  font-size: 12px;
  font-weight: 500;
  border-radius: 6px;
}

.nb-action.btn-secondary {
  color: var(--ink-2);
  border-color: var(--line-strong);
  background: var(--surface);
}

.nb-action.btn-secondary:hover {
  color: var(--ink);
  background: var(--surface-subtle);
}

.nb-action.btn-primary, .nb-action.btn-primary:hover {
  color: var(--accent-contrast);
}

.row-menu-wrap { position: relative; display: inline-flex; }

.row-menu-btn {
  width: 30px;
  height: 30px;
  min-width: 30px;
  color: var(--ink-3);
  font-size: 17px;
  padding: 0;
  border-radius: 6px;
}

.row-menu-btn:hover { color: var(--ink); background: var(--surface-subtle); }

.row-menu {
  top: calc(100% + 6px);
  right: 0;
  left: auto;
  min-width: 168px;
  padding: 4px;
  z-index: 30;
}

.empty-state {
  margin: 0;
  padding: 42px 24px;
  border: 1px dashed var(--line-strong);
  border-radius: 10px;
  color: var(--ink-3);
  text-align: center;
  font-size: 13px;
  background: var(--surface);
}

/* Workspace shell */

/* Header floating islands */

/* Save status pill: quiet checkmark when saved, semantic badge when syncing/offline */

/* Unified Dropdowns & Overflow Menu */

.menu-toggle-title {
  white-space: nowrap;
}

/* Page tray floating over the canvas */

/* Main dock: always a compact centered floating island */

/* Main dock: unified 40px height rhythm floating instrument */

/* History and zoom floating islands */

@keyframes menuUpIn {
  from { opacity: 0; transform: translateY(3px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Insert menu opens above the dock */

/* Tool settings popover - sleek 236px instrument card */

/* Modals */

.modal-card {
  animation: modalCardIn 140ms cubic-bezier(0.2, 0, 0, 1);
}

/* A card focused on open (so no input raises the soft keyboard) is a container,
   not a control: it takes focus without drawing a ring. */
.modal-card[tabindex="-1"]:focus { outline: none; }

.new-notebook-modal {
  width: min(420px, calc(100vw - 32px));
  max-width: 420px;
}

.new-notebook-modal .modal-header { padding: 16px 18px 14px; }

.new-notebook-modal .create-nb-form {
  display: flex; flex-direction: column; align-items: stretch;
  gap: 14px; padding: 18px;
}

.new-notebook-modal .form-group, .new-notebook-modal .form-group-name, .new-notebook-modal .form-group-subject, .new-notebook-modal .form-group-sm { flex: 1 1 auto; width: 100%; }

.new-notebook-modal .text-input, .new-notebook-modal .select-input { width: 100%; height: 36px; }

.modal-form-actions {
  display: flex; justify-content: flex-end; gap: 6px;
  padding-top: 4px;
}

.qr-modal { width: min(380px, calc(100vw - 32px)); max-width: 380px; }

.qr-body { padding: 22px; text-align: center; }

.qr-code {
  display: grid; place-items: center;
  width: 216px; height: 216px; margin: 0 auto;
  border: 1px solid var(--line); border-radius: 8px;
  background: #fff;
}

.qr-code svg { display: block; width: 196px; height: 196px; }

.qr-caption { margin: 14px auto 0; max-width: 280px; color: var(--ink-2); font-size: 12px; line-height: 1.45; }

/* Unified Responsive Breakpoints */

@media (max-width: 900px) {

.back-btn span { display: none; }

.dash-container { padding: 28px 18px 64px; }

}

@media (max-width: 640px) {

/* Dashboard */

.dash-header { height: 52px; min-height: 52px; padding: 0 14px; gap: 8px; }

.dash-brand { gap: 8px; min-width: 0; }

.dash-brand h1, .dash-brand-title { font-size: 14px; white-space: nowrap; }

.dash-brand .brand-mark { width: 24px; height: 24px; flex-basis: 24px; }

.dash-header-actions { flex-wrap: nowrap; gap: 2px; }

.dash-header-actions .btn { font-size: 11px; padding: 4px 7px; }

.dash-container { padding: 24px 16px 56px; }

.dash-title-row { align-items: center; }

.dash-title-row h1 { font-size: 22px; }

#new-notebook-btn { height: 32px; padding: 0 10px; font-size: 11.5px; }

.auth-card { padding: 22px; }

.list-filter-bar { flex-direction: column; align-items: stretch; gap: 10px; }

.search-input { max-width: none; width: 100%; }

.filter-tabs { margin-left: 0; align-self: flex-start; }

.notebook-card { padding: 12px 14px; gap: 10px 12px; }

/* The subject always takes its own line: sharing a row with the name only when it fits made
   consecutive cards different heights at the same mobile width. */
.notebook-title-row { flex-direction: column; align-items: flex-start; gap: 4px; }

/* Workspace floating bars & dock */

/* PDF modal on narrow screens */

.pdf-modal-body { flex-direction: column; overflow: auto; }

.pdf-thumbs-pane { width: 100%; height: 232px; max-height: none; border-right: 0; border-bottom: 1px solid var(--line); }

.pdf-thumbs-grid { display: block; min-height: 106px; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x proximity; scroll-padding-inline: 4px; }

/* The strip packs whole columns per view (app.js); the button must not force a wider cell. */
.pdf-thumb { min-width: 0; }

.pdf-thumb-item { scroll-snap-align: start; }

.modal-header { padding: 12px 14px; }

.modal-footer { flex-wrap: wrap; }

.modal-footer-actions { width: 100%; flex-wrap: wrap; }

.pdf-clipper-header { flex-wrap: wrap; }

}

@media (max-width: 560px) {

.notebook-card, .notebook-card:first-child, .notebook-card:last-child, .notebook-card:only-child {
    flex-wrap: wrap;
    align-items: flex-start;
    padding: 14px;
    gap: 10px 12px;
  }

.notebook-main {
    flex: 1 1 calc(100% - 52px);
  }

.card-actions {
    flex: 1 1 100%;
    width: 100%;
    margin-left: 0;
    padding-top: 8px;
    border-top: 1px solid var(--line);
    justify-content: flex-start;
  }

.row-menu-wrap {
    margin-left: auto;
  }

}

/* ==========================================================================
   Remediation pass: chrome, accessibility, selection, PDF, join
   ========================================================================== */

/* Toggle: 30x18 border-box with a 12px knob and 2px clearance in both states. */

#dash-tools-menu {
  left: 0;
  right: auto;
  width: 168px;
  min-width: 0;
  top: calc(100% + 8px);
}

/* Portalled page menu: fixed coordinates come from the trigger rect. */

.student-link-message { text-align: center; }

input[type="search"]::-webkit-search-cancel-button {
  filter: grayscale(1);
  opacity: .65;
}

/* Selection mode segmented control */

/* PDF crop handles and selectable thumbnails */

.pdf-crop-box { pointer-events: none; }

.pdf-crop-handle {
  position: absolute;
  width: 8px;
  height: 8px;
  border: 1px solid #2563eb;
  border-radius: 1px;
  background: #fff;
  pointer-events: auto;
  z-index: 2;
}

.pdf-crop-handle[data-corner="nw"] { left: -5px; top: -5px; cursor: nwse-resize; }

.pdf-crop-handle[data-corner="ne"] { right: -5px; top: -5px; cursor: nesw-resize; }

.pdf-crop-handle[data-corner="sw"] { left: -5px; bottom: -5px; cursor: nesw-resize; }

.pdf-crop-handle[data-corner="se"] { right: -5px; bottom: -5px; cursor: nwse-resize; }

.pdf-thumb-item {
  position: absolute;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: #fff;
}

.pdf-thumb-item.selected { border-color: var(--line-strong); }

.pdf-thumb-item.current { border-color: var(--ink); }
.pdf-thumb-item.current .pdf-thumb-select { background: var(--surface-subtle); font-weight: 650; }

.pdf-thumb-item .pdf-thumb {
  width: 100%;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: #fff;
  box-shadow: none;
  outline: none;
}

.pdf-thumb-item .pdf-thumb.selected, .pdf-thumb-item .pdf-thumb.current { border: 0; box-shadow: none; outline: none; }

.pdf-thumb-item .pdf-thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.pdf-thumb-item .pdf-thumb-canvas { display: block; width: 100%; height: 128px; object-fit: contain; }
.pdf-thumb-space { pointer-events: none; min-width: 1px; min-height: 1px; }
.pdf-page-entry { display: flex; align-items: center; gap: 5px; white-space: nowrap; font-weight: 400; }
.pdf-page-entry input { width: 57px; min-width: 0; padding: 4px; border: 1px solid var(--line-strong); border-radius: 4px; color: var(--ink); background: var(--surface); font-size: 11px; }
.pdf-range-entry { display: grid; gap: 4px; font-weight: 400; }
.pdf-range-entry input { width: 100%; min-width: 0; padding: 6px; border: 1px solid var(--line-strong); border-radius: 4px; color: var(--ink); background: var(--surface); font-size: 12px; }
.pdf-import-progress { width: 100%; color: var(--ink-2); font-size: 12px; }
@media (max-width:640px) { .pdf-thumb-item .pdf-thumb-canvas { height: 72px; } .pdf-thumbs-pane { height: 206px; } .pdf-thumbs-header { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 6px; margin-bottom: 5px; } .pdf-page-entry { grid-column: 1 / -1; } .pdf-thumbs-header > span { display: none; } .pdf-thumbs-header .btn-group { gap: 0; margin: 0; } }

.pdf-thumb-select {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 6px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 10.5px;
  font-weight: 500;
  cursor: pointer;
}

.pdf-thumb-check {
  appearance: auto;
  width: 14px;
  height: 14px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  accent-color: var(--ink);
}

/* Student join request and tutor banner */

@keyframes joinPulse { 50% { opacity: .35; } }

/* The save pill can still grow to "3 pending · offline" at this width.
     Presence avatars move to the follow banner rather than squeezing the
     notebook identity into the action cluster. */

/* 320px cannot carry the 44px touch rhythm across ten controls. Keep every
     control fully inside the viewport instead of clipping the undo/redo pair. */

@media (prefers-reduced-motion: reduce) {

*, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

}

/* ==========================================================================
   Workspace system. This is the single home for workspace component rules.
   Hierarchy: work surface → global rail → drawing instrument → contextual UI.
   State: neutral routine status, one active fill per control family, one canvas selection outline.
   Keep shared/login/dashboard styling above; do not append competing refreshes.
   ========================================================================== */
:root {
  --work-paper: #fff;
  --work-desk: #f0f1f3;
  --work-selected: #edf1f8;
  /* POL-23: the active instrument needs a stronger fill and a ring of its own;
     --work-selected is 1.13:1 against the dock, so a pen's hover hid it. Light
     reuses the brand accent; the dark block replaces it. */
  --work-active-fill: #dfe8f7;
  --work-active-ring: var(--accent-brand);
  --work-selection: #5279bd;
  --work-shadow: 0 1px 3px #17212e0a, 0 6px 20px #17212e0b;
  /* POL-30: every workspace radius is one of these three, in both themes. sm is
     a control or an inner row, md a surface, pill anything fully rounded: 999 px
     clamps to half the box, so a 16 px track keeps its 12 px knob seated. */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-pill: 999px;
  /* Peer palette: cursors, presence avatars and page pills share these. Light
     values are dark enough for white pill text; dark values invert that. Each
     peer hue stays ≥30° from every pen colour (in both themes' display values),
     so a peer cursor or view frame can never read as ink. */
  --peer-tutor: #127572;
  --peer-student: #b8168d;
  --peer-ink: #fff;
}
body[data-theme=dark] {
  --work-paper: #191b20;
  --work-desk: #121419;
  --work-selected: #2a303c;
  --work-active-fill: #26324a;
  --work-active-ring: #8eb3ee;
  --work-selection: #8eb3ee;
  --work-shadow: 0 1px 3px #0003, 0 6px 20px #0003;
  /* Light peer colours read on the dark sheet, so pill text is near-black. The
     two hues match light mode; only their lightness changes. */
  --peer-tutor: #68e6e2;
  --peer-student: #f23dc2;
  --peer-ink: #101114;
}
#workspace-view { position: fixed; inset: 0; display: flex; flex-direction: column; overflow: clip; background: var(--work-desk); }
.top-strip { position: relative; z-index: 40; display: flex; align-items: center; justify-content: space-between; gap: 24px; height: 60px; min-height: 60px; padding: 0 18px; background: var(--surface); border-bottom: 1px solid var(--line); }
.top-strip-left, .top-strip-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
.top-strip-left { flex: 1; }
.top-strip-right { flex: none; }
.top-strip .btn { min-height: 36px; border-radius: var(--radius-sm); font-size: 12px; }
/* POL-24: a square target keeps its size: 36x36 from 641 px up, 32x36 on a
   phone. Without the min-width the generic 28 px minimum let Back shrink to
   28x36 when the find button joined the rail. */
.top-strip .btn-icon { width: 36px; min-width: 36px; height: 36px; flex: none; }
.top-strip .icon { width: 17px; height: 17px; }
.top-divider { height: 24px; width: 1px; margin: 0 6px; background: var(--line); flex: none; }
.page-badge { color: var(--ink-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.nb-identity { display: flex; align-items: center; min-width: 0; padding: 4px 6px; border-radius: var(--radius-sm); }
.nb-identity[tabindex="0"] { cursor: pointer; }
.nb-identity[tabindex="0"]:hover { background: var(--surface-subtle); }
.nb-identity-text { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.nb-title { font-size: 13px; font-weight: 600; line-height: 1.35; letter-spacing: -.015em; }
.nb-subject-badge { font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.3; }
.nb-title, .nb-subject-badge { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 330px; }
.nb-subject-badge:empty { display: none; }
.nb-edit-btn { display: none !important; }
.save-pill { display: inline-flex; align-items: center; justify-content: center; gap: 4px; min-height: 30px; padding: 3px 6px; border: 0; border-radius: var(--radius-sm); background: transparent; font-size: 11px; font-weight: 400; color: var(--ink-3); white-space: nowrap; flex: none; }
.save-pill .status-check { width: 13px; height: 13px; }
.save-pill.pending, .save-pill.offline { color: var(--status-warn); background: color-mix(in srgb, var(--status-warn) 7%, var(--surface)); }
.save-pill:not(.saved) .status-check { display: none; }
.save-pill:not(.saved):hover { background: color-mix(in srgb, var(--status-warn) 12%, var(--surface)); }
.rtt-badge { display: none; }
.presence-strip { display: flex; gap: 4px; align-items: center; margin-right: 6px; }
/* POL-26: one outline pill for a peer, in the header and at the stage edge: a
   surface fill, one hairline, 34 px tall, 16 px radius, 11 px/500. The 24 px face
   is inset 5 px on every side, so the POL-25 ring's 4 px spread stops 1 px short
   of the border at every width: at 32 px it reached the outer edge and the
   status colour showed through the hairline, which is only 13% opaque. The solid
   peer fill stays on the face and the cursor: behind the face it would erase
   both the initial and the POL-25 status ring. */
.presence-avatar { position: relative; display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 8px 0 4px; border: 1px solid var(--line-strong); border-radius: var(--radius-pill); background: var(--surface); font-size: 11px; font-weight: 500; color: var(--ink-2); }
.presence-avatar:hover { background: var(--surface-subtle); color: var(--ink); }
.presence-avatar.following { background: var(--work-selected); color: var(--ink); }
.presence-initial { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: var(--radius-pill); background: var(--peer-student); color: var(--peer-ink); font-size: 11px; font-weight: 600; box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--status-ok); }
.presence-avatar.tutor .presence-initial { background: var(--peer-tutor); }
.presence-name { max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* POL-25: presence is a 2 px ring around the face, not a dot over it. The 2 px
   surface gap keeps the status colour off the peer fill: a status colour dark
   enough to reach 3:1 there is near-black, and green and amber would then be
   indistinguishable at 2 px. So the ring's 3:1 target is the rail it sits on.
   The 8 px face-to-name gap leaves 4 px clear of the 4 px ring, the same 4 px as
   the chip's left padding. */
.presence-avatar[data-presence="hidden"] .presence-initial, .presence-avatar[data-presence="unfocused"] .presence-initial, .presence-avatar[data-presence="slow"] .presence-initial { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--status-warn); }
.presence-more { display: inline-flex; align-items: center; height: 24px; padding: 0 6px; border-radius: var(--radius-pill); background: var(--surface-subtle); color: var(--ink-3); font-size: 10px; font-weight: 500; }
@media (max-width: 899px) {
  /* POL-26: with the name hidden the pill is the 24 px face and its ring and
     nothing else, so the 8 px trailing padding buys nothing: 4 px each side keeps
     the same 1 px clearance inside the same 34 px pill. A 32 px box made the ring
     reach the outer edge and paint over the hairline, so a peer lost the pill on a
     tablet and a phone. */
  .presence-avatar { padding: 0 4px; }
  /* POL-26: the narrow pill is 2 px wider than the 32 px one POL-24 measured the
     notebook name against, so the strip takes those 2 px back out of its
     trailing margin and the name keeps its 13-character floor at 720 with one
     student. With two or more peers the name is at its cap and the 4 px gap
     between the strip and the actions stays. */
  .presence-strip { margin-right: 4px; }
  .presence-name { display: none; }
}
#ws-follow-btn[aria-pressed="true"] { background: var(--work-selected); }
#workspace-view[data-role="student"] .presence-strip { display: flex; }
.workspace-body { flex: 1; min-height: 0; position: relative; display: flex; overflow: clip; }
.canvas-stage { flex: 1; min-width: 0; height: 100%; position: relative; overflow: clip; background: var(--work-desk); touch-action: none; overscroll-behavior: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; outline: 0; cursor: var(--pen-cursor, crosshair); }
.stage-canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; touch-action: none; }
.canvas-stage[data-tool="select"] { cursor: default; }
/* CHROME-3: the eraser paints its own ring, so the OS pointer would sit inside it. */
.canvas-stage[data-tool="eraser"] { cursor: none; }
.canvas-stage[data-tool="text"] { cursor: text; }
.canvas-stage[data-tool="pan"] { cursor: grab; }
.canvas-stage.panning { cursor: grabbing !important; }
.canvas-stage.drag-over { box-shadow: inset 0 0 0 2px var(--work-selection); }

/* Shared floating surfaces: one border, one elevation, unboxed interior actions. */
.floating-bar, .tool-popover, .selection-toolbar, .page-sidebar, .follow-banner, .join-request-banner { border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--work-shadow); cursor: default; }
.dropdown-wrap { position: relative; }
.dropdown-menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 50; min-width: 190px; max-height: calc(100dvh - 80px); overflow-y: auto; padding: 6px; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--work-shadow); touch-action: pan-y; }
.dropdown-menu button { display: flex; align-items: center; gap: 9px; width: 100%; min-height: 34px; padding: 7px 9px; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-2); text-align: left; font-size: 12px; font-weight: 400; white-space: nowrap; }
.dropdown-menu button:hover { background: var(--surface-subtle); color: var(--ink); }
.more-menu { width: 242px; max-width: calc(100vw - 24px); }
.menu-row .icon { width: 16px; height: 16px; flex: none; color: var(--ink-3); }
.menu-divider { height: 1px; background: var(--line); margin: 6px 7px; }
.menu-field { padding: 5px 8px 6px; }
.menu-field > label { display: block; margin-bottom: 8px; color: var(--ink-3); font-size: 11px; font-weight: 500; }
.paper-segmented { display: flex; gap: 4px; }
.dropdown-menu .paper-seg-btn { flex: 1; justify-content: center; min-height: 30px; padding: 5px; text-align: center; }
.paper-seg-btn.active { background: var(--work-selected); color: var(--ink); }
.menu-toggle { justify-content: space-between; }
.menu-toggle-info, .menu-toggle-ctrl { display: inline-flex; align-items: center; gap: 9px; }
/* LAT-1: the estimate lives on the switch row as well as in the chip tooltip,
   because a pen or touch never opens a tooltip (DEC-10). */
.menu-toggle-text { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-width: 0; }
.menu-toggle-sub { color: var(--ink-3); font-size: 10px; font-weight: 400; line-height: 1.35; white-space: nowrap; }
.toggle-pill { width: 28px; height: 16px; position: relative; border-radius: var(--radius-pill); background: var(--line-strong); flex: none; }
.toggle-knob { position: absolute; top: 2px; left: 2px; height: 12px; width: 12px; border-radius: var(--radius-pill); background: var(--surface); box-shadow: 0 1px 2px #0002; transition: transform 120ms ease; }
/* POL-30: an on switch is the POL-23 accent, not the black ink track. A 2 px
   inset ring on the 16 px track would leave its 12 px knob flush against the ring
   with no gap at all, so the pale --work-active-fill is the track and the accent
   ring colour moves to the knob: the same --work-active-* pair, one subtle fill
   per selected state. */
.menu-toggle[aria-checked="true"] .toggle-pill, .popover-toggle[aria-checked="true"] .toggle-pill { background: var(--work-active-fill); }
.menu-toggle[aria-checked="true"] .toggle-knob, .popover-toggle[aria-checked="true"] .toggle-knob { transform: translateX(12px); background: var(--work-active-ring); }

/* One movable instrument. Stroke samples carry colour, width and line pattern. */
.tool-dock { position: absolute; z-index: 30; bottom: 18px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; width: max-content; height: 54px; padding: 6px 8px 6px 4px; touch-action: none; }
.tool-dock[data-positioned="true"] { bottom: auto; transform: none; }
.tool-dock[data-dragging="true"] { cursor: grabbing; box-shadow: 0 4px 24px #17212e24; }
.dock-grip { display: flex; align-items: center; justify-content: center; width: 22px; height: 38px; flex: none; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-3); cursor: grab; touch-action: none; }
.dock-grip .icon { width: 12px; height: 22px; stroke-width: 2.5; }
.dock-grip:hover { color: var(--ink); background: var(--surface-subtle); }
.dock-grip:active { cursor: grabbing; }
.history-hud, .preset-group { display: flex; align-items: center; gap: 2px; }
.history-hud { padding-right: 4px; }
.tool-dock .tool-btn { display: inline-flex; align-items: center; justify-content: center; width: 38px; min-width: 38px; height: 40px; padding: 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-2); }
.tool-dock .tool-btn:hover { background: var(--surface-subtle); color: var(--ink); }
.tool-dock .tool-btn.active { background: var(--work-active-fill); color: var(--ink); box-shadow: inset 0 0 0 2px var(--work-active-ring); }
.tool-dock .tool-btn .icon { height: 19px; width: 19px; }
.tool-dock .pen-preset-btn { width: 44px; min-width: 44px; }
.swatch-dot { display: flex; width: 38px; height: 26px; color: var(--pen-colour); }
.preset-stroke { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; }
.dock-divider { display: none; }
/* HUD-1: zoom is a dock group at the grip end, so it shares the dock's 54 px
   surface and 40x40 targets instead of floating as a second pill. The value
   reads Fit at the fit zoom, so it needs a touch more width than an icon. */
.zoom-group { display: flex; align-items: center; gap: 2px; }
/* HUD-2: the owner's half of a 1280 px laptop is 640 px and has no pinch there,
   so the three controls keep 40 px targets in the dock's phone layout too, where
   the other instruments shrink to 36. A side-snapped dock keeps its 38 px column
   (HUD-1) so the three still share one column at a desktop height. */
.tool-dock:not([data-side]) .zoom-group .tool-btn:not(.zoom-value) { width: 40px; min-width: 40px; }
.tool-dock .zoom-value { width: 48px; min-width: 48px; height: 40px; font-size: 11px; font-variant-numeric: tabular-nums; }
.tool-dock > .dropdown-wrap { margin-left: 2px; }
.insert-menu { top: auto; bottom: calc(100% + 12px); width: 176px; min-width: 176px; }
.tool-dock[data-menu-below="true"] .insert-menu { bottom: auto; top: calc(100% + 12px); }
/* Snapped to a side, the dock stands vertical so it never overhangs the sheet;
   its insert menu opens toward the sheet, bottom-aligned with the + button. */
.tool-dock[data-side] { flex-direction: column; width: max-content; height: auto; padding: 4px 6px 6px; }
.tool-dock[data-side] .history-hud, .tool-dock[data-side] .preset-group { flex-direction: column; }
/* HUD-1: vertical, zoom in sits on top so the pair reads like a magnifier.
   The value shrinks to the button width so all three share one column. */
.tool-dock[data-side] .zoom-group { flex-direction: column-reverse; }
.tool-dock[data-side] .zoom-value { width: 38px; min-width: 38px; height: 28px; font-size: 10px; }
/* A stage too short for the whole vertical dock drops the zoom group rather
   than the side the tutor chose; pinch and the -/+ keys still zoom. */
.tool-dock[data-compact] .zoom-group { display: none; }
.tool-dock[data-side] .history-hud { padding-right: 0; padding-bottom: 4px; }
.tool-dock[data-side] .dock-grip { width: 38px; height: 22px; }
.tool-dock[data-side] .dock-grip .icon { transform: rotate(90deg); }
.tool-dock[data-side] > .dropdown-wrap { margin-left: 0; margin-top: 2px; }
.tool-dock[data-side] .insert-menu, .tool-dock[data-side][data-menu-below="true"] .insert-menu { top: auto; bottom: 0; }
.tool-dock[data-side="left"] .insert-menu { left: calc(100% + 12px); right: auto; }
.tool-dock[data-side="right"] .insert-menu { right: calc(100% + 12px); left: auto; }
.tool-popover { position: absolute; z-index: 45; width: 264px; max-width: calc(100% - 24px); max-height: calc(100% - 16px); overflow-y: auto; padding: 16px; touch-action: pan-y; }
.popover-heading { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 18px; }
.popover-header { font-size: 12px; font-weight: 600; color: var(--ink); }
#popover-stroke-preview { width: 82px; height: 24px; fill: none; stroke: var(--ink); stroke-linecap: round; }
.popover-label { display: block; margin: 0 0 9px; color: var(--ink-3); font-size: 11px; font-weight: 400; }
.popover-row { margin-bottom: 18px; }
.colour-swatches { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 2px; }
.colour-choice { width: 25px; height: 25px; padding: 0; border: 1px solid #0001; border-radius: var(--radius-pill); }
.colour-choice.active { outline: 1.5px solid var(--ink); outline-offset: 3px; }
.thickness-segmented, .style-segmented { display: grid; gap: 4px; }
.thickness-segmented { grid-template-columns: repeat(4, 1fr); margin-bottom: 18px; }
.thickness-btn, .style-seg-btn, .selection-mode-btn { display: flex; align-items: center; justify-content: center; height: 34px; padding: 6px 9px; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-2); font: inherit; font-size: 11px; }
/* POL-16: "Copy region" is the long label; nowrap plus tighter inline padding keeps
   three equal 1fr cells untruncated at the 264px popover width. */
.selection-mode-btn { white-space: nowrap; padding-inline: 5px; }
.thickness-btn:hover, .style-seg-btn:hover, .selection-mode-btn:hover { background: var(--surface-subtle); }
.thickness-btn.active, .style-seg-btn.active, .selection-mode-btn.active { background: var(--work-selected); color: var(--ink); }
.thickness-btn span { display: block; width: 26px; max-height: 9px; border-radius: var(--radius-pill); background: currentColor; }
.style-segmented { grid-template-columns: repeat(3, 1fr); }
/* POL-16: three equal-width cells so the mode buttons read as segmented controls
   instead of floating labels separated by dead space. */
.selection-mode-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; margin-bottom: 16px; }
/* SNAP-1: the straighten switch reuses the More-menu switch control (pill and
   knob) so one toggle looks the same wherever a preference lives. */
/* POL-30: the label owns the row's left edge. Eight px of left padding made
   "Straighten lines" sit 8 px right of the Colour and Width labels above it;
   the switch keeps its 6 px trailing inset so it stays clear of the edge. */
.popover-toggle { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: 34px; margin-top: 8px; padding: 6px 6px 6px 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-2); font: inherit; font-size: 11px; }
.popover-toggle:hover { background: var(--surface-subtle); }
.popover-toggle-title { color: var(--ink-2); }

/* Context remains attached to the object; renderer internals stay invisible. */
.selection-toolbar { position: absolute; display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 3px; z-index: 35; width: max-content; padding: 4px 6px; transform: translateX(-50%); max-width: calc(100% - 16px); }
/* POL-28: every action in this bar is a 40 px target, the same as the dock's;
   30 px was a stylus miss beside Duplicate. */
.selection-toolbar .btn { min-height: 40px; padding: 5px 8px; font-size: 11px; }
.sel-label { padding: 0 8px; font-size: 11px; color: var(--ink-3); white-space: nowrap; }
/* BUG-8: a selection that only Escape could dismiss was a softlock on a
   stylus. Close is a 40px target on every viewport and sits first; Delete
   stays last behind a rule because it destroys work. */
#sel-close-btn { width: 40px; min-height: 40px; padding: 0; }
#sel-delete-btn { width: 40px; min-height: 40px; padding: 0; }
#sel-delete-btn:hover { color: var(--status-err); }
/* POL-28: Delete destroys work next to Duplicate, which costs one undo. A rule
   with 8 px of air keeps them apart under a stylus; the divider leaves with the
   button it fences off. */
.sel-divider { flex: none; width: 1px; height: 24px; margin-left: 8px; background: var(--line-strong); }
.selection-toolbar:has(#sel-delete-btn.hidden) .sel-divider { display: none; }
.text-editor-overlay { position: absolute; z-index: 36; width: min(340px, calc(100% - 24px)); padding: 12px; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--work-shadow); }
.text-editor-overlay textarea { display: block; width: 100%; min-height: 56px; max-height: min(220px, 30dvh); overflow-y: auto; padding: 7px; resize: none; border: 0; outline: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink); font-size: 13px; line-height: 1.5; }
.text-editor-overlay:focus-within { border-color: #8b9cc4; box-shadow: 0 0 0 2px rgba(80, 112, 180, .14), var(--work-shadow); }
.text-editor-actions { display: flex; align-items: center; gap: 5px; justify-content: flex-end; margin-top: 6px; }
.text-editor-hint { margin-right: auto; color: var(--ink-3); font-size: 10px; }
.text-editor-actions .btn { min-height: 30px; }
/* Back and (COL-7) the column navigator share one bar; zoom lives in the dock
   (HUD-1), so this HUD holds history only. */
.view-hud { position: absolute; bottom: 18px; left: 18px; z-index: 24; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; max-width: calc(100% - 36px); }
/* POL-28: the bar wears the dock's 54 px height, 10 px radius and var(--surface);
   6 px around a 40 px button is the dock's own arithmetic
   (54 = 40 + 2 x 6 + 2 x 1 border). */
.view-nav { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; width: max-content; max-width: 100%; padding: 6px; }
/* A bar with nothing to hold is not a surface. */
.view-nav:not(:has(> :not(.hidden))) { display: none; }
/* POL-28: a generic icon target is 40 px, like the dock's; the find bar keeps
   its own 32 px inset controls (NAV-1) and the dock overrides the width. */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-2); }
/* Hover and keyboard focus share one fill so the percentage button reads as a control, not a label. */
.icon-btn:hover, .icon-btn:focus-visible { background: var(--surface-subtle); }
/* POL-28: a labelled history control is a 40 px target, matching the dock. */
.view-back, #view-top-btn { width: max-content; height: 40px; gap: 5px; padding: 4px 9px; font-size: 11px; white-space: nowrap; }
#pdf-links-layer { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 3; }
.pdf-page-link { position: absolute; pointer-events: auto; cursor: pointer; border-radius: var(--radius-sm); touch-action: manipulation; }
.pdf-page-link:hover { background: rgba(37, 99, 235, .10); outline: 1px solid rgba(37, 99, 235, .3); }
.pdf-page-link:focus-visible { outline: 2px solid #7daaff; outline-offset: 2px; background: rgba(37, 99, 235, .10); }
/* NAV-1: the find bar replaces the PDF page field. On a 720 px stage it is
   360 px wide at the stage's top-right (y 12-56), so the bottom dock and HUD
   stay clear and the sheet's left margin is clear; a heading whose line reaches
   past x ~348 sits behind the bar, and the open list extends that column down
   to about 482 px (12 + 44 + 6 + up to 50% of the stage), until Escape closes it. */
.pdf-find { position: absolute; top: 12px; right: 12px; z-index: 32; display: flex; align-items: center; gap: 2px; width: min(360px, calc(100% - 24px)); height: 44px; padding: 0 3px 0 10px; }
.pdf-find-input { flex: 1; min-width: 0; height: 30px; padding: 0 6px; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink); font-size: 13px; -webkit-user-select: text; user-select: text; }
.pdf-find-input:focus { outline: 0; background: var(--surface-subtle); }
.pdf-find-input::placeholder { color: var(--ink-3); }
.pdf-find-count { flex: none; min-width: 34px; margin-right: 2px; color: var(--ink-3); font-size: 11px; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.pdf-find .find-step, .pdf-find .find-close { width: 32px; height: 32px; flex: none; }
.pdf-find .find-step:disabled { color: var(--ink-3); opacity: .45; }
.pdf-find .find-step:disabled:hover { background: transparent; }
.pdf-find #pdf-find-prev .icon { transform: rotate(180deg); }
.pdf-find .icon { width: 16px; height: 16px; }
/* The list hangs under the bar without widening it; its height is set from the
   live stage (50%) so half a sheet of questions stays reachable by scrolling. */
.pdf-find-list { position: absolute; top: calc(100% + 6px); left: 0; right: 0; overflow-y: auto; overscroll-behavior: contain; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--work-shadow); }
.pdf-find-list:empty { display: none; }
.pdf-find-row { display: flex; align-items: center; gap: 6px; width: 100%; height: 36px; padding: 0 10px; border: 0; border-radius: 0; background: transparent; color: var(--ink); font-size: 12px; font-weight: 400; text-align: left; white-space: nowrap; overflow: hidden; cursor: pointer; }
.pdf-find-row:hover, .pdf-find-row:focus-visible { background: var(--surface-subtle); }
.pdf-find-row.active { background: var(--work-selected); }
.pdf-find-row .pdf-find-label { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pdf-find-row.group .pdf-find-label { color: var(--ink-3); font-size: 11px; font-weight: 600; letter-spacing: .04em; }
.pdf-find-page { margin-left: auto; flex: none; color: var(--ink-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.pdf-find-empty { padding: 10px; color: var(--ink-3); font-size: 11px; }
/* Tutor-local only: the hit is drawn over the sheet and never sent. The sheet is
   always white inside the page, so a fixed blue works in both themes (the theme
   accent is near-white in dark mode and vanishes on the paper). */
.pdf-find-hit { position: absolute; z-index: 5; pointer-events: none; border: 2px solid #2563eb; border-radius: var(--radius-sm); background: color-mix(in srgb, #2563eb 15%, transparent); }
.pdf-find-spinner { display: inline-block; width: 12px; height: 12px; vertical-align: -2px; border: 2px solid var(--line-strong); border-top-color: var(--accent); border-radius: var(--radius-pill); animation: pdfFindSpin .7s linear infinite; }
@keyframes pdfFindSpin { to { transform: rotate(360deg); } }
.follow-banner { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; z-index: 34; min-height: 36px; padding: 3px 5px 3px 10px; font-size: 11px; white-space: nowrap; pointer-events: none; }
/* BUG-5: banners sit over the sheet, so the pen must write through the banner
   body; only the buttons take pointer input. */
.follow-banner .btn { pointer-events: auto; font-size: 10px; border-left: 1px solid var(--line); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.follow-banner > .icon { width: 14px; height: 14px; color: var(--ink-3); }
.join-request-banner { position: absolute; top: 72px; left: 50%; transform: translateX(-50%); z-index: 48; display: flex; align-items: center; gap: 10px; min-height: 44px; max-width: calc(100% - 24px); padding: 6px 7px 6px 12px; font-size: 12px; font-weight: 400; white-space: nowrap; pointer-events: none; }
.join-request-banner .btn { pointer-events: auto; min-height: 30px; }
.join-request-banner > .icon { color: var(--ink-3); }
.join-request-chip { padding: 2px 7px; border-radius: var(--radius-sm); background: var(--surface-subtle); color: var(--ink-2); font-size: 10px; white-space: nowrap; }
.join-actions { display: flex; justify-content: center; gap: 8px; margin-top: 16px; }
/* BUG-7: an off-screen peer gets a chip at the stage edge. The layer must not
   consume pointer input; only the chip box does (BUG-5 pen pass-through). */
.peer-jump-layer { position: absolute; inset: 0; z-index: 23; pointer-events: none; overflow: hidden; }
/* POL-26: the same outline pill as the header presence chip: 34 px tall, the
   pill radius, 11 px/500 on the surface with one hairline. */
.peer-jump-chip { position: absolute; display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 9px; border: 1px solid var(--line-strong); border-radius: var(--radius-pill); background: var(--surface); box-shadow: var(--work-shadow); color: var(--ink); font-size: 11px; font-weight: 500; white-space: nowrap; pointer-events: auto; transform: translate(-50%, -50%); }
/* POL-27: the label can no longer widen the pill off the sheet. The name is the
   part that truncates; the separator and the distance stay whole, so a long
   student name costs characters, not the direction. The name's cap leaves room
   for the pill's own chrome (9+9 padding, 8 dot, 14 arrow, two 6 gaps) and the
   longest distance phrase ("12 pages below"), so the whole pill still fits a
   390 px stage. */
.peer-jump-label { display: inline-block; max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.peer-jump-name { display: inline-block; vertical-align: bottom; max-width: calc(100vw - 152px); overflow: hidden; text-overflow: ellipsis; }
.peer-jump-where { white-space: nowrap; }
.peer-jump-chip:hover { background: var(--surface-subtle); }
.peer-jump-dot { width: 8px; height: 8px; border-radius: var(--radius-pill); background: var(--peer-student); }
.peer-jump-chip.tutor .peer-jump-dot { background: var(--peer-tutor); }
.peer-jump-chip.student .peer-jump-dot { background: var(--peer-student); }
/* POL-27: with the distance in words beside it, the arrow is a 14 px bearing in
   the peer's own colour. A 12 px grey chevron read as a dropdown arrow. */
.peer-jump-chevron { width: 14px; height: 14px; color: var(--peer-student); transform: rotate(var(--peer-angle, 0rad)); }
.peer-jump-chip.tutor .peer-jump-chevron { color: var(--peer-tutor); }
/* BUG-5: opt-in input probe (?inputdebug=1). It is non-interactive except its
   own buttons and sits above the view HUD, so it never covers the top of the
   sheet the owner is asked to write on. Hide collapses it to a chip. */
#input-debug-panel { position: fixed; left: 18px; bottom: 100px; z-index: 70; display: flex; flex-direction: column; gap: 6px; width: min(320px, calc(100vw - 36px)); max-height: min(38dvh, 320px); padding: 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); color: var(--ink); font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; box-shadow: var(--work-shadow); pointer-events: none; }
#input-debug-panel.collapsed { max-height: none; padding: 5px 6px; }
#input-debug-panel.collapsed #input-debug-list,
#input-debug-panel.collapsed #input-debug-copy { display: none; }
.input-debug-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.input-debug-actions { display: flex; gap: 4px; }
.input-debug-head .btn { pointer-events: auto; }
#input-debug-list { margin: 0; padding-left: 18px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }

/* Page tray: document navigation, not another layer of header chrome. */
.sidebar-top .btn { border-color: transparent; }
.page-sidebar { position: absolute; z-index: 32; top: 12px; left: 12px; width: 218px; max-height: calc(100% - 90px); display: flex; flex-direction: column; overflow: visible; }
.page-sidebar.collapsed { display: none; }
.sidebar-top { padding: 10px; }
.sidebar-top .btn { justify-content: flex-start; font-size: 12px; }
.page-list { overflow-y: auto; padding: 4px 6px 12px; scrollbar-width: thin; }
.page-item { position: relative; display: flex; align-items: center; gap: 2px; margin: 2px 0; border-radius: var(--radius-sm); }
.page-item:hover { background: var(--surface-subtle); }
.page-item.active { background: var(--work-selected); }
.page-open { display: flex; align-items: center; flex: 1; min-width: 0; gap: 10px; min-height: 88px; padding: 9px; border: 0; background: transparent; color: var(--ink); text-align: left; font-size: 12px; }
.page-thumbnail { display: block; width: 48px; height: 67px; flex: none; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: #fff; }
.page-meta-col { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 5px; }
/* Dated titles ("Mon 26 Oct 2026 (2)") need two lines: one line hides the year and
   the same-day suffix, so two lessons on one day would read identically. */
.page-meta-col > span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; line-height: 1.35; }
.page-peers { display: flex; flex-wrap: wrap; gap: 3px; }
.page-peer-pill { font-size: 9px; color: var(--ink-3); font-weight: 400; }
.page-peer-pill.tutor { color: var(--peer-tutor); }
.page-peer-pill.student { color: var(--peer-student); }
.page-menu { width: 24px; padding: 0; border: 0; background: transparent; color: var(--ink-3); font-size: 18px; }
.page-action-menu {
  position: fixed; z-index: 60; min-width: 144px;
  display: flex; flex-direction: column; padding: 4px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-md);
  background: var(--surface); box-shadow: var(--work-shadow);
}
.page-action-menu button {
  display: flex; align-items: center; width: 100%; min-height: 32px;
  padding: 7px 9px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--ink-2);
  text-align: left; font-size: 12px; font-weight: 400; white-space: nowrap;
}
.page-action-menu button:hover:not(:disabled) { background: var(--surface-subtle); color: var(--ink); }
.page-action-menu button.danger { color: var(--status-err); }
.page-action-menu button:disabled { color: var(--ink-3); opacity: .5; }
.sidebar-restore { width: 100%; margin-top: 8px; color: var(--ink-3); }
.deleted-pages-box { display: flex; flex-direction: column; gap: 4px; padding: 6px; }
.deleted-page-btn { padding: 8px; border: 0; border-radius: var(--radius-sm); background: var(--surface-subtle); color: var(--ink-2); font-size: 11px; text-align: left; }

@media (max-width: 1100px) {
  .top-strip { gap: 8px; padding: 0 12px; }
  .top-strip-left, .top-strip-right { gap: 6px; }
  /* POL-24: 768 px and wider still has slack, so the title and subject keep the
     caps they had before this card did anything. Only the name is tightened in
     the 767 block below, where the words and the name compete for the same rail;
     the subject keeps this 220 because "VCE Specialist Mathematics 3/4" is 166 px
     and a tighter cap only spends slack the left group already has.
     The left group is not clipped either: a clip hid the save pill's own state,
     and min-width: 0 on .nb-identity already lets the column give way. */
  .nb-title, .nb-subject-badge { max-width: 220px; }
  /* .view-hud is placed from live dock geometry by positionViewHud(). */
  #input-debug-panel { bottom: 160px; left: 12px; }
}
/* POL-24: a tooltip never opens for a pen (BUG-6), so between a phone and a
   full-width window the label is the only identification "Copy link"
   and "Show view" have. The words take the icons' space; the phone rule
   below keeps the icon-only buttons, where there is room for neither. */
@media (min-width: 641px) and (max-width: 1100px) {
  .copy-link-btn span, .summon-btn span { display: inline; }
  .copy-link-btn, .summon-btn { width: auto; padding: 0 5px; }
  .copy-link-btn .icon, .summon-btn .icon { display: none; }
}
/* POL-24: 767 px is the last width where the two words and the name share the
   rail: a 1280 px laptop used half is 641, the owner's split-screen width. The
   name and the subject are both blocks in one ellipsising column, so they lose
   characters together as the rail narrows; the caps only stop one long title
   from starving the actions beside it. */
@media (max-width: 767px) {
  .nb-title { max-width: 190px; }
  /* POL-24: two or more students is where the words stop fitting. At 641 with
     two chips the save pill painted under the presence strip, and under round
     3's clip it was cut to 80 of its 106 px. The labels are the only thing left
     that can be paid, so the buttons become their icons. One student is the
     common lesson and keeps the words, as does every width from 768 px up.
     DEC-15 default: a readable save state outranks a label that only repeats
     the tooltip a pen never opens. */
  #presence-strip:has(.presence-avatar ~ .presence-avatar) ~ .copy-link-btn span,
  #presence-strip:has(.presence-avatar ~ .presence-avatar) ~ .summon-btn span { display: none; }
  #presence-strip:has(.presence-avatar ~ .presence-avatar) ~ .copy-link-btn,
  #presence-strip:has(.presence-avatar ~ .presence-avatar) ~ .summon-btn { width: 36px; padding: 0; }
  #presence-strip:has(.presence-avatar ~ .presence-avatar) ~ .copy-link-btn .icon,
  #presence-strip:has(.presence-avatar ~ .presence-avatar) ~ .summon-btn .icon { display: inline; }
}
@media (min-width: 641px) { #ws-more-summon-btn { display: none; } }
/* HUD-1: a phone pinches. A touch screen has no keyboard and pinches too, so
   the dock keeps its width and the group stays out of it there. */
@media (hover: none) and (pointer: coarse) { .tool-dock .zoom-group { display: none; } }
/* HUD-2: measured in the phone layout, the dock is 440 px with the zoom group
   inside it and needs 8 px of stage each side, so the group is kept from 456 px
   up. Below that the window is a phone held in one hand, which pinches; the
   -/+/0 keys still zoom wherever a keyboard exists. */
@media (max-width: 455px) { .tool-dock .zoom-group { display: none; } }
@media (max-width: 640px) {
  .top-strip { height: 54px; min-height: 54px; gap: 8px; padding: 0 8px; }
  .top-strip-left, .top-strip-right { gap: 3px; }
  .top-strip-left { overflow: hidden; }
  .top-strip .btn-icon { width: 32px; min-width: 32px; }
  .top-strip .btn { min-height: 36px; }
  #ws-toggle-sidebar-btn { padding: 0 5px; gap: 4px; }
  .top-divider, .nb-subject-badge, #ws-summon-btn { display: none; }
  /* POL-24: a phone has no room for the words either, so copy is its icon. */
  .copy-link-btn span { display: none; }
  .copy-link-btn { width: 36px; padding: 0; }
  .nb-identity { flex: 1; min-width: 24px; padding: 4px 2px; }
  .nb-title { max-width: none; font-size: 12px; }
  .nb-identity-text { min-width: 0; }
  .save-pill { padding: 3px 5px; font-size: 10px; }
  #ws-follow-btn { padding: 5px 7px; font-size: 11px; }
  #ws-follow-btn .icon { display: none; }
  .save-pill:not(.saved) { max-width: 116px; overflow: hidden; font-size: 10px; }
  #ws-follow-btn[aria-pressed="true"] { display: none; }
  .top-strip:has(.save-pill:not(.saved)) .nb-identity { display: none; }
  .tool-dock { height: 52px; bottom: max(12px, env(safe-area-inset-bottom)); gap: 4px; padding: 5px; max-width: calc(100% - 16px); }
  .tool-dock .tool-btn { width: 36px; min-width: 36px; height: 40px; }
  /* HUD-2: the zoom value is a 40 px target at half screen too; Fit and NNN%
     still fit inside it at 11 px. */
  .tool-dock:not([data-side]) .zoom-value { width: 40px; min-width: 40px; }
  .tool-dock .pen-preset-btn { width: 38px; min-width: 38px; }
  .swatch-dot { width: 34px; height: 26px; }
  .dock-grip { width: 18px; }
  /* CHROME-1: a fine pointer may snap the dock vertical at this width, where the
     vertical dock stacks history inside its own column; the floating pill is the
     horizontal phone dock's. */
  .tool-dock:not([data-side]) .history-hud { position: absolute; right: 0; top: -46px; height: 38px; padding: 2px; gap: 1px; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--work-shadow); }
  .history-hud .tool-btn { height: 32px; width: 34px; min-width: 34px; }
  /* .view-hud is placed from live dock geometry by positionViewHud(). */
  .view-hud { max-width: calc(100% - 20px); }
  /* POL-28: the phone dock is 52 px, so the HUD's padding gives the same
     52 = 40 + 2 x 5 + 2 x 1 border. */
  .view-nav { padding: 5px; }
  #input-debug-panel { left: 10px; bottom: 156px; width: min(320px, calc(100vw - 20px)); }
  .page-sidebar { left: 8px; top: 8px; width: 202px; }
  .follow-banner { top: 8px; gap: 6px; font-size: 10px; }
  .join-request-banner { top: 62px; gap: 6px; font-size: 11px; }
  .join-request-banner > .icon { display: none; }
  .tool-popover { width: 264px; }
}
@media (max-width: 360px) {
  .tool-dock { gap: 2px; padding: 4px; }
  .tool-dock .pen-preset-btn { min-width: 36px; width: 36px; }
  .tool-dock > .dropdown-wrap { margin-left: 0; }
  /* A waiting Paste control adds a sixth slot to the row. Tighten the row while
     it is shown so a 320px phone keeps every control on screen; the dock
     returns to full targets the moment the copy is pasted or cleared. */
  .tool-dock:has(#dock-paste-btn:not(.hidden)) { gap: 1px; }
  .tool-dock:has(#dock-paste-btn:not(.hidden)) .tool-btn,
  .tool-dock:has(#dock-paste-btn:not(.hidden)) .pen-preset-btn { width: 33px; min-width: 33px; }
  .tool-dock:has(#dock-paste-btn:not(.hidden)) .swatch-dot { width: 31px; }
  .top-strip { padding: 0 5px; }
  .top-strip-right .btn { padding-left: 5px; padding-right: 5px; }
  .join-request-banner { padding-left: 8px; }
}
@media (prefers-reduced-motion: reduce) { .toggle-knob { transition: none; } .pdf-find-spinner { animation: none; } }
