/* Printurtle - styles
   Clean, high-contrast, large click targets, no decorative animation.

   Every colour pair used for text meets WCAG AA (4.5:1 for body text, 3:1 for
   large text and for the borders that carry meaning). The foreground colours
   below are named for their meaning, and each one is chosen against the
   background it actually sits on, not against white. */

:root {
  --bg: #eef1f6;
  --surface: #ffffff;
  --surface-2: #f4f6fa;
  --border: #d5dbe6;
  --border-strong: #b9c2d2;
  --text: #1c2333;
  --text-muted: #5b6577;
  --accent: #2b6de0;
  --accent-hover: #1f58ba;
  --accent-text: #ffffff;
  /* A pale accent wash, used for selected rows, cards and notices. */
  --accent-soft: #edf3ff;
  --accent-soft-hover: #e2ebfd;
  --accent-soft-border: #bcd2f5;
  /* 4.97:1 with white: the Run button is the most important control here. */
  --run: #17804a;
  --run-hover: #0e6b38;
  --error: #b71c1c;
  --error-hover: #8f1515;
  --error-bg: #fdecec;
  --error-border: #f0b8b8;
  --warning: #8f5600;
  --warning-bg: #fff4e0;
  --warning-border: #f2d39a;
  --ok: #1a6e36;
  --ok-bg: #e6f5ea;
  --ok-border: #b9dfc4;
  --ok-border-strong: #9ed3ae;
  --info: #1f58ba;
  --info-bg: #e8f0fd;
  /* The turtle's position and the stepping highlight: a warm marker colour. */
  --focus: #b06a00;
  --focus-bg: #fff6e3;
  /* The keyboard focus ring: a dark ring over a white one, so it stays visible
     on white panels and on the solid green and blue buttons alike. */
  --ring: #1c2333;
  --ring-halo: #ffffff;
  /* The 3D pane. Kept in step with the renderer's clear colour in js/viewport.js
     so there is no seam where the canvas ends. */
  --stage: #f3f5f9;
  --radius-sm: 6px;
  --radius: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;
  --shadow: 0 1px 2px rgba(20, 30, 50, 0.08);
  --shadow-pop: 0 8px 28px rgba(20, 30, 50, 0.18);
  --font: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", "Fira Code", "Cascadia Code", Consolas, "Courier New", monospace;
  --topbar-height: 56px;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; margin: 0; }

body {
  font-family: var(--font);
  font-size: 15px;
  color: var(--text);
  background: var(--bg);
  display: grid;
  grid-template-rows: var(--topbar-height) 1fr auto;
  min-height: 100vh;
  overflow: hidden;
}

button, input, select { font: inherit; color: inherit; }
/* WCAG 2.2 target size: nothing a pointer has to hit falls below 24px. Most
   controls are 30-40px already; this catches the small selects and number
   fields in the class-plate toolbars, which WebKit laid out a pixel short. */
button, input, select { min-height: 24px; }

/* Author `display` rules would otherwise beat the browser's [hidden] rule. */
[hidden] { display: none !important; }

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

.skip-link {
  position: absolute; left: -999px; top: 8px; z-index: 100;
  background: var(--accent); color: #fff; padding: 8px 12px; border-radius: var(--radius);
}
.skip-link:focus { left: 8px; }

/* Two rings: white against the button, dark against the page. One of the two
   always has contrast, whatever the control is sitting on. */
:focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--ring-halo);
}
/* Inputs already carry a border, so the halo would double it up. */
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline-offset: 1px;
  box-shadow: none;
}

/* ---------- Top bar ---------- */

