/* ---------------------------------------------------------------------------
   The sheet: a payslip that someone typed an essay into.

   Vollkorn carries the prose. Monospace carries the chrome -- rules, boxes,
   labels, dates -- so the furniture reads as a printed form and the writing
   reads as writing. Two rules keep it from becoming a costume:

     1. One box per page, never nested.
     2. Rules stay hairline and muted; they are ruling, not drawing.
--------------------------------------------------------------------------- */

/* The palette, `color-scheme` and the page background live in critical.css,
   which is inlined into every <head> so the first paint is already correct.
   Everything below is layout and type, which can arrive a moment later without
   anything visibly changing colour. */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
  color: var(--text);
  font-family: var(--serif);
  /* Vollkorn is a variable face; 450 gives prose a touch more body at 19px. */
  font-variation-settings: "wght" 450;
  font-size: 19px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.sheet {
  max-width: 41rem;
  margin: 0 auto;
  padding: 3.5rem 1.5rem 6rem;
}

/* --- Prose --------------------------------------------------------------- */

h1,
h2,
h3,
strong,
b {
  color: var(--header);
}

h1 {
  font-size: 1.5rem;
  font-variation-settings: "wght" 700;
  margin: 0 0 1.25rem;
  letter-spacing: 0.01em;
}

p {
  margin: 0 0 1.25rem;
}

a {
  color: var(--link);
  font-variation-settings: "wght" 600;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0 0 2rem;
}

/* The nav rule and the page's boxes are the same weight and the same inset, so
   the top of every page reads as one ruled sheet. */
.sheet > hr {
  margin-bottom: 1.75rem;
}

/* --- Navigation: the form's top rail ------------------------------------- */

nav {
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  margin-bottom: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

nav a {
  color: var(--ink);
  font-weight: 400;
  text-decoration: none;
}

nav a:hover {
  text-decoration: underline;
}

/* The current section is stated, not offered. */
nav a[aria-current="page"] {
  color: var(--header);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- The ledger box ------------------------------------------------------ */

/* The box is a lattice, not a container with lines inside it. Every rule --
   frame, title, column divider -- is the same hairline, and cells share edges
   so the verticals run unbroken from the title rule to the foot. That shared,
   uninterrupted line is what the reference actually does. */
.box {
  border: 1px solid var(--line);
  margin: 0 0 2rem;
}

.box-title {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0;
  padding: 0.45rem 0.85rem;
  border-bottom: 1px solid var(--line);
}

/* No padding: the rows reach the frame, so their divider meets it. */
.box-body {
  padding: 0;
}

/* Label and value are separated by the column rule, not a colon. The rule is
   a left border on the value cell, so consecutive rows stack it into one
   continuous vertical. */
.row {
  display: grid;
  grid-template-columns: 11rem 1fr;
  font-family: var(--mono);
  font-size: 0.82rem;
  line-height: 1.75;
  color: var(--ink);
}

.row-label {
  padding: 0.28rem 0.85rem;
}

.row-value {
  padding: 0.28rem 0.85rem;
  border-left: 1px solid var(--line);
  color: var(--text);
}

/* A total is ruled off above, the way a payslip closes a column. Both cells
   take the border so the rule crosses the full width, through the divider. */
.row-total > * {
  border-top: 1px solid var(--line);
}

.row-total .row-value {
  color: var(--header);
}

/* --- Dated entries ------------------------------------------------------- */

/* Entries share one spine: the rule between the date column and the text runs
   the height of the whole list rather than restarting per entry. */
.entries {
  margin-bottom: 2rem;
}

.entry {
  display: grid;
  grid-template-columns: 7rem 1fr;
}

.entry-date {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
  /* Aligns the date to the title's baseline, not the cell's top edge. */
  padding: 0.62rem 0.9rem 0.9rem 0;
}

.entry-body {
  border-left: 1px solid var(--line);
  padding: 0.45rem 0 0.9rem 0.9rem;
}

.entry-title {
  font-variation-settings: "wght" 600;
}

.entry-note p {
  margin: 0.15rem 0 0;
  font-size: 0.95rem;
}

/* --- Rendered markdown ---------------------------------------------------- */

/* The date under a post title, in the mono voice of the chrome. */
.post-date {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink);
  margin: -0.8rem 0 1.75rem;
}

.prose > :first-child {
  margin-top: 0;
}

.prose > :last-child {
  margin-bottom: 0;
}

/* Headings step down but stay in Vollkorn, so a post reads as one voice. */
.prose h2,
.prose h3,
.prose h4 {
  font-variation-settings: "wght" 700;
  line-height: 1.3;
  margin: 2rem 0 0.75rem;
}

.prose h2 {
  font-size: 1.2rem;
}

.prose h3 {
  font-size: 1.05rem;
}

.prose h4 {
  font-size: 0.95rem;
}

/* Hanging markers keep the text edge of a list flush with the paragraphs. */
.prose ul,
.prose ol {
  margin: 0 0 1.25rem;
  padding-left: 1.2rem;
}

.prose li {
  margin-bottom: 0.35rem;
}

/* A marked passage, not a decorated one. */
.prose blockquote {
  margin: 0 0 1.25rem;
  padding-left: 1rem;
  border-left: 2px solid var(--ink);
  color: var(--text);
  font-style: italic;
}

.prose blockquote p:last-child {
  margin-bottom: 0;
}

.prose code {
  font-family: var(--mono);
  /* Mono runs large beside a serif; pull it back to match the x-height. */
  font-size: 0.82em;
  color: var(--ink);
}

.prose pre {
  margin: 0 0 1.25rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  background: var(--panel);
  overflow-x: auto;
  line-height: 1.5;
}

.prose pre code {
  font-size: 0.78rem;
  color: var(--text);
}

.prose hr {
  margin: 2rem 0;
}

.prose img {
  max-width: 100%;
  height: auto;
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1.25rem;
  font-size: 0.9rem;
}

.prose th,
.prose td {
  border: 1px solid var(--line);
  padding: 0.35rem 0.6rem;
  text-align: left;
}

.prose th {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}

/* The way back out of a post. */
.back {
  font-family: var(--mono);
  font-size: 0.75rem;
  margin-top: 2.5rem;
}

.back a {
  font-weight: 400;
}

/* --- Corner toggle ------------------------------------------------------- */

#theme-toggle {
  position: fixed;
  bottom: 0.75rem;
  right: 0.75rem;
  background: none;
  border: none;
  padding: 0.35rem;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink);
  opacity: 0.55;
}

