/* pytrainer.css — single-viewport app layout and panel styling.
   Injected by engine.js; the host page only provides the mount div. */

/* Minimal page reset so the app fills the viewport with no page scrolling.
   (When embedded in Hugo, the shortcode's page can override this.) */
html, body {
  height: 100%;
  margin: 0;
}

.pt-app {
  height: 100vh;
  height: 100dvh; /* mobile: exclude the browser's collapsing URL bar */
  display: grid;
  grid-template-columns: 1fr 320px;
  /* The middle track is the horizontal divider that resizes the output
     pane; ui.js overwrites the third track once the bar has been dragged.
     minmax(0, 1fr) and not 1fr: the auto floor of a plain 1fr would stop
     the pane row shrinking past its content, which is exactly what
     growing the output has to do. */
  grid-template-rows: minmax(0, 1fr) 8px 190px;
  grid-template-areas:
    "editor  side"
    "hdiv    hdiv"
    "console console";
  gap: 8px;
  padding: 8px;
  box-sizing: border-box;
  /* When the panes don't fit (phones, narrow windows) the whole view pans
     horizontally; panning inside a pane scroll-chains up to here, while the
     dividers (touch-action: none) still resize on drag. */
  overflow-x: auto;
  overflow-y: hidden;
  /* Divider drags change column widths while scrolled; scroll anchoring
     would adjust scrollLeft to visually cancel the resize. */
  overflow-anchor: none;
  background: #f2f3f5;
  color: #1d2129;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
}

/* With a course loaded, the runtime adds nav + lesson panels and switches
   the grid to four columns. Same single-viewport, no-page-scroll rule. */
.pt-app.pt-with-course {
  grid-template-columns: 230px 340px 1fr 300px;
  grid-template-areas:
    "nav     lesson  editor  side"
    "hdiv    hdiv    hdiv    hdiv"
    "console console console console";
}

/* ---- pane dividers (created by ui.js; each sits in its own 8px grid
   column that replaces the column gap, so dragging one resizes the panes
   beside it, and one more in an 8px row above the output pane) ---- */

.pt-divider {
  cursor: col-resize;
  touch-action: none;
  display: flex;
  align-items: stretch;
  justify-content: center;
}

.pt-divider::after {
  content: "";
  width: 2px;
  border-radius: 1px;
  background: #d5d9de;
}

.pt-divider:hover::after,
.pt-divider.pt-dragging::after {
  background: #7aa7e8;
}

/* The one horizontal bar: same 8px track, turned on its side. Height is
   the scarce resource on a desktop, so this is the divider that matters —
   dragging it up grows the output pane and shrinks the panes above. */
.pt-divider-h {
  cursor: row-resize;
  flex-direction: column;
  justify-content: center;
}

.pt-divider-h::after {
  width: auto;
  height: 2px;
}

/* Split, the output is the last grid row and has nothing under it to trade
   height with, so its bottom edge is not a boundary at all. The stacked
   layout below turns it back on. */
.pt-divider-h-bottom {
  display: none;
}

/* Touch: an 8px bar is too thin a target, so extend the hit area over the
   neighboring panes (pseudo-element boxes hit-test as the divider itself;
   dividers are appended after the panes, so they win the overlap). */
@media (pointer: coarse) {
  .pt-divider {
    position: relative;
  }

  .pt-divider::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -14px;
    right: -14px;
    z-index: 1; /* beat the panes' own positioned content in the overlap */
  }

  /* Only upwards: below the bar sits the output pane's Clear button, and
     the divider's hit area would otherwise cover its top 14px. */
  /* Upwards only: under this bar sits the output pane's Clear button, and
     a symmetric hit area would cover its top 14px. */
  .pt-divider-h::before {
    top: -14px;
    bottom: 0;
    left: 0;
    right: 0;
  }

  /* And the other way for the bottom edge: the variables pane under it is
     free space, where the output's own scrolling text above is not. */
  .pt-divider-h-bottom::before {
    top: 0;
    bottom: -14px;
  }
}

/* Short viewports (landscape phones): the fixed 190px console row would
   swallow most of the screen — give the top row the space instead. */
@media (max-height: 520px) {
  .pt-app {
    grid-template-rows: minmax(0, 1fr) 8px minmax(80px, 24dvh);
  }
}

/* ---- code pane: toolbar + editor ---- */