.topbar {
  display: flex; align-items: center; gap: 16px;
  padding: 0 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.brand {
  display: flex; align-items: center; gap: 10px;
  font-weight: 800; letter-spacing: 0.12em; font-size: 16px;
}

.project-name { flex: 1; max-width: 340px; }
.project-name input {
  width: 100%; height: 40px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2);
}
.project-name input:focus { background: #fff; border-color: var(--accent); }

.topbar-actions { display: flex; gap: 8px; margin-left: auto; align-items: center; }

/* ---------- Menus ---------- */

.menu { position: relative; }
.menu > summary { list-style: none; cursor: pointer; }
.menu > summary::-webkit-details-marker { display: none; }
.menu-panel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 60;
  min-width: 250px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-pop);
}
.menu-panel hr { border: none; border-top: 1px solid var(--border); margin: 6px 4px; }
.menu-item {
  display: block; width: 100%; text-align: left;
  min-height: 40px; padding: 8px 12px;
  background: none; border: none; border-radius: var(--radius-sm); cursor: pointer;
}
.menu-item:hover { background: var(--surface-2); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 40px; padding: 0 16px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
  cursor: pointer; font-weight: 600; white-space: nowrap;
}
.btn:hover:not(:disabled) { background: var(--surface-2); border-color: var(--border-strong); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn-small { min-height: 34px; padding: 0 12px; font-size: 14px; }
.btn-icon { min-width: 40px; padding: 0; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
/* "Suggested", not "primary": it points a newcomer at the quickest way in
   without competing with Run and Download STL, which are the two actions that
   actually change something. */
.btn-suggested { background: var(--accent-soft); border-color: var(--accent-soft-border); color: var(--info); }
.btn-suggested:hover:not(:disabled) { background: var(--accent-soft-hover); border-color: var(--accent); }

.btn-danger { background: var(--error); border-color: var(--error); color: #fff; }
.btn-danger:hover:not(:disabled) { background: var(--error-hover); }
.btn[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: var(--accent-text);
}

.btn-run {
  background: var(--run); border-color: var(--run); color: #fff;
  min-height: 42px; padding: 0 18px; font-size: 16px;
  /* "Downloading Python…" is much wider than "Run" and used to push itself off
     the edge of a phone-width pane. */
  min-width: 0; max-width: 100%;
}
#btn-run-label { overflow: hidden; text-overflow: ellipsis; }
.btn-run:hover:not(:disabled) { background: var(--run-hover); border-color: var(--run-hover); }
.btn-run kbd {
  font-family: var(--font); font-size: 12px; font-weight: 500;
  padding: 2px 6px; border-radius: var(--radius-sm); background: rgba(0, 0, 0, 0.28);
}

/* ---------- Workspace ---------- */

.workspace {
  display: grid;
  grid-template-columns: minmax(320px, 42%) 1fr;
  gap: 12px; padding: 12px;
  min-height: 0;
}

.pane {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  min-height: 0; overflow: hidden;
}

.pane-header {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px 8px 16px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.pane-header h2 {
  margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-muted);
}
.pane-header #btn-step { margin-left: auto; }
.pane-tools { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

.save-status { font-size: 12px; color: var(--text-muted); }

.editor { flex: 1; min-height: 140px; overflow: auto; }
.editor .cm-editor { height: 100%; }

/* ---------- Step bar ---------- */

.step-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--border);
  background: var(--focus-bg);
}
.step-bar input[type="range"] { flex: 1; min-width: 60px; accent-color: var(--accent); }
.step-label { font-size: 13px; font-family: var(--mono); white-space: nowrap; max-width: 46%; overflow: hidden; text-overflow: ellipsis; }

/* ---------- Messages under the editor ---------- */

.messages {
  max-height: 40%;
  overflow: auto;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  padding: 10px 12px;
  display: flex; flex-direction: column; gap: 10px;
}
.messages:empty { display: none; }

.message {
  border-radius: var(--radius);
  padding: 10px 14px;
  border: 1px solid var(--border);
  background: var(--surface);
}
.message p { margin: 0 0 6px; }
.message p:last-child { margin-bottom: 0; }
.message-info { background: var(--info-bg); border-color: var(--accent-soft-border); }
.message-error { background: var(--error-bg); border-color: var(--error-border); }
.message-error h3 { margin: 0 0 6px; font-size: 15px; color: var(--error); }
.message-hint { color: var(--text); }
.message-ok { background: var(--ok-bg); border-color: var(--ok-border); }
.message-warning { background: var(--warning-bg); border-color: var(--warning-border); }
.message code, .message pre { font-family: var(--mono); font-size: 13px; }
.message pre {
  margin: 8px 0 0; padding: 8px 10px; overflow: auto; max-height: 200px;
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius-sm); white-space: pre-wrap;
}
.message details summary { cursor: pointer; color: var(--text-muted); font-size: 13px; margin-top: 6px; }
/* A disclosure triangle is a pointer target like any other: WCAG 2.2 asks for
   24px. The More menu's summary is already a full-size button, so it opts out. */
details > summary:not(.btn) { min-height: 24px; padding: 4px 2px; }
.program-output { font-family: var(--mono); font-size: 13px; white-space: pre-wrap; margin: 0; }
.output-label { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 4px; }
.message-link {
  background: none; border: none; padding: 0; margin: 0;
  color: var(--info); font: inherit; font-weight: 600; text-decoration: underline; cursor: pointer;
}

/* ---------- Challenge card ---------- */

.challenge-card { border-color: var(--accent-soft-border); background: var(--accent-soft); }
.challenge-card .challenge-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.challenge-card h3 { margin: 0; font-size: 16px; }
.challenge-level {
  font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  background: var(--accent); color: #fff; padding: 2px 8px; border-radius: var(--radius-pill);
}
.challenge-card .criteria { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.challenge-card .criteria li { display: grid; grid-template-columns: 22px 1fr; gap: 6px; align-items: baseline; }
.criterion-met { color: var(--ok); font-weight: 800; }
.criterion-unmet { color: var(--text-muted); font-weight: 800; }
.challenge-passed { background: var(--ok-bg); border-color: var(--ok-border-strong); }
.challenge-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }

/* ---------- Viewport ---------- */

.viewport { flex: 1; min-height: 240px; position: relative; background: var(--stage); }
.viewport-canvas { display: block; width: 100% !important; height: 100% !important; touch-action: none; }
.viewport-canvas.measuring { cursor: crosshair; }
.viewport-canvas.moving-model { cursor: grab; }
.viewport-canvas.moving-model:active { cursor: grabbing; }
.position-toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; padding: 8px 12px; border-bottom: 1px solid var(--border); font-size: 12px; }
.position-toolbar input { width: 74px; }
.position-toolbar span { color: var(--text-muted); }
.dialog.dialog-plate { width: min(1320px, calc(100vw - 24px)); max-width: none; }
.plate-shell { padding: 18px; height: calc(100vh - 48px); max-height: 940px; overflow: auto; display: flex; flex-direction: column; }
.plate-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.plate-actions input { width: 64px; }
.plate-notice { padding: 9px 12px; border-radius: var(--radius-sm); background: var(--accent-soft); font-size: 13px; }
.plate-layout { display: grid; grid-template-columns: 290px minmax(0, 1fr); gap: 18px; flex: 1; min-height: 0; }
.plate-sidebar { min-width: 0; overflow: auto; padding-right: 4px; }
.plate-items { display: grid; gap: 6px; margin-bottom: 14px; }
.plate-item { display: grid; gap: 4px; text-align: left; padding: 9px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); cursor: pointer; overflow-wrap: anywhere; }
.plate-item.selected { border-color: var(--accent); background: var(--accent-soft); }
.plate-item span { font-size: 12px; color: var(--text-muted); }
.plate-preview { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
.plate-preview .viewport { min-height: 220px; flex: 1; border: 1px solid var(--border); border-radius: 8px; }
.plate-preview .check-list { max-height: 85px; overflow: auto; }
.plate-preview .check-list:empty { display: none; }
.plate-preview #plate-export { flex-shrink: 0; }
.plate-guidance { color: var(--text-muted); font-size: 12px; margin: 0; }
.position-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 10px 0; }
.position-fields label { font-size: 12px; }
.position-fields input { display: block; width: 100%; }
.position-fields input, .position-toolbar input, .plate-actions input, .plate-actions select { min-height: 30px; padding: 3px 7px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--text); font: inherit; }
/* WebKit ignores min-height on a native select, which left this one a pixel
   under the 24px target minimum. An explicit height is honoured everywhere. */