#theme-toggle:hover {
  opacity: 1;
}

/* --- Narrow screens ------------------------------------------------------ */

@media (max-width: 34rem) {
  body {
    font-size: 18px;
  }

  .sheet {
    padding: 2.5rem 1.1rem 5rem;
  }

  nav {
    gap: 1rem;
  }

  .row {
    grid-template-columns: 7.5rem 1fr;
  }

  /* Narrow screens cannot hold the date column, so the lattice becomes a
     single column: the date sits above the title and the spine goes, rather
     than surviving as a cramped gutter. */
  .entry {
    display: block;
    padding-bottom: 1.1rem;
  }

  .entry-date {
    display: block;
    text-align: left;
    padding: 0 0 0.1rem;
  }

  .entry-body {
    border-left: 0;
    padding: 0;
  }
}

/* --- The admin tool ------------------------------------------------------ */

/* The tool is not part of the site, so it does not get the site's nav. It
   gets a rail of its own, in the mono chrome, to make "you are behind the
   door" unmistakable at a glance. */
.sheet-narrow {
  max-width: 26rem;
}

/* The editor only. Source and preview side by side need more than the site's
   reading measure, which every page meant for reading keeps. */
.sheet-wide {
  max-width: 68rem;
}

.admin-bar {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  padding-bottom: 0.6rem;
  margin-bottom: 1.75rem;
  border-bottom: 1px solid var(--line-strong);
}

.admin-mark {
  color: var(--ink);
  letter-spacing: 0.08em;
}

.admin-bar nav {
  border: 0;
  padding: 0;
  margin: 0;
  flex: 1;
}

/* A button that has to be a button (logging out must be a POST) but should
   not look like one. */
.linklike {
  font: inherit;
  color: var(--link);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.linklike:hover {
  text-decoration: underline;
}

/* --- The post list ------------------------------------------------------- */

.admin-posts {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--text);
}

.admin-posts th {
  text-align: left;
  font-weight: normal;
  color: var(--ink);
  padding: 0.28rem 0.85rem 0.28rem 0;
  border-bottom: 1px solid var(--line);
}

.admin-posts td {
  padding: 0.28rem 0.85rem 0.28rem 0;
  border-bottom: 1px solid var(--line);
}

.admin-posts .cell-date {
  white-space: nowrap;
  color: var(--ink);
}

.admin-posts .cell-state {
  text-align: right;
  white-space: nowrap;
}

/* --- The login form ------------------------------------------------------ */

.login-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: flex-start;
  font-family: var(--mono);
  font-size: 0.82rem;
}

.login-form input {
  font: inherit;
  width: 100%;
  padding: 0.4rem 0.5rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line);
}

.login-form input:focus {
  outline: 1px solid var(--line-strong);
  outline-offset: 0;
}

.login-form button {
  font: inherit;
  margin-top: 0.4rem;
  padding: 0.4rem 1rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line-strong);
  cursor: pointer;
}

.login-form button:hover {
  color: var(--header);
  border-color: var(--header);
}

/* A refusal is stated plainly, in the link red, without an alarm panel. */
.form-error {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--link);
}

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

/* The header fields reuse the ledger lattice: an editor for this site should
   look like the form the site already is. Inputs sit inside the value cell
   with no border of their own, so the lattice keeps drawing the boxes. */
.editor-heading {
  margin-bottom: 1.25rem;
}

/* The inputs carry their own padding so the text sits where the lattice
   expects it; the cell itself must not add more. The static slug row keeps
   the normal cell padding, or it would hang outside the spine. */
