/* The panel. Same palette and discipline as the tenant theme, quieter scale.
   No animation anywhere, on purpose: a tool should not perform. */

:root {
  --ink: #000;
  --paper: #fff;
  --muted: color-mix(in srgb, var(--ink) 50%, var(--paper));
  --rule: color-mix(in srgb, var(--ink) 20%, var(--paper));
  /* Full width. `main` and the bar both read this, so the bar's rule stays
     flush with the content edge instead of drifting away from it. The
     24px on `body` is what keeps text off the window edge. */
  --measure: none;
}

@media (prefers-color-scheme: dark) {
  :root { --ink: #fff; --paper: #000; }
}

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

body {
  margin: 0;
  padding: 0 24px 96px;
  background: var(--paper);
  color: var(--ink);
  font-family: Archivo, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.4;
  -webkit-text-size-adjust: 100%;
}

/* Four type styles. The tenant theme has five; a tool needs fewer. */
h1 { font-size: 32px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; margin: 0 0 8px; }
h2 { font-size: 20px; font-weight: 800; line-height: 1.25; margin: 48px 0 8px; }
label, button, .panel-bar { font-size: 16px; font-weight: 700; }
.helptext, li span, .save-status, .errorlist { font-size: 12px; line-height: 1.3; }

p, ul, ol, li, h1, h2, label { overflow-wrap: anywhere; }

main { max-width: var(--measure); }
p { margin: 0 0 16px; }

a { color: inherit; text-decoration: underline; }
/* The ring has to contrast with what is behind it, which is the page, not
   with the element's own text. `currentColor` on a filled button is the
   button's white label, and `outline-offset` then draws that white ring on
   the white page: invisible, exactly where a keyboard user needs it most.
   `--ink` is guaranteed to contrast with `--paper` -- on a tenant site the
   contrast nudge enforces it -- so the ring reads on filled and unfilled
   controls alike. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* The bar. One line, two things, and it must survive a longer German word. */
.panel-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: baseline;
  justify-content: space-between;
  max-width: var(--measure);
  padding: 24px 0 16px;
  margin-bottom: 48px;
  border-bottom: 1px solid var(--rule);
}
.panel-bar a, .panel-bar span { text-decoration: none; }
/* the sign-out control is a POST form; it should read as a link */
.panel-bar form { margin: 0; }
/* Specificity raised on purpose: button[type="submit"] below is also
   (0,1,1), and equal specificity resolves by source order, which a later
   reordering could silently flip. (0,1,2) wins outright, regardless. */