.plate-actions select { height: 30px; }
#plate-source { max-height: 220px; overflow: auto; font-size: 12px; white-space: pre-wrap; overflow-wrap: anywhere; }
#plate-selection { padding: 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.tutorial-layout { display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 20px; }
#tutorial-list { display: flex; flex-direction: column; gap: 6px; }
#tutorial-list button { text-align: left; white-space: normal; }
#tutorial-list button[aria-current=true] { background: var(--accent-soft); border-color: var(--accent); }
.tutorial-step { padding: 12px 0; border-bottom: 1px solid var(--border); }
.tutorial-step pre { white-space: pre-wrap; overflow-wrap: anywhere; padding: 12px; background: var(--stage); border-radius: var(--radius-sm); font-size: 12px; }
.tutorial-step h3 { margin-top: 0; }
@media (max-width: 900px) {
  .plate-shell { display: block; height: auto; max-height: calc(100vh - 36px); }
  .plate-layout { grid-template-columns: 230px minmax(0, 1fr); }
  .plate-sidebar { max-height: 65vh; }
  .plate-preview .viewport { height: 36vh; min-height: 260px; flex: none; }
  .topbar-actions { flex-wrap: wrap; }
}
@media (max-width: 650px) {
  .plate-layout, .tutorial-layout { grid-template-columns: 1fr; }
  .plate-sidebar { max-height: 40vh; }
}
/* Empty state: the 3D pane says what to do instead of showing a bare grid. */
.viewport-empty {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 24px; text-align: center;
}
.viewport-empty-title { margin: 0; font-size: 17px; font-weight: 700; }
.viewport-empty-text { margin: 0; max-width: 34ch; color: var(--text-muted); font-size: 14px; }