.pt-editor-pane {
  grid-area: editor;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pt-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px;
  background: #fff;
  border: 1px solid #d5d9de;
  border-radius: 6px;
  /* Always a single row: when it doesn't fit, the row slides sideways.
     Contained so a swipe here doesn't pan the whole app. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}

/* Groups and the status pill keep their natural width instead of being
   squeezed — overflow slides, it never shrinks or wraps. */
.pt-toolbar > * {
  flex-shrink: 0;
}

/* One button group: (Run, Stop), (Step mode, Next, Stop), (Restore). */
.pt-group {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px;
  background: #f1f3f5;
  border: 1px solid #e0e4e8;
  border-radius: 7px;
}

/* The group that owns the current activity: yellow while running or
   stepping, and on the Restore group while its inline query is open. */
.pt-group.pt-group-active {
  background: #fdeaa0;
  border-color: #dfc45a;
}

.pt-toolbar button {
  font: inherit;
  padding: 5px 12px;
  border: 1px solid #c2c8cf;
  border-radius: 5px;
  background: #fafbfc;
  cursor: pointer;
  white-space: nowrap;
}

.pt-toolbar button:hover:not(:disabled) {
  background: #eef1f4;
}

.pt-toolbar button:disabled {
  opacity: 0.45;
  cursor: default;
}

.pt-toolbar button.pt-active {
  background: #dbe9ff;
  border-color: #7aa7e8;
}

/* Inline restore query: gentle amber strip inside the Restore group. */
.pt-restore-confirm {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-block: 2px;
  padding-inline: 8px 4px;
  background: #fff8e1;
  border: 1px solid #ecd9a0;
  border-radius: 5px;
  font-size: 13px;
  color: #6b5615;
}

.pt-restore-confirm[hidden] {
  display: none;
}

.pt-restore-confirm button {
  padding: 2px 9px;
  font-size: 13px;
}

/* Settings group (the gear, at the toolbar's far end). Its controls unfold
   inline. */
.pt-settings-inline {
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
  font-size: 13px;
  color: #3c4652;
}

.pt-settings-inline[hidden] {
  display: none;
}

.pt-settings-inline label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.pt-settings-inline input {
  width: 52px;
  font: inherit;
  font-size: 13px;
  padding: 2px 5px;
  border: 1px solid #c2c8cf;
  border-radius: 4px;
  background: #fff;
}

.pt-status {
  margin-inline-start: auto;
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 13px;
  background: #e8eaed;
}

.pt-status::before {
  content: "●";
  margin-inline-end: 6px;
}

.pt-status[data-state="loading"]::before  { color: #e6a817; }
.pt-status[data-state="ready"]::before    { color: #2e9e44; }
.pt-status[data-state="running"]::before  { color: #d97706; }
.pt-status[data-state="stepping"]::before { color: #2563eb; }
.pt-status[data-state="error"]::before    { color: #d32f2f; }

/* ---- editor ---- */

.pt-editor {
  flex: 1;
  min-height: 0;
  border: 1px solid #d5d9de;
  border-radius: 6px;
  overflow: hidden;
  background: #fff;
}

.pt-editor .CodeMirror {
  height: 100%;
  font-family: "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
  font-size: 14px;
}

.pt-editor .CodeMirror.pt-readonly {
  background: #f7f8f9;
}

/* Line about to execute in step mode. */
.pt-current-line {
  background: #fff1a8 !important;
}

/* ---- side panels ---- */

.pt-side {
  grid-area: side;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pt-panel {
  background: #fff;
  border: 1px solid #d5d9de;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.pt-vars { flex: 3; }

/* A step's diagram, above the variables. It sizes itself to the image until
   the bar under it is dragged; ui.js then pins its flex-basis. */
.pt-diagram { flex: 0 1 auto; max-height: 60%; }
.pt-diagram[hidden] { display: none; }
.pt-diagram-body {
  flex: 1;
  min-height: 0;
  padding: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pt-diagram-body img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}
.pt-diagram-body img:focus-visible {
  outline: 2px solid #4b8ee0;
  outline-offset: 2px;
}

/* The diagram over the whole page, as RefTrainer shows its images. SVG
   scales losslessly, so this is as large as the screen allows. */
.pt-lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 20px;
  background: rgba(29, 33, 41, 0.74);
  cursor: zoom-out;
}
.pt-lightbox img {
  width: min(96vw, 1200px);
  height: min(80vh, 820px);
  object-fit: contain;
  background: #fff;
  border-radius: 6px;
  padding: 14px;
  box-sizing: border-box;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
}
.pt-lightbox-hint {
  margin: 0;
  color: #98a2ad;
  font-size: 11px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
/* The bar sits in the side column's 8px gap rather than adding a third. */
.pt-divider-diagram { height: 8px; margin: -8px 0; flex: none; }
.pt-divider-diagram[hidden] { display: none; }
.pt-files { flex: 1; }

.pt-panel h2 {
  margin: 0;
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #5b6470;
  background: #f6f7f8;
  border-bottom: 1px solid #e3e6ea;
}

/* The lesson panel's header is the path to the current step, with each
   segment a control that re-orients the outline. That needs to be readable
   and clickable, so it drops the uppercase micro-label treatment the other
   panel headers use. */
.pt-lesson-title {
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  color: #3c4652;
}

.pt-crumb {
  font: inherit;
  color: #2c6cc4;
  background: none;
  border: 0;
  margin: 0;
  padding: 1px 4px;
  border-radius: 3px;
  cursor: pointer;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* When the pane is narrow the chapter gives up room first — the lesson is
   the more useful half of the path to keep readable. */
.pt-crumb { flex: 0 1 auto; min-width: 4ch; }
.pt-crumb:first-of-type { flex-shrink: 4; }

.pt-crumb:hover { background: #e6eefb; text-decoration: underline; }

.pt-crumb:focus-visible {
  outline: 2px solid #7aa7e8;
  outline-offset: 1px;
}

.pt-crumb-sep { flex: none; color: #98a2ad; }

.pt-vars-body {
  overflow: auto;
  padding: 6px 8px;
  flex: 1;
}

.pt-vars-section + .pt-vars-section {
  margin-top: 10px;
}

.pt-vars-title {
  font-size: 11px;
  font-weight: 600;
  color: #7a828d;
  margin-bottom: 3px;
}

/* Locals of the current frame, distinguished from globals. */
.pt-vars-locals {
  background: #eef5ff;
  border: 1px solid #cfe0f7;
  border-radius: 5px;
  padding: 5px 7px;
}

.pt-vars-locals .pt-vars-title {
  color: #2b5aa0;
}

.pt-vars-body table {
  width: 100%;
  border-collapse: collapse;
  font-family: "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
}

.pt-vars-body td {
  padding-block: 2px;
  padding-inline: 0 6px;
  vertical-align: top;
  border-bottom: 1px solid #f0f2f4;
}

.pt-var-name {
  color: #8a4baf;
  white-space: nowrap;
}

.pt-var-value {
  color: #1d2129;
  word-break: break-all;
  width: 100%;
}

.pt-files-body {
  margin: 0;
  padding: 6px 10px;
  overflow: auto;
  list-style: none;
  flex: 1;
  font-family: "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
}

.pt-files-body li {
  padding: 2px 0;
}

.pt-files-body li::before {
  content: "📄 ";
}

.pt-empty {
  color: #9aa1ab;
  font-style: italic;
  font-size: 13px;
}

/* ---- course navigation panel ---- */

.pt-nav { grid-area: nav; }

.pt-nav-body {
  overflow: auto;
  flex: 1;
  padding: 8px 10px;
  font-size: 13px;
}

/* The outline is a browser: expanded/collapsed is a viewing preference,
   independent of which lesson is current. "You are here" is a quiet stripe
   (.pt-here) down the row's leading edge, carried by the deepest row still
   visible on the path to the current step, so collapsing hands it up
   rather than losing it. */

.pt-nav-twisty {
  display: inline-block;
  width: 14px;
  flex: none;
  color: #98a2ad;
  font-size: 10px;
  line-height: inherit;
  text-align: center;
  user-select: none;
}

/* The lesson twisty is a real button: its own hit target, so it can
   expand without selecting. */
.pt-nav-twisty-btn {
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: inherit;
}

.pt-nav-twisty-btn:hover { color: #3c4652; }

.pt-nav-twisty-btn:focus-visible {
  outline: 2px solid #7aa7e8;
  outline-offset: 1px;
  border-radius: 3px;
}

.pt-nav-chapter {
  display: flex;
  align-items: center;
  gap: 2px;
  font-weight: 700;
  color: #3c4652;
  margin: 10px 0 2px;
  padding-block: 3px;
  padding-inline: 2px 6px;
  border-inline-start: 2px solid transparent;
  border-radius: 4px;
  cursor: pointer;
}

.pt-nav-chapter:first-child { margin-top: 0; }
.pt-nav-chapter:hover { background: #eef1f4; }

.pt-nav-chapter:focus-visible {
  outline: 2px solid #7aa7e8;
  outline-offset: -2px;
}

.pt-nav-chapter-title { flex: 1; min-width: 0; }

.pt-nav-count {
  flex: none;
  font-weight: 400;
  font-size: 11px;
  color: #98a2ad;
  font-variant-numeric: tabular-nums;
}

.pt-nav-lessons {
  list-style: none;
  margin: 0 0 4px;
  padding: 0;
  padding-inline-start: 8px;
}

.pt-nav-lesson-row {
  display: flex;
  align-items: baseline;
  gap: 2px;
  padding-block: 3px;
  padding-inline: 2px 6px;
  border-inline-start: 2px solid transparent;
  border-radius: 4px;
}

.pt-nav-lesson-label {
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

.pt-nav-lesson-row:hover { background: #f4f6f8; }
.pt-nav-lesson-label:hover { text-decoration: underline; }

.pt-nav-badge {
  flex: none;
  font-size: 11px;
  color: #5b6470;
  font-variant-numeric: tabular-nums;
}

/* Outline numbering (courses that set `numberedOutline`). The digits are a
   column the eye runs down, so they stay quiet and tabular instead of
   thickening the title they sit beside. */
.pt-nav-num {
  color: #98a2ad;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  /* An outline number is Western digits and dots whatever the prose is, so
     it is its own little LTR run. Without the isolate a chapter's trailing
     dot is a neutral at the end of an RTL line and renders as ".1". */
  direction: ltr;
  unicode-bidi: isolate;
  /* ...which also pins the span's own inline axis to LTR, so `end` here is
     the digits' right — the side the title is on in an LTR outline, and the
     wrong side in a mirrored one. */
  margin-inline-end: 0.45em;
}

[dir="rtl"] .pt-nav-num {
  margin-inline: 0.45em 0;
}

/* Quiet position marker — not a filled block. */
.pt-here {
  border-inline-start-color: #4b8ee0;
  background: #f2f6fc;
}

/* Reveal from the breadcrumb: a brief pulse so the eye catches the row. */
@keyframes pt-flash {
  0%, 100% { background: transparent; }
  25%      { background: #ffe9a8; }
}

.pt-flash { animation: pt-flash 1.1s ease-in-out 1; }

@media (prefers-reduced-motion: reduce) {
  .pt-flash { animation-duration: 0.01s; }
}

.pt-nav-steps {
  list-style: none;
  margin: 2px 0 4px;
  padding: 0;
  padding-inline-start: 14px;
}

.pt-nav-step {
  padding: 2px 6px;
  border-radius: 4px;
  color: #5b6470;
  cursor: pointer;
}

.pt-nav-step:hover { background: #eef1f4; }

.pt-nav-step.pt-current {
  color: #1d2129;
  font-weight: 600;
  background: #eaf1fc;
}

/* Progress ✓ marks: the same success green as the Check button/result,
   so a passed step/lesson is visible at a glance in the nav. */
.pt-nav-mark {
  color: #1d6b2a;
  font-weight: 700;
}

/* Reset options at the foot of the nav (mirrors LxTrainer's block). */
.pt-danger {
  flex: none;
  border-top: 1px solid #e3e6ea;
  padding: 6px 10px;
  font-size: 12px;
  color: #7a828d;
}

.pt-danger summary { cursor: pointer; }

.pt-danger button {
  display: block;
  margin: 6px 0;
  font: inherit;
  font-size: 12px;
  padding: 4px 10px;
  border: 1px solid #c2c8cf;
  border-radius: 5px;
  background: #fafbfc;
  cursor: pointer;
}

.pt-danger button:hover { background: #eef1f4; }

/* ---- lesson text panel ---- */

.pt-lesson { grid-area: lesson; }

.pt-lesson-text {
  flex: 1;
  overflow-y: auto;     /* the text scrolls; the page never does */
  padding: 10px 14px;
  line-height: 1.5;
}

.pt-lesson-text h1, .pt-lesson-text h2, .pt-lesson-text h3 {
  margin: 0.3em 0 0.5em;
  font-size: 16px;
}

.pt-lesson-text p { margin: 0.6em 0; }

.pt-lesson-text code {
  font-family: "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.92em;
  background: #eef1f4;
  padding: 1px 4px;
  border-radius: 3px;
}

.pt-lesson-text pre {
  background: #f4f5f7;
  border: 1px solid #e3e6ea;
  border-radius: 5px;
  padding: 8px 10px;
  overflow-x: auto;
}

.pt-lesson-text pre code {
  background: none;
  padding: 0;
}

/* Markdown tables in course prose — the same rules reftrainer carries, kept
   identical across the three trainers so a table looks the same whichever
   one a course runs on. No PyTrainer course uses one yet, but the markdown path
   is shared (marked + DOMPurify), so a table would otherwise arrive with the
   browser's default styling: no borders, no cell padding. */
.pt-lesson-text table,
.pt-hint-text table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.7em 0;
  font-size: 0.95em;
}

.pt-lesson-text th, .pt-lesson-text td,
.pt-hint-text th, .pt-hint-text td {
  border: 1px solid #e3e6ea;
  padding: 4px 8px;
  text-align: start;
  vertical-align: top;
  /* "anywhere", not "break-word": only the former shrinks the cell's
     min-content width, which is what decides whether a wide table fits its
     pane or pushes a scrollbar under the whole column. */
  overflow-wrap: anywhere;
}

.pt-lesson-text th,
.pt-hint-text th {
  font-weight: 600;
  color: #1d2129;
  background: #f4f5f7;
}

.pt-lesson-text tbody tr:nth-child(even),
.pt-hint-text tbody tr:nth-child(even) {
  background: #fafbfc;
}

/* A cell is a tight space, so code in one drops the pill background it gets
   in running text and keeps only the monospace face. */
.pt-lesson-text td code, .pt-lesson-text th code,
.pt-hint-text td code, .pt-hint-text th code {
  background: none;
  padding: 0;
}

.pt-lesson-foot {
  border-top: 1px solid #e3e6ea;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pt-step-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pt-step-controls button {
  font: inherit;
  padding: 4px 10px;
  border: 1px solid #c2c8cf;
  border-radius: 5px;
  background: #fafbfc;
  cursor: pointer;
}

.pt-step-controls button:hover:not(:disabled) { background: #eef1f4; }
.pt-step-controls button:disabled { opacity: 0.45; cursor: default; }

.pt-step-pos {
  font-size: 12px;
  color: #7a828d;
  white-space: nowrap;
}

.pt-check-btn {
  margin-inline-start: auto;
  background: #2e7d32 !important;
  border-color: #2e7d32 !important;
  color: #fff;
  font-weight: 600;
}

.pt-check-btn:hover:not(:disabled) { background: #256b29 !important; }

/* ---- check result + hint ---- */

.pt-check-result {
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 13px;
}

.pt-check-result pre {
  margin: 6px 0 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px;
}

.pt-check-result.pt-pass {
  background: #e6f6e8;
  border: 1px solid #79c284;
  color: #1d6b2a;
}

.pt-check-result.pt-fail {
  background: #fdecea;
  border: 1px solid #f2a49e;
  color: #a8352a;
}

.pt-hint summary {
  cursor: pointer;
  color: #2563eb;
  font-size: 13px;
}

.pt-hint-text {
  margin-top: 6px;
  padding: 6px 10px;
  background: #fff8e1;
  border: 1px solid #ecd9a0;
  border-radius: 5px;
  font-size: 13px;
}

.pt-hint-text p { margin: 0.3em 0; }

.pt-hint-text code {
  font-family: "SF Mono", Menlo, Consolas, monospace;
  background: #f2ecd9;
  padding: 1px 4px;
  border-radius: 3px;
}

/* ---- course load error ---- */

.pt-course-error {
  max-width: 640px;
  margin: 12vh auto;
  padding: 20px 24px;
  background: #fff;
  border: 1px solid #f2a49e;
  border-radius: 8px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.pt-course-error h2 {
  margin: 0 0 10px;
  color: #a8352a;
  font-size: 18px;
}

.pt-course-error pre {
  background: #fdecea;
  border-radius: 5px;
  padding: 10px 12px;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 13px;
}

/* ---- console ---- */

/* The output pane is its own bar plus the scrolling text under it. The
   wrapper is what the grid places and what a divider drag resizes; the
   <pre> inside only holds output. */
.pt-output {
  grid-area: console;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: #14181d;
  border-radius: 6px;
  overflow: hidden;
  /* Stacked, the pane's height is set in px by the divider drag, which has
     to mean the height the drag measured. */
  box-sizing: border-box;
}

/* Wide and short: the row spans the pane, so the button is easy to aim at
   sideways and costs about the height of one line of output. */
.pt-output-bar {
  flex: none;
  display: flex;
  align-items: stretch;
  gap: 10px;
  height: 24px;
  padding: 0 10px;
  background: #1b2026;
  border-bottom: 1px solid #262c34;
}

/* The pane's name, in the micro-label treatment the light panels use for
   theirs — the output pane had none before. The button sits next to it
   rather than at the far end of a full-width bar, where the eye never goes
   looking for it. */
.pt-output-label {
  flex: none;
  align-self: center;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #6f7a86;
}

.pt-output-bar button {
  font: inherit;
  font-size: 12px;
  min-width: 76px;
  margin: 2px 0;
  padding: 0 12px;
  color: #c3cad2;
  background: #2a313a;
  border: 1px solid #39424d;
  border-radius: 4px;
  cursor: pointer;
  white-space: nowrap;
}

.pt-output-bar button:hover {
  background: #38414c;
  color: #eef2f6;
}

.pt-output-bar button:focus-visible {
  outline: 2px solid #7aa7e8;
  outline-offset: 1px;
}

/* A finger needs a taller target than a pointer does, so the bar grows and
   the button grows with it. The divider right above gives up its downward
   hit area in return (see the coarse-pointer block above), or the two would
   be competing for the same 14 pixels. */
@media (pointer: coarse) {
  .pt-output-bar { height: 34px; }
  .pt-output-bar button { min-width: 92px; font-size: 13px; }
}

.pt-console {
  flex: 1;
  min-height: 0;
  margin: 0;
  padding: 8px 10px;
  /* A long line scrolls rather than wraps, in both layouts. Wrapping one
     200-character line into five spends five lines of the height the pane
     was just dragged open to buy — and height is the scarce resource here,
     on a desktop as much as on a phone. */
  overflow: auto;
  color: #d8dde3;
  font-family: "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
  font-size: 13px;
  line-height: 1.45;
  white-space: pre;
}

.pt-out-stdout { color: #d8dde3; }
.pt-out-stderr { color: #ff6b6b; }   /* exceptions / stderr in red */
.pt-out-info   { color: #6f7a86; font-style: italic; }

/* Standing course-wide banner at the top of the nav pane, from the course
   file's optional `notice`. Yellow so it reads as a caveat, not chrome.
   No `display` property here on purpose: the element carries the `hidden`
   attribute when there is no notice, and a display rule would override it. */
.pt-nav-notice {
  margin: 0;
  padding: 7px 10px;
  flex: none;
  font-size: 12px;
  line-height: 1.4;
  font-weight: 600;
  color: #6b5200;
  background: #fff3bf;
  border-bottom: 1px solid #ecd77a;
}

/* ---- writing direction -------------------------------------------------

   The app mirrors itself: engine.js puts dir="rtl" on the mount for an RTL
   course, and a grid in RTL lays its columns out right to left — so the nav
   pane arrives on the right and the templates above are never duplicated.
   Everything one-sided is written as a logical property, which leaves only
   the rules below.

   What does NOT mirror is the code. Python is left-to-right in every
   language: identifiers, filenames, tracebacks and printed output are LTR
   text whose correct alignment is the left edge, whatever the prose around
   them does. So the panes that hold code are LTR islands inside an RTL
   page — the same split a bilingual editor makes — and only their headings
   follow the page. */

/* The editor is LTR under every course. CodeMirror measures its own
   geometry, and it has no RTL mode we could trust with step highlighting. */
.pt-editor,
.pt-editor .CodeMirror {
  direction: ltr;
  text-align: left;
}

/* Program output, variable reprs and filenames: LTR islands.
   The engine's own console banners are Hebrew inside this LTR box, which is
   why each is fenced with ── on both sides — a symmetric fence reads the
   same whichever way its middle runs. */
.pt-console,
.pt-vars-body table,
.pt-files-body {
  direction: ltr;
  text-align: left;
}

/* Code inside lesson prose. `isolate` is what stops a bidi run from
   reordering around it: without it a `print()` at the end of a Hebrew
   sentence drifts to the wrong edge, brackets and all. */
.pt-lesson-text code,
.pt-hint-text code,
.pt-lesson-text pre,
.pt-hint-text pre {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: left;
}

/* The check diagnostic is the one genuinely mixed block: Hebrew labels
   naming lines of Python output. `plaintext` gives each line its own
   direction from its own first strong character, so the prose reads RTL and
   the output reads LTR without either being forced through the other. */
.pt-check-result pre {
  unicode-bidi: plaintext;
}

/* Mirrored, the ✓ of a completed lesson sits before its title in reading
   order and the space that separated them lands on the wrong side. */
[dir="rtl"] .pt-nav-mark {
  unicode-bidi: isolate;
}

/* ---- narrow screens ----------------------------------------------------

   Below the breakpoint in ui.js the panes stack into one column and the page
   scrolls, instead of the four-pane grid panning sideways off a phone. Same
   breakpoint and same reasoning as RefTrainer: this is as much about 200-400%
   browser zoom as about phones (WCAG 1.4.10 Reflow).

   Python still runs here — Pyodide is WebAssembly, not a virtual machine —
   and most steps ship with their code already written, so Run and Step mode
   work without typing on a touch keyboard.

   ui.js clears the inline grid-template-columns/areas below this width;
   inline styles would otherwise beat everything in this block. */
@media (max-width: 859px) {
  .pt-app,
  .pt-app.pt-with-course {
    height: auto;
    min-height: 100dvh;
    /* One column: everything stacks, full width, and the page scrolls in
       ONE direction only. Two side-by-side columns were tried and dropped —
       at phone width each was ~190px, and turning the pair into a swiped
       strip would have meant scrolling in two dimensions with a whole pane
       hidden off-screen, which is the thing WCAG 1.4.10 Reflow exists to
       prevent.

       minmax(0, 1fr), not 1fr: a plain 1fr is minmax(AUTO, 1fr), and that
       auto floor stops a track shrinking below its content's min-content
       width — so one long token in the console or the editor would widen
       the column and push the page sideways anyway. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: none;
    overflow-x: hidden;
    overflow-y: visible;
    gap: 8px;
  }
  /* Nothing left to drag sideways once the panes are stacked — but height
     is scarce on a phone too, so the horizontal bar stays and resizes the
     output pane on its own (there are no panes beside it to take from). */
  .pt-divider:not(.pt-divider-h) { display: none; }
  /* Every pane carries a named grid-area (some inline, from ui.js). With the
     template areas gone those names resolve to lines that do not exist and
     the grid invents implicit COLUMNS for them — rebuilding the side-by-side
     layout. Hence auto, and hence !important for the inline ones. */
  .pt-nav, .pt-lesson, .pt-editor-pane, .pt-side, .pt-output, .pt-divider {
    grid-area: auto !important;
    /* Same reason as the track floor above: a grid item defaults to
       min-width:auto, which is min-content, and refuses to shrink. */
    min-width: 0;
  }
  /* The toolbar is a single sliding row on a desktop, which hides controls
     behind a horizontal scroll on a phone — the buttons ARE the interface
     here, so they wrap onto as many rows as they need instead. Groups stay
     intact when they can, and may wrap internally if one is wider than the
     screen on its own. */
  .pt-toolbar {
    flex-wrap: wrap;
    overflow-x: visible;
    row-gap: 6px;
  }
  .pt-group { flex-wrap: wrap; }
  /* DOM order is editor, side, console, nav, lesson — not the reading order
     a student wants, so it is set explicitly: outline, lesson, code, the
     results of running it, then the variables. Code and its output stay
     adjacent, one above the other rather than side by side. */
  .pt-nav            { order: 1; max-height: 38vh; }
  .pt-lesson         { order: 2; }
  .pt-editor-pane    { order: 3; min-height: 40vh; }
  /* The output pane is fenced by both of its edges here. Nothing in this
     column is elastic, so each edge trades height with the pane across it —
     the top with the code pane, the bottom with the variables pane — which
     is what lets both of them move with the finger. */
  .pt-divider-h-top  { order: 4; height: 8px; }
  .pt-output         { order: 5; min-height: 18vh; max-height: 40vh; }
  .pt-divider-h-bottom { order: 6; height: 8px; display: flex; }
  .pt-side           { order: 7; }
}