.panel-bar form button {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* The legal footer, shaped like the one on a published page: a rule, air
   above it, and links spaced far enough apart to be separate targets. The
   panel had none of that, so three statutory links ran together as one line
   of small print. */
.legal-footer {
  margin-top: 96px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
}
.legal-footer a { margin-right: 24px; }

/* Sections, labelled down the left margin like row headers on a table.
   The label is a real <h2>, so the document still has a heading outline and
   a screen reader reads "Site", "Pages", "Actions" in order — the rotation
   is presentation only. */
.section {
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  gap: 20px;
  padding-top: 16px;
  margin: 0 0 32px;
  border-top: 1px solid var(--rule);
}
.section > h2 {
  /* vertical-rl alone reads top-to-bottom; the 180 turn makes it read
     bottom-to-top, which is the usual direction for a label in a left
     margin. Flip by dropping the rotate if you want the other one. */
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
  /* Without this the cell stretches to the row height and the rotated
     word lands at the bottom of a long section. Shrink to the text and
     pin it to the top, where a row header belongs. */
  align-self: start;
}
/* Placement is explicit, not left to the grid's auto-flow. A section with
   more than two children used to wrap: the third landed back in the label
   column and a button rendered one letter per line. Templates should not
   have to know that, so the columns are assigned by role instead. */
.section > h2 { grid-column: 1; }
.section > :not(h2) { grid-column: 2; }
.section > :last-child { margin-bottom: 0; }

/* The controls in a section sit in a row. They are alternatives, and
   stacking them made the page look longer than it is. `gap` does the
   spacing, so the .button + .button margin is cancelled here to stop the
   two mechanisms adding up. */
.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.actions form, .actions p { margin: 0; }
.actions .button + .button { margin-left: 0; }

/* A plan used to be a row: what it is on the left, the button that buys it
   on the right. It is an order form now. § 312j Abs. 2 BGB puts the
   essential particulars and the § 356 declaration between the price and the
   button, and § 312j Abs. 3 wants them "in hervorgehobener Weise" — so the
   parts stack in the order the statute reads them in, and the block is
   drawn as a box rather than left as running text. */
.plan-row { display: block; padding: 16px; border-bottom: 1px solid var(--rule); }
.plan-row > span { color: inherit; margin-left: 0; font-weight: 800; }
.plan-row form { margin: 12px 0 0; }
/* The particulars, set off from the price above them so that "highlighted"
   is something a reader can see rather than something a template claims. */
.order-summary { border-left: 3px solid var(--rule); padding-left: 12px; }
.order-summary p { margin: 0 0 8px; }
.order-summary p:last-child { margin-bottom: 0; }
/* The declaration and its box, side by side, with the box aligned to the
   first line of a sentence that runs to three or four. The consequence of
   each answer sits under both, quieter than the choice itself but not
   hidden: it is the sentence that decides what a withdrawal costs. */
.waiver { margin: 0 0 16px; }
.waiver-choice { display: flex; gap: 8px; align-items: flex-start; margin: 0; }
.waiver-consequence { margin: 8px 0 0 24px; color: var(--muted); }
.order-terms { color: var(--muted); margin: 0 0 16px; }

/* A row in the page list. The title leads; Delete is pushed to the far
   right and kept quiet. A destructive action should be easy to find and
   hard to hit by accident, which is the opposite of a filled button sitting
   against the title. */
.page-row { display: flex; align-items: baseline; gap: 8px; }
.page-row span { margin-left: 0; }
/* Row controls lead the row. They sat at the far right on an auto margin,
   which on a full-width panel put them an inch from the page they act on and
   off the edge of a narrow window entirely. Quiet until you reach for them. */
/* After the title, not before it: the row reads as a thing and then what
   can be done to it. They sat at the far right on an auto margin once,
   which put them an inch from the page they act on. */
.page-row .row-actions {
  display: flex;
  gap: 12px;
  margin-left: 12px;
}
.page-row .row-actions a, .page-row .delete {
  font-size: 12px;
  color: var(--muted);
  text-decoration: none;
}
.page-row .row-actions a:hover, .page-row .row-actions a:focus-visible,
.page-row .delete:hover, .page-row .delete:focus-visible {
  color: var(--ink);
  text-decoration: underline;
}

/* An image row leads with the image. `align-items: baseline` above would
   hang a thumbnail off its own bottom edge, so image rows centre instead.
   The box is fixed so a portrait and a landscape upload line up; the image
   is contained rather than cropped, because a cropped thumbnail can hide
   exactly the detail somebody is using to tell two photographs apart. */
.page-row:has(.image-thumb) { align-items: center; }
.image-thumb {
  width: 64px;
  height: 64px;
  object-fit: contain;
  background: var(--rule);
  border-radius: 3px;
  flex: 0 0 auto;
}

/* The delete confirmation shows the image large enough to recognise without
   pushing the button it is warning about off the screen. */
.image-preview {
  display: block;
  max-width: 100%;
  max-height: 320px;
  width: auto;
  height: auto;
  margin: 0 0 16px;
  border-radius: 3px;
}

/* Lists of pages */
/* Scoped to a list of things, not to every `li` on the page. Unscoped, the
   rule for the dashboard's page list also ruled off each line of Django's
   password help text, so the signup form arrived as four bordered rows of
   small print between the label and its field. */
main > ul, .page-list { list-style: none; padding: 0; margin: 0 0 24px; }
main > ul > li, .page-list > li {
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
main > ul > li span, .page-list > li span { color: var(--muted); margin-left: 8px; }

/* Help text inside a form is prose, whatever element Django wraps it in. */
.helptext ul, .helptext li {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 0;
}

/* Forms, as Django's as_div renders them: label, then help text, then the
   widget, each field a bare div direct under the form. */
form > div { margin: 0 0 20px; }
label { display: block; margin-bottom: 4px; }
input[type="text"], input[type="email"], input[type="password"], input[type="url"] {
  display: block;
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
}
.helptext { display: block; margin: 4px 0 8px; color: var(--muted); }

/* Errors carry weight and a rule rather than a colour, so they read the same
   to someone who cannot distinguish one. */
.errorlist {
  margin: 0 0 8px;
  padding: 0 0 0 12px;
  border-left: 2px solid var(--ink);
  font-weight: 700;
}
.errorlist li { border: 0; padding: 0; }

button[type="submit"], #save, .save, .button {
  padding: 10px 20px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
button[type="submit"]:hover, #save:hover, .save:hover, .button:hover {
  background: var(--paper);
  color: var(--ink);
}

/* A link that acts as a button. `a` sets colour and an underline at (0,0,1);
   `.button` is (0,1,0) and wins outright, so this needs no !important and no
   ordering luck. Only the box behaviour has to be added back. */
a.button {
  display: inline-block;
  text-decoration: none;
}
.button + .button { margin-left: 8px; }

/* The editing surface. editor.js brings its own internals; this is the frame. */
/* The frame moved to .editor-sheet, which now holds the title as well.
   Equal above and below: the sheet sits between two identical control rows,
   and an uneven gap makes the lower one look detached from it. */
.save-status { color: var(--muted); }

/* The image tool's own image, at whatever width the customer's photo
   happened to be -- unconstrained it can run wider than the editing
   surface, which no other block does. */
#editor img { max-width: 100%; height: auto; }

/* The editing surface wearing the site's look, so that what a customer
   types looks like what a visitor will read. Only the surface: the panel
   around it is our interface, and its contrast was chosen against a white
   page. The editor's own furniture -- the plus button, the block menu, the
   popovers -- is tooling, and tooling that recoloured itself per site would
   stop being recognisable from one page to the next. */
.editor-sheet {
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--rule);
  margin: 16px 0;
  padding: 24px 16px;
}
.editor-title {
  font-family: var(--font, inherit);
  font-size: calc(32px * var(--heading-scale, 1));
  margin: 0 0 16px;
}
.editor-surface {
  background: transparent;
  color: inherit;
  font-family: var(--font, inherit);
  border: 0;
  margin: 0;
  padding: 0;
  min-height: 20rem;
}
.editor-surface .ce-block__content,
.editor-surface h1, .editor-surface h2, .editor-surface h3 {
  font-family: var(--font, inherit);
}
.editor-surface .ce-toolbar__plus,
.editor-surface .ce-toolbar__settings-btn,
.editor-surface .ce-popover {
  color: var(--ink);
  background: var(--paper);
}