.viewport-overlay { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.viewport-label {
  position: absolute; top: 0; left: 0;
  padding: 3px 8px; border-radius: var(--radius-sm);
  background: rgba(28, 35, 51, 0.88); color: #fff;
  font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap;
  transform-origin: 0 0; margin: -10px 0 0 10px;
}
.viewport-label-strong { background: var(--error); font-weight: 700; }
.viewport-status {
  padding: 8px 14px; border-top: 1px solid var(--border);
  background: var(--focus-bg); font-size: 14px;
}

/* ---------- Status bar ---------- */

.statusbar {
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 10px 16px;
  display: flex; flex-direction: column; gap: 8px;
  max-height: 38vh; overflow: auto;
}

.status-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.model-info { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }

.status-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--radius-pill); font-weight: 700; font-size: 14px;
}
.status-badge-neutral { background: var(--surface-2); color: var(--text-muted); }
.status-badge-ok { background: var(--ok-bg); color: var(--ok); }
.status-badge-error { background: var(--error-bg); color: var(--error); }
.status-badge-warning { background: var(--warning-bg); color: var(--warning); }

.model-stats { display: flex; gap: 18px; margin: 0; flex-wrap: wrap; }
.model-stats div { display: flex; flex-direction: column; }
.model-stats dt { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
.model-stats dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }

.status-actions { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.printer-summary { font-size: 13px; color: var(--text-muted); }

.check-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.check-list:empty { display: none; }
.check-item {
  display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: start;
  padding: 8px 12px; border-radius: var(--radius); border: 1px solid;
}
.check-item strong { display: block; }
.check-item-error { background: var(--error-bg); border-color: var(--error-border); }
.check-item-error .check-level { color: var(--error); }
.check-item-warning { background: var(--warning-bg); border-color: var(--warning-border); }
.check-item-warning .check-level { color: var(--warning); }
.check-item-info { background: var(--info-bg); border-color: var(--accent-soft-border); }
.check-item-info .check-level { color: var(--info); }
.check-level { font-weight: 800; font-size: 12px; letter-spacing: 0.08em; padding-top: 2px; }

/* ---------- Dialogs ---------- */

.dialog {
  border: none; border-radius: var(--radius-lg); padding: 0;
  width: min(640px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  box-shadow: 0 12px 40px rgba(20, 30, 50, 0.25);
  color: var(--text);
}
.dialog-wide { width: min(900px, calc(100vw - 32px)); }
.dialog-narrow { width: min(440px, calc(100vw - 32px)); }
.dialog::backdrop { background: rgba(20, 30, 50, 0.45); }
.dialog-body { padding: 20px 24px 24px; overflow: auto; max-height: calc(100vh - 48px); }
.dialog-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.dialog h2 { margin: 0; font-size: 20px; }
.dialog h3 { font-size: 16px; margin: 20px 0 8px; }
.dialog-hint { color: var(--text-muted); margin: 0 0 14px; }
.dialog-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
.dialog-actions-left { justify-content: flex-start; margin-top: 0; margin-bottom: 14px; }
.about-list { margin: 0 0 12px; padding-left: 20px; }
.about-list li { margin-bottom: 6px; }

/* Examples */
.example-group { margin-bottom: 18px; }
.example-group h3 { margin: 0 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.examples-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.example-card {
  text-align: left; padding: 12px 14px; min-height: 64px;
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
}
.example-card .example-concept { font-weight: 400; color: var(--text-muted); font-size: 13px; white-space: normal; }

/* Quick make (open evenings and first lessons) */
.dialog-header-actions { display: flex; gap: 8px; }
.quick-layout { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 20px; align-items: start; }
.quick-section { margin-bottom: 18px; }
.quick-section h3, .quick-section h4 { margin: 0 0 8px; font-size: 15px; }

/* The three steps: a bar of links at the top, a numbered block for each. */
.quick-steps { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 16px; }
.quick-step {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 14px;
  border: 1px solid var(--accent-soft-border); border-radius: var(--radius-pill);
  background: var(--accent-soft); color: var(--text); font-weight: 600; text-decoration: none;
}
.quick-step:hover { background: var(--accent-soft-hover); }
.quick-step span {
  display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent); color: var(--accent-text); font-size: 13px;
}
.quick-step-section {
  border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px 16px 4px;
  margin-bottom: 16px; scroll-margin-top: 8px;
}
.dialog .quick-step-title { margin: 0 0 12px; font-size: 17px; }
.quick-card:disabled { opacity: 0.55; }
#quick-print-note { margin-top: 10px; }
.quick-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
.quick-cards-small { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); }
.quick-card {
  text-align: left; padding: 10px 12px; min-height: 58px; height: auto;
  display: flex; flex-direction: column; gap: 3px; align-items: flex-start;
}
.quick-card.is-selected {
  /* .btn[aria-pressed="true"] paints a solid accent button with white text; a
     card is too big for that, so take back both the background and the colour. */
  border-color: var(--accent); background: var(--accent-soft); color: var(--text);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.quick-card-title { font-weight: 600; white-space: normal; }
.quick-card-hint { font-weight: 400; color: var(--text-muted); font-size: 13px; white-space: normal; }
.quick-subsection { margin-bottom: 12px; }
.quick-label { display: block; font-size: 13px; color: var(--text-muted); font-weight: 600; margin-bottom: 4px; }
.quick-colours { display: flex; flex-wrap: wrap; gap: 8px; }
.quick-colour {
  width: 34px; height: 34px; min-width: 34px; padding: 0; border-radius: 50%;
  border: 1px solid var(--border);
}
.quick-colour, .quick-colour[aria-pressed="true"] { background: var(--swatch); }
.quick-colour.is-selected { box-shadow: 0 0 0 3px var(--accent); }
.quick-preview { position: sticky; top: 0; min-width: 0; }
.quick-3d-wrap { position: relative; margin-bottom: 12px; }
.quick-3d { height: 230px; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; position: relative; }
.quick-3d-status {
  position: absolute; left: 8px; bottom: 8px; margin: 0; padding: 4px 8px; font-size: 12px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-muted);
}
.quick-group-title {
  grid-column: 1 / -1; margin: 6px 0 0; font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted);
}
.quick-card.has-icon { flex-direction: row; align-items: center; gap: 10px; }
.quick-card-icon { flex: 0 0 40px; width: 40px; height: 40px; display: grid; place-items: center; color: var(--accent); }
.quick-card-icon svg { width: 40px; height: 40px; overflow: visible; }
.quick-card-icon .icon-fill { fill: currentColor; }
.quick-card-icon .icon-hole, .quick-card-icon .icon-cut { fill: var(--surface); }
.quick-card.is-selected .quick-card-icon .icon-hole, .quick-card.is-selected .quick-card-icon .icon-cut { fill: var(--accent-soft); }
.quick-card-icon .icon-cut-stroke { stroke: var(--surface); }
.quick-card-icon .icon-accent { fill: var(--run); }
.quick-card-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.quick-card:disabled .quick-card-icon { color: var(--text-muted); }
.quick-preview h3 { margin-top: 0; }
.quick-code {
  font-family: var(--mono); font-size: 12px; line-height: 1.5; margin: 0 0 10px;
  padding: 12px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); max-height: 30vh; overflow: auto; white-space: pre;
}

/* Kiosk mode: bigger targets for a shared machine at an open evening. */
body.kiosk .quick-card { min-height: 70px; padding: 14px 16px; font-size: 16px; }
body.kiosk .quick-colour { width: 44px; height: 44px; min-width: 44px; }
body.kiosk .dialog-actions .btn { height: 48px; padding: 0 22px; font-size: 16px; }
body.kiosk #quick-name { height: 48px; font-size: 18px; }

@media (max-width: 980px) {
  .quick-layout { grid-template-columns: 1fr; }
  .quick-preview { position: static; }
  .quick-code { max-height: 220px; }
}

/* Setting up VS Code for Education */
.setup-steps { margin: 0 0 14px; padding-left: 22px; display: flex; flex-direction: column; gap: 16px; }
.setup-steps li { padding-left: 4px; }
.setup-steps strong { display: block; margin-bottom: 4px; }
.setup-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.setup-url { font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere; }
.setup-code {
  font-family: var(--mono); font-size: 13px; line-height: 1.5; margin: 8px 0 0;
  padding: 12px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: auto; white-space: pre;
}
#share-link { font-family: var(--mono); font-size: 13px; }

