* {
  box-sizing: border-box;
}

/* The page itself never scrolls; every scrollable thing is a pane inside the
   fixed-height app grid below. */
html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  background: #fff;
  color: #000;
}

/* The hidden attribute must survive our display declarations on elements it
   is toggled on, or the binary-file note and the find controls would both
   show at once. */
[hidden] {
  display: none !important;
}

/* 100vh first as the fallback, then 100dvh so iOS toolbars shrink the app
   instead of covering its bottom edge. */
.app {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  height: 100vh;
  height: 100dvh;
}

/* The top bar keeps the browser's default serif — it is the one line of
   document on an otherwise monospaced instrument. Embedded in the article,
   the article supplies that line itself, so the bar goes. */
.topbar {
  align-items: center;
  border-bottom: 1px solid #777;
  display: flex;
  gap: 1.1em;
  min-height: 34px;
  padding: 0 10px;
}

.topbar a {
  align-items: center;
  align-self: stretch;
  display: inline-flex;
}

.topbar strong {
  font-size: 0.94em;
}

.embedded .topbar {
  display: none;
}

/* minmax(0, 1fr) everywhere below: without it the code pane's long lines
   would widen the grid and force the page itself sideways. */
.main {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  min-height: 0;
  position: relative;
}

/* The warm grey is TypeCafe's structural navigation field. The rail scrolls
   by itself, independent of the code pane. position: relative makes a row's
   offsetTop measure from the list, which the scripted reveal relies on. */
.files {
  background: #f1f1eb;
  border-right: 1px solid #b0b0ab;
  font-family: "Courier New", Courier, monospace;
  line-height: 1.4;
  overflow-x: hidden;
  overflow-y: auto;
  padding: 4px 0 10px;
  position: relative;
  scrollbar-width: thin;
}

.row {
  align-items: baseline;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: inherit;
  cursor: pointer;
  display: flex;
  font: inherit;
  font-size: 11px;
  padding: 3px 10px;
  text-align: left;
  width: 100%;
}

.row:hover,
.row[aria-current="true"] {
  background: #fff;
}

.row[aria-current="true"] .row-name {
  font-weight: bold;
}

.row:focus-visible {
  outline: 1px solid #000;
  outline-offset: -2px;
}

.row-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.files-note {
  color: #7d7d78;
  font-size: 11px;
  margin: 0;
  padding: 8px 10px;
}

.reader {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  min-height: 0;
  min-width: 0;
}

/* The filename stays pinned above the independently scrolling code pane. */
.filebar {
  align-items: center;
  border-bottom: 1px solid #b0b0ab;
  display: flex;
  font-family: "Courier New", Courier, monospace;
  font-size: 10.5px;
  gap: 0.8em;
  min-height: 27px;
  padding: 0 10px;
}

.file-name {
  font-weight: bold;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The files toggle only exists where the rail is not simply there: the
   overlay layouts (a narrow screen, or the embedded cabinet). */
.files-toggle {
  background: transparent;
  border: 0;
  border-radius: 0;
  color: inherit;
  cursor: pointer;
  display: none;
  flex: none;
  font: inherit;
  padding: 0;
  text-decoration: underline;
}

.files-toggle:focus-visible {
  outline: 1px solid #000;
  outline-offset: 1px;
}

/* The viewport is the single scroll container for gutter and code, so they
   can never drift apart vertically; long lines scroll here and nowhere
   else. position: relative anchors offsetTop for the scripted scroll to the
   current match. */
.viewport {
  font-family: "Courier New", Courier, monospace;
  font-size: 11.5px;
  line-height: 1.45;
  min-height: 0;
  min-width: 0;
  overflow: auto;
  position: relative;
  scrollbar-width: thin;
}

.viewport:focus-visible {
  outline: 1px solid #000;
  outline-offset: -1px;
}

/* The plane is the one thing the viewport scrolls: as wide as the longest
   line and never narrower than the viewport. It exists so the sticky
   gutter's containing block spans the full scroll width — as a grid column
   the gutter would be confined to its own track and could never stick. */
.plane {
  display: flex;
  min-height: 100%;
  min-width: 100%;
  width: max-content;
}

.line-numbers,
.code {
  font: inherit;
  line-height: inherit;
  margin: 0;
  min-height: 100%;
  padding-bottom: 18px;
  padding-top: 7px;
  tab-size: 4;
}

/* Sticky at the plane's left edge on an opaque white ground, so the numbers
   hold still while long lines scroll underneath them and the hairline stays
   the gutter's only edge. */
.line-numbers {
  background: #fff;
  border-right: 1px solid #b0b0ab;
  color: #b0b0ab;
  flex: none;
  left: 0;
  min-width: 5ch;
  padding-left: 8px;
  padding-right: 9px;
  position: sticky;
  text-align: right;
  user-select: none;
  z-index: 1;
}

.code {
  flex: 1 0 auto;
  padding-left: 10px;
  padding-right: 24px;
}

/* The UA sheet gives the inner code element its own generic monospace at a
   different pitch, and the gutter then drifts a full row every dozen lines.
   Inheriting the pre's Courier keeps both columns on the same grid. */
.code code {
  font: inherit;
  line-height: inherit;
}

.tok-keyword { color: #184f82; }
.tok-preprocessor { color: #704285; }
.tok-comment { color: #53704f; }
.tok-string { color: #8a411d; }

.binary-hex {
  color: #7d7d78;
}

/* The overlay model: the reader has the full width and the file list covers
   it only while summoned (absolute inside .main, not fixed, so iOS toolbars
   can never sit on its controls). It applies on any narrow screen, and
   always inside the embedded cabinet, whose height could never afford a
   permanent rail. */
@media (max-width: 640px) {
  .topbar {
    min-height: 44px;
  }

  .main {
    grid-template-columns: minmax(0, 1fr);
  }

  .files {
    border-right: 0;
    display: none;
    inset: 0;
    position: absolute;
    z-index: 2;
  }

  .app.list-open .files {
    display: block;
  }

  .row {
    align-items: center;
    font-size: 12.5px;
    min-height: 44px;
    padding: 8px 12px;
  }

  /* The toggle is the only way into the file list here, so it takes the
     same finger-sized treatment as every other control: the full height of
     its bar, with a little extra width to land on. */
  .files-toggle {
    align-items: center;
    align-self: stretch;
    display: inline-flex;
    min-height: 44px;
    padding-right: 4px;
  }

  .filebar {
    font-size: 11px;
    min-height: 44px;
  }

}

/* The compact article cabinet gives the file rail roughly one third less
   width than the earlier study. The browser-filling route stays at 280px. */
.embedded .main {
  grid-template-columns: 128px minmax(0, 1fr);
}

.embedded .row {
  font-size: 10.5px;
  padding: 2px 8px;
}

.embedded .filebar {
  min-height: 26px;
  padding-left: 9px;
  padding-right: 9px;
}

@media (max-width: 640px) {
  .embedded .main {
    grid-template-columns: minmax(0, 1fr);
  }

  .embedded .row {
    font-size: 12.5px;
    min-height: 40px;
    padding: 8px 10px;
  }

  .embedded .filebar {
    min-height: 40px;
  }

}

/* A coarse pointer means a touch screen whatever the width. */
@media (pointer: coarse) {
  /* Only sizes the toggle where another rule has already made it visible —
     the base display: none still hides it wherever the rail is simply
     there, so a touch screen at desktop width does not grow a second way
     in. */
  .files-toggle {
    min-height: 44px;
    padding-right: 4px;
  }

  .row {
    align-items: center;
    font-size: 12.5px;
    min-height: 44px;
    padding: 8px 12px;
  }

}