/* Decorative, so it is a pseudo-element rather than text a screen reader
   would read out as punctuation before the word. */
.button.back::before { content: "\2039"; margin-right: 6px; }

@media (max-width: 40rem) {
  h1 { font-size: 26px; }
  body { padding: 0 16px 64px; }
  /* A rotated label costs width a phone does not have. Set it upright and
     stack it above its section instead. */
  .section { grid-template-columns: 1fr; gap: 8px; }
  .section > h2 { writing-mode: horizontal-tb; transform: none; }
}

/* The Change style preview.

   Two swatches side by side say nothing about whether words on that
   background can be read, so the preview is a block of real text in the
   chosen colours and the chosen face. The customer's choice arrives as a
   `style` attribute redefining these three properties on this element only,
   which is why the defaults are set here rather than inherited: the panel
   has a dark scheme and the tenant theme does not, and a preview that went
   dark with the panel would be a preview of the wrong thing. */
.style-preview {
  --ink: #000;
  --paper: #fff;
  --font: Archivo, system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  border: 1px solid var(--rule);
  padding: 24px;
  margin: 0 0 24px;
  max-width: 34rem;
}
.style-preview-title { font-size: 32px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }

/* What we did to a pair of colours that could not be read. Not an error:
   the save went through. */
.adjusted { font-weight: 700; }

/* "Your password has been changed." A confirmation, not a warning, and the
   only feedback a customer gets that a settings form did anything: the save
   redirects, so without this the page comes back looking untouched. Bold
   rather than coloured, for the reason the focus ring keys off --ink: the
   panel's two schemes have one ink and one paper, and a green nobody chose
   would have to be legible against both. */
.saved { font-weight: 700; }

/* A colour input renders as a swatch, and at the browser's default size it
   is a postage stamp next to a 16px label. */
input[type="color"] { width: 8rem; height: 2.5rem; padding: 2px; }

/* The subdomain field and the apex it will hang off, on one line, so what
   the customer reads while typing is a whole address rather than a word
   with an explanation underneath. The suffix is not an input: it is not
   theirs to change, and a disabled input that looks editable is a worse
   lie than plain text. */
.address-field {
  display: flex;
  align-items: baseline;
  /* One line, always. The apex is the second half of a single address, and
     an address broken across two lines stops reading as one thing. The
     input gives way instead: it can shrink, the apex cannot. */
  flex-wrap: nowrap;
  gap: 0;
  max-width: 100%;
}
.address-field input {
  flex: 1 1 12rem;
  min-width: 0;
}
.address-apex {
  flex: 0 0 auto;
  padding-left: 0.15em;
  font-weight: 700;
  white-space: nowrap;
}