/* Challenges */
.challenge-list { display: flex; flex-direction: column; gap: 8px; }
.challenge-row {
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
.challenge-row.is-passed { background: var(--ok-bg); border-color: var(--ok-border); }
.challenge-row h4 { margin: 0 0 2px; font-size: 15px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.challenge-row p { margin: 0; color: var(--text-muted); font-size: 13px; }
.challenge-tag {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  background: var(--surface-2); color: var(--text-muted); padding: 2px 8px; border-radius: var(--radius-pill);
  border: 1px solid var(--border);
}

/* Projects */
.projects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.project-card {
  border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden;
  background: var(--surface); display: flex; flex-direction: column;
}
.project-thumb {
  display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  background: var(--surface-2); border: none; cursor: pointer; padding: 0;
}
.project-thumb.is-blank { display: grid; place-items: center; color: var(--text-muted); font-size: 13px; }
.project-meta { padding: 10px 12px; display: flex; flex-direction: column; gap: 4px; }
.project-meta strong { font-size: 14px; word-break: break-word; }
.project-meta time { font-size: 12px; color: var(--text-muted); }
.project-buttons { display: flex; gap: 6px; padding: 0 10px 10px; }
.project-buttons .btn { flex: 1; }

/* History */
.history-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.history-list li {
  display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius);
}
.history-list time { font-size: 12px; color: var(--text-muted); display: block; }
.history-snippet { font-family: var(--mono); font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Help */
.help-layout { display: grid; grid-template-columns: 150px 1fr; gap: 20px; }
.help-nav { display: flex; flex-direction: column; gap: 6px; position: sticky; top: 0; align-self: start; }
.help-nav a { padding: 8px 10px; border-radius: var(--radius-sm); text-decoration: none; color: var(--info); font-weight: 600; }
.help-nav a:hover { background: var(--surface-2); }
.help-content h3 { margin-top: 8px; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.help-content h4 { margin: 18px 0 6px; font-size: 14px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; }
.command { padding: 10px 0; border-bottom: 1px dashed var(--border); }
.command code.syntax { font-family: var(--mono); font-weight: 700; font-size: 14px; color: var(--info); }
.command p { margin: 4px 0; }
.command pre, .topic pre {
  margin: 6px 0 0; padding: 8px 10px; font-family: var(--mono); font-size: 13px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: auto;
}
.topic { padding: 10px 0; }
.topic h4 { text-transform: none; letter-spacing: 0; font-size: 15px; color: var(--text); margin-bottom: 4px; }
.topic p { margin: 4px 0; }
.shortcuts { border-collapse: collapse; width: 100%; }
.shortcuts td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.shortcuts td:first-child { font-family: var(--mono); font-size: 13px; white-space: nowrap; }

/* Settings */
.settings-group { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 16px 16px; margin: 0 0 14px; }
.settings-group legend { font-weight: 700; padding: 0 6px; }
.field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.field span { font-size: 13px; color: var(--text-muted); font-weight: 600; }
.field input, .field select {
  height: 40px; padding: 0 10px; border: 1px solid var(--border); border-radius: var(--radius); background: #fff;
}
.field textarea {
  font-family: var(--mono); font-size: 13px; padding: 8px 10px; resize: vertical;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text);
}
.field-check input { height: 24px; flex: 0 0 24px; min-width: 24px; }
.field-hint { color: var(--text-muted); font-size: 12px; line-height: 1.4; }
.field-wide { grid-column: 1 / -1; }

/* Slicer settings: shared by Settings and the G-code dialog. */
.slice-settings { display: flex; flex-direction: column; gap: 8px; }
.slice-group { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.slice-group > summary { cursor: pointer; font-weight: 700; padding: 10px 14px; min-height: 24px; }
.slice-group[open] > summary { border-bottom: 1px solid var(--border); }
.slice-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 0 14px; padding: 12px 14px 2px; }
.slice-grid .field-check { align-self: center; }

/* The G-code dialog and its print preview player. */
.dialog.dialog-gcode { width: min(1040px, calc(100vw - 32px)); }
.gcode-step { border-top: 1px solid var(--border); padding-top: 14px; margin-top: 14px; }
.dialog .gcode-step-title { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; font-size: 17px; }
.gcode-step-title span {
  display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent); color: var(--accent-text); font-size: 14px; flex: 0 0 26px;
}
.gcode-summary {
  margin: 0 0 12px; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2);
  border: 1px solid var(--border); font-weight: 600; font-variant-numeric: tabular-nums;
}
.gcode-recommend { border: 1px solid var(--ok-border); background: var(--ok-bg); border-radius: var(--radius-lg); padding: 12px 14px; margin-bottom: 12px; }
.gcode-recommend-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px; }
.gcode-recommend h4 { margin: 0; font-size: 15px; }
.gcode-recommend-state { font-size: 13px; font-weight: 700; color: var(--warning); }
.gcode-recommend-state.is-match { color: var(--ok); }
.gcode-recommend-list { margin: 8px 0; padding-left: 20px; display: grid; gap: 4px; font-size: 14px; }
.gcode-recommend-note { margin: 6px 0; font-size: 13px; color: var(--warning); font-weight: 600; }
.gcode-all-settings > summary { cursor: pointer; font-weight: 700; padding: 8px 0; min-height: 24px; }
.gcode-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 8px; }
.btn-large { min-height: 46px; padding: 0 24px; font-size: 16px; }
.gcode-mode-cards { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.gcode-results { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; margin-top: 12px; }
.gcode-results > .message, .gcode-results > .dialog-actions { grid-column: 1 / -1; margin: 0; }
.gcode-file { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px; }
.gcode-file h4 { margin: 0 0 4px; }
.gcode-file p { margin: 0 0 8px; font-size: 13px; }
.gcode-filename { font-family: var(--mono); color: var(--text-muted); word-break: break-all; }
.gcode-pause { color: var(--warning); font-weight: 600; }
.print-player { margin-top: 12px; }
.print-player h3 { margin-top: 0; }
.print-player-view { height: min(420px, 55vh); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; position: relative; }
.print-player-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.print-player-controls input[type="range"] { flex: 1 1 200px; min-width: 140px; }
.print-player-speed { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-muted); font-weight: 600; }
.print-player-speed select { min-height: 34px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
.print-player-readout { font-variant-numeric: tabular-nums; font-weight: 600; margin: 8px 0 2px; }
.field-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.field-check { flex-direction: row; align-items: center; gap: 10px; }
.field-check input { width: 24px; height: 24px; }
.field-check span { color: var(--text); font-weight: 400; }

/* ---------- Responsive ---------- */

@media (max-width: 1240px) {
  .topbar-actions .btn { padding: 0 12px; }
  .project-name { max-width: 220px; }
}

@media (max-width: 1040px) {
  /* Stacked layout: the document scrolls normally instead of each pane. */
  html, body { height: auto; }
  body { display: block; overflow: visible; min-height: 100vh; }
  .topbar { flex-wrap: wrap; height: auto; padding: 8px 12px; gap: 8px; }
  .project-name { order: 3; max-width: none; flex-basis: 100%; }
  .workspace { grid-template-columns: 1fr; grid-template-rows: auto auto; }
  .pane-editor { height: 520px; }
  .pane-viewport { height: 420px; }
  .statusbar { max-height: none; }
  .status-actions { margin-left: 0; width: 100%; justify-content: space-between; }
  .help-layout { grid-template-columns: 1fr; }
  .help-nav { flex-direction: row; flex-wrap: wrap; position: static; }
  .field-row { grid-template-columns: 1fr; }
  .menu-panel { right: auto; left: 0; }
}

@media (max-width: 620px) {
  .model-stats { gap: 12px; }
  /* The pane's tools become one swipeable row rather than three stacked ones,
     so the heading and the 3D view keep their space. */
  .pane-header { flex-wrap: nowrap; }
  .pane-tools {
    flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start;
    padding-bottom: 2px; scrollbar-width: thin;
  }
  .pane-tools .btn { padding: 0 10px; flex: 0 0 auto; }
  .pane-header h2 { flex: 0 0 auto; }
  .btn-run kbd { display: none; }   /* no keyboard to speak of on a phone */
  .topbar-actions { gap: 6px; }
  .topbar-actions .btn { padding: 0 10px; font-size: 14px; }
}

/* Windows high-contrast mode replaces every colour we choose, so any state
   shown only by a fill - a pressed toggle, a selected card - would disappear.
   Give each of them a border the system cannot take away. */
@media (forced-colors: active) {
  .btn[aria-pressed="true"],
  .quick-card.is-selected,
  .plate-item.selected,
  .challenge-passed,
  #tutorial-list button[aria-current="true"] {
    outline: 2px solid; outline-offset: -3px;
  }
  .check-item, .message, .status-badge { border: 1px solid; }
}