.editor-fields .row-value:has(input) {
  padding: 0;
}

.editor-fields input {
  font: inherit;
  width: 100%;
  padding: 0.28rem 0.85rem;
  color: var(--text);
  background: transparent;
  border: 0;
}

.editor-fields input:focus {
  outline: 0;
  background: var(--panel);
}

.frozen {
  color: var(--ink);
  opacity: 0.75;
}

/* Source and result, side by side, sharing one rule down the middle -- the
   same lattice the ledger rows use, so the editor reads as part of the form
   rather than a panel bolted onto it. */
.editor-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: 1.5rem;
  border: 1px solid var(--line);
}

/* The body is monospace: it is markdown source, not prose yet. Fixed height
   rather than auto-growing, so the save bar stays where the hand expects it. */
.editor-body {
  display: block;
  width: 100%;
  min-height: 26rem;
  padding: 0.9rem 1rem;
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.7;
  color: var(--text);
  background: var(--panel);
  /* The split's frame is the border now; only the shared spine belongs here. */
  border: 0;
  border-right: 1px solid var(--line);
  resize: vertical;
  tab-size: 2;
}

.editor-body:focus {
  outline: 0;
  /* Never the frame: moving a shared edge would shift the pane beside it. */
  background: var(--bg);
}

/* The preview is the published page's own styling, at the published measure,
   so what is read here is what ships. */
.editor-preview {
  padding: 0.9rem 1.1rem;
  overflow-y: auto;
  max-height: 34rem;
}

.editor-preview .prose > :first-child {
  margin-top: 0;
}

.preview-empty {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--text);
  opacity: 0.5;
}

/* Below the measure where two columns each become too narrow to read, the
   preview goes under the source rather than beside it. */
@media (max-width: 60rem) {
  .editor-split {
    grid-template-columns: 1fr;
  }

  .editor-body {
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
}

/* The status rail, where a payslip puts its total. */
.editor-bar {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-top: 0.9rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.8rem;
}

.editor-state {
  color: var(--ink);
}

.editor-status {
  flex: 1;
  opacity: 0.75;
}

.editor-bar button {
  font: inherit;
  padding: 0.35rem 1.1rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line-strong);
  cursor: pointer;
}

.editor-bar button:hover {
  color: var(--header);
  border-color: var(--header);
}

/* --- Whole-post operations ----------------------------------------------- */

/* The list heading and its one action share a line, so "new post" sits where
   the eye already is rather than below the table. */
.page-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.page-head button {
  font-family: var(--mono);
  font-size: 0.8rem;
  padding: 0.35rem 1.1rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line-strong);
  cursor: pointer;
}

.page-head button:hover {
  color: var(--header);
  border-color: var(--header);
}

/* The slug row carries a prefix, a field and its own submit, and still has to
   sit inside the ledger lattice without breaking the vertical rule. */
.editor-fields .row-value.slug-row {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  flex-wrap: wrap;
  /* Right padding matters: without it the submit sits flush against the
     ledger's frame and reads as clipped. */
  padding: 0.28rem 0.85rem;
}

.slug-prefix {
  color: var(--ink);
  opacity: 0.7;
}

/* Not `flex: 1`: a slug is short, and a field stretched across the row
   invites the eye to expect a sentence. It grows with its content instead. */
.slug-form {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

/* The field is transparent so the row still reads as a ledger cell rather
   than a form control dropped into one. Sized in `ch` so it holds a typical
   slug and no more. */
.slug-form input {
  font: inherit;
  width: 24ch;
  max-width: 100%;
  padding: 0 0 0.15rem;
  color: var(--text);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
}

.slug-form input:focus {
  outline: none;
  border-bottom-color: var(--header);
}

.slug-note {
  font-size: 0.72rem;
  color: var(--ink);
  opacity: 0.75;
}

/* Publish and delete sit together at the right of the bar, away from save. */
.editor-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Publishing is the affirmative act on a draft, so it carries the one accent
   on the page. */
.editor-bar button.primary {
  color: var(--header);
  border-color: var(--header);
}

/* Destructive, and styled to be noticed rather than to be pretty. It is only
   ever shown for drafts. */
.editor-bar button.danger {
  color: var(--link);
  border-color: var(--line);
}

.editor-bar button.danger:hover {
  border-color: var(--link);
}

/* --- Draft preview ------------------------------------------------------- */

/* Shown only on the admin host, to a logged-in author, reading a post at the
   address it will have once published. It has to be unmistakable: the whole
   page below it looks exactly like the live article, which is the point, so
   the banner is the only thing saying otherwise. */
.draft-banner {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink);
  padding: 0.5rem 0.85rem;
  margin-bottom: 1.75rem;
  border: 1px solid var(--line);
  background: var(--panel);
}

/* A link sitting among the action buttons; aligned with them rather than
   floating on the baseline of its own. */
.editor-actions .action-link {
  font-family: var(--mono);
  font-size: 0.82rem;
  align-self: center;
  margin-right: auto;
}