/* Print planning */
.printer-summary { text-decoration: underline; text-underline-offset: 3px; }
.estimate-controls { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.estimate-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-top: 18px; }
.estimate-card { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px; }
.estimate-card h3 { margin: 0; }
.estimate-card p { font-size: 12px; }
.estimate-card .estimate-time { font-size: 23px; font-weight: 800; margin: 12px 0 4px; }
.estimate-card dl { font-size: 12px; margin: 0; }
.estimate-card dt { color: var(--text-muted); margin-top: 8px; }
.estimate-card dd { margin: 0; font-weight: 600; }
.estimate-assumptions { margin-top: 20px; font-size: 13px; }
.estimate-assumptions summary { cursor: pointer; font-weight: 700; }
@media (max-width: 700px) { .estimate-grid, .estimate-controls { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px) { .estimate-controls { grid-template-columns: 1fr; } }

/* Open day: templates printed in advance, designs printed over them. */
.openday-layout { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 20px; align-items: start; }
.openday-steps .openday-first { border-top: 0; margin-top: 0; padding-top: 0; }
.openday-preview { position: sticky; top: 0; min-width: 0; }
.openday-preview h3 { margin-top: 0; }
.openday-viewport { height: min(520px, 60vh); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; position: relative; }
.openday-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#page-openday .quick-cards { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.openday-base { min-height: 52px; }
.openday-designs { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; max-height: 260px; overflow: auto; }
.openday-design { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.openday-design > span:nth-child(2) { flex: 1; min-width: 0; }
.openday-design.is-printed { background: var(--ok-bg); border-color: var(--ok-border); }
.openday-slot {
  display: inline-grid; place-items: center; min-width: 30px; height: 30px; padding: 0 6px; border-radius: var(--radius-pill);
  background: var(--accent); color: var(--accent-text); font-weight: 700; font-variant-numeric: tabular-nums;
}
.quick-openday { margin-bottom: 14px; }
.quick-openday .message-link + .message-link { margin-left: 12px; }

/* Full-screen Open day page (also ?openday) */
.page-openday {
  position: fixed; inset: 0; z-index: 40;
  background: var(--bg); color: var(--text);
  overflow: auto;
}
.page-openday .page-body {
  box-sizing: border-box;
  width: min(1320px, 100%);
  margin: 0 auto;
  padding: 20px 24px 40px;
}
.page-openday .page-header { flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
.page-openday .openday-viewport { height: min(560px, calc(100vh - 180px)); }
body.openday-page .topbar,
body.openday-page .workspace { display: none; }

/* Open day Quick make fills the window like its own page */
body.openday-quick #dialog-quickmake {
  width: 100vw; max-width: none; height: 100vh; max-height: none;
  margin: 0; border-radius: 0; box-shadow: none;
}
body.openday-quick #dialog-quickmake::backdrop { background: var(--bg); }
body.openday-quick #dialog-quickmake .dialog-body {
  max-height: 100vh; height: 100vh; box-sizing: border-box;
  width: min(1200px, 100%); margin: 0 auto;
}
body.openday-quick .topbar,
body.openday-quick .workspace { display: none; }

@media (max-width: 980px) {
  .openday-layout { grid-template-columns: 1fr; }
  .openday-preview { position: static; }
  .openday-row { grid-template-columns: 1fr; }
}

/* The open day guide */
.guide-contents { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.guide-contents a {
  display: inline-flex; align-items: center; min-height: 32px; padding: 0 12px; border-radius: var(--radius-pill);
  background: var(--accent-soft); border: 1px solid var(--accent-soft-border); color: var(--text); font-weight: 600; text-decoration: none;
}
.guide-section { border-top: 1px solid var(--border); padding-top: 12px; margin-top: 12px; scroll-margin-top: 8px; }
.dialog .guide-section h3 { display: flex; align-items: center; gap: 10px; margin: 0 0 8px; font-size: 17px; }
.guide-section h3 span {
  display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent); color: var(--accent-text); font-size: 14px;
}
.guide-section ol { margin: 0; padding-left: 22px; display: grid; gap: 8px; line-height: 1.5; }
.guide-note { margin: 10px 0 0; padding: 8px 12px; border-radius: var(--radius); background: var(--info-bg); color: var(--text); }
.guide-faq dt { font-weight: 700; margin-top: 12px; }
.guide-faq dd { margin: 4px 0 0; line-height: 1.5; }
.help-nav .btn { margin-top: 8px; }

/* About: which version is published */
.about-build { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 0 0 12px; }
.about-build dt { color: var(--text-muted); font-weight: 600; }
.about-build dd { margin: 0; font-variant-numeric: tabular-nums; }
