/* Stems and Branches — one stylesheet, screen and print. */

@font-face {
  font-family: StemsBranches;
  src: url("data/sqtt-regular.ttf") format("truetype");
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: StemsBranches;
  src: url("data/sqtt-bold.ttf") format("truetype");
  font-weight: 700; font-display: swap;
}

:root {
  --ink: #23201d;
  --muted: #6d6862;
  --line: #ddd6cc;
  --bg: #fbf9f6;
  --panel: #fff;
  --accent: #8a3324;
  --radius: 8px;
  --field: #fdfcfa;
  /* A label is .8rem at 1.55 plus its .3rem margin. Anything that has to line up with
     a control but has no label of its own -- the Calculate button -- offsets by this,
     rather than bottom-aligning, so a note appearing under one field cannot drag it. */
  --label-h: 1.54rem;
  /* Every control in the form is this tall. Left to itself a date input is a couple of
     pixels taller than a select, which is invisible until they sit side by side. */
  --control-h: 2.7rem;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 2rem 1.25rem 4rem;
  font: 16px/1.55 StemsBranches, "Helvetica Neue", Helvetica, Arial, sans-serif;
  color: var(--ink);
  background: var(--bg);
}
.wrap { max-width: 62rem; margin: 0 auto; }

h1 { font-size: 1.6rem; margin: 0 0 .2rem; font-weight: 700; letter-spacing: -0.01em; }
.tagline { color: var(--muted); margin: 0 0 1.75rem; font-size: .95rem;
           max-width: 66ch; }

/* The form is a grid rather than a wrapping flex row. Flex gave every field the same
   appetite for leftover space, which stretched the birthplace input across half the
   page while the date sat cramped beside it. Columns are sized for what each control
   actually holds, and the row aligns from the top so a note appearing under one field
   never shifts its neighbours. */
form {
  display: grid;
  grid-template-columns:
    minmax(8.5rem, 10.5rem)      /* date     */
    minmax(7rem, 9rem)           /* time -- wide enough for a 12-hour locale's AM/PM */
    minmax(10rem, 13rem)         /* calendar */
    minmax(11rem, 1fr)           /* place    */
    auto;                        /* the button */
  gap: 1.1rem 1.15rem;
  align-items: start;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.15rem 1.25rem 1.25rem; margin-bottom: 1.5rem;
}
form > div { min-width: 0; }
/* Placed explicitly rather than by source order: the toggle comes before the button in
   the markup, because tabbing to Submit before reaching the switch that changes what
   Submit does would be perverse. The grid puts the button back up on the field row. */
form > button[type="submit"] {
  grid-column: 5; grid-row: 1; margin-top: var(--label-h);
}
.solar-field { grid-column: 1 / 5; grid-row: 2; }

/* Below this the five columns are too narrow to hold their controls -- the calendar
   select starts truncating its own option text -- so the form folds to two. Date and
   time keep each other company on the first row; everything else takes the full width. */
@media (max-width: 58rem) {
  form { grid-template-columns: minmax(8.5rem, 1fr) minmax(7rem, 1fr); }
  .calendar-field, .place-field { grid-column: 1 / -1; }
  .solar-field, form > button[type="submit"] { grid-column: 1 / -1; grid-row: auto; }
  form > button[type="submit"] { margin-top: .25rem; }
}

label { display: block; font-size: .8rem; color: var(--muted); margin-bottom: .3rem;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
input, select, button {
  font: inherit; padding: .5rem .65rem;
  border: 1px solid var(--line); border-radius: 6px; background: var(--field);
  color: inherit;
}
input, select { width: 100%; }
form input, form select, form button { height: var(--control-h); }
form label.check input { height: 1rem; }
input:hover, select:hover { border-color: #c9c0b3; }
input:focus-visible, select:focus-visible, button:focus-visible, .cycle:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 2px;
}
select { appearance: none; background-image:
  linear-gradient(45deg, transparent 50%, var(--muted) 50%),
  linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: right 1rem center, right .7rem center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  padding-right: 2rem; }
button {
  cursor: pointer; background: var(--ink); color: #fff; border-color: var(--ink);
  padding-left: 1.1rem; padding-right: 1.1rem; font-weight: 700; white-space: nowrap;
}
button.ghost { background: var(--panel); color: var(--ink); border-color: var(--line);
               font-weight: 400; }
button.ghost:hover { border-color: var(--ink); }
button:hover { opacity: .88; }

/* The birthplace typeahead. A plain list under a plain input -- no combobox library,
   and it degrades to a text field if the gazetteer fails to load. */
.place-field { position: relative; }
.place-results {
  position: absolute; z-index: 10; left: 0; right: 0; top: 100%;
  margin: .25rem 0 0; padding: .25rem; list-style: none;
  background: #fff; border: 1px solid var(--line); border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0,0,0,.12); max-height: 15rem; overflow-y: auto;
}
.place-results li {
  padding: .4rem .55rem; border-radius: 4px; cursor: pointer; font-size: .9rem;
}
.place-results li .where { color: var(--muted); font-size: .8rem; }
.place-results li[aria-selected="true"], .place-results li:hover { background: #f4efe8; }
.place-results .empty { color: var(--muted); cursor: default; }
#place-chosen:empty, #solar-note:empty { display: none; }
#place-chosen { margin: .4rem 0 0; line-height: 1.35; }

/* The true-solar-time switch, and what it did once it is on. It spans the whole row
   because it belongs to the form as a whole, not to the column it happens to sit in. */
label.check {
  display: inline-flex; align-items: center; gap: .5rem; white-space: normal;
  font-size: .9rem; color: var(--ink); margin-bottom: 0; cursor: pointer;
}
label.check input {
  width: 1rem; height: 1rem; flex: none; padding: 0; accent-color: var(--ink);
}
label.check:has(input:disabled) { color: var(--muted); cursor: default; }
#solar-note { margin: .35rem 0 0; }
.correction {
  background: #f4efe8; border: 1px solid var(--line); border-left: 3px solid var(--ink);
  padding: .7rem .95rem; border-radius: 0 var(--radius) var(--radius) 0;
  margin: 0 0 1.25rem; font-size: .875rem; max-width: 46rem;
  font-variant-numeric: tabular-nums;
}
.correction strong { font-weight: 700; }
.correction .parts {
  display: block; color: var(--muted); font-size: .8rem; margin-top: .25rem;
}
button:disabled { opacity: .45; cursor: default; }

.error {
  background: #fdf0ee; border: 1px solid #e9c4bd; color: #7d2718;
  padding: .7rem .9rem; border-radius: var(--radius); margin-bottom: 1.25rem;
}
.error:empty { display: none; }

table {
  border-collapse: collapse; width: 100%; background: var(--panel);
  font-variant-numeric: tabular-nums;
}
caption { text-align: left; font-size: .8rem; color: var(--muted); padding: 0 0 .4rem; }
th, td { border: 1px solid var(--line); padding: .5rem .7rem; text-align: left; }
th { background: #f4efe8; font-weight: 700; font-size: .85rem; }
td .sub { display: block; color: var(--muted); font-size: .8rem; }
tr.stems td, tr.stems th { border-bottom-style: dotted; }
/* Own tooltip rather than the native one: title needs about a second of stillness,
   is unreachable by keyboard, and does not exist at all on a touch screen. */
.cycle, .weight .rel {
  position: relative; cursor: help; outline-offset: 3px;
}
.cycle { border-bottom: 1px dotted var(--line); }
.weight .rel { border-bottom: 1px dotted var(--line); display: inline-block; }
.cycle::after, .weight .rel::after {
  content: attr(data-tip);
  position: absolute; left: 50%; bottom: 150%; transform: translateX(-50%);
  width: max-content; max-width: 15rem;
  background: var(--ink); color: #fff; border-radius: 6px;
  padding: .45rem .6rem; font-size: .75rem; line-height: 1.4; font-weight: 400;
  text-align: left; opacity: 0; visibility: hidden; transition: opacity .1s ease;
  pointer-events: none; z-index: 5;
}
.cycle::before, .weight .rel::before {
  content: ""; position: absolute; left: 50%; bottom: 150%;
  transform: translate(-50%, 85%);
  border: 5px solid transparent; border-top-color: var(--ink);
  opacity: 0; visibility: hidden; transition: opacity .1s ease;
  pointer-events: none; z-index: 5;
}
.cycle:hover::after, .cycle:focus::after, .cycle:focus-visible::after,
.cycle:hover::before, .cycle:focus::before, .cycle:focus-visible::before,
.weight .rel:hover::after, .weight .rel:focus::after, .weight .rel:focus-visible::after,
.weight .rel:hover::before, .weight .rel:focus::before,
.weight .rel:focus-visible::before {
  opacity: 1; visibility: visible;
}
/* the narrow label column, so the sheet explains itself */
.rowlabel, th[scope="row"] {
  width: 6.5rem; background: #f4efe8; color: var(--muted);
  font-size: .78rem; font-weight: 600; text-align: left; letter-spacing: .02em;
  white-space: nowrap;
}
tr.context .rowlabel { background: #faf7f2; border-bottom: none; }
tr.stems strong, tr.branches strong { font-size: 1.05rem; }
/* the stems hidden in each branch, a lookup rather than a calculation */
tr.hidden-stems td {
  border-top: none; background: #faf7f2; color: var(--muted);
  font-size: .82rem; padding-top: .2rem;
}
/* the birth moment, split across the pillar it produced */
tr.context td {
  border-bottom: none; background: #faf7f2; color: var(--muted);
  font-size: .82rem; padding-bottom: .15rem;
}

.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.1rem 1.25rem; margin-bottom: 1.5rem;
}
.panel h2 { font-size: .95rem; margin: 0 0 .8rem; letter-spacing: .02em;
  display: flex; align-items: center; gap: .6rem; }
.panel h2 .note { font-weight: 400; }
button.mini {
  margin-left: auto; font-size: .72rem; padding: .2rem .55rem; font-weight: 400;
  background: var(--panel); color: var(--muted); border-color: var(--line);
}
button.mini:hover { color: var(--ink); }

.weights { display: flex; gap: .6rem; flex-wrap: wrap; }
.weight {
  flex: 1 1 7rem; border: 1px solid var(--line); border-radius: 6px;
  padding: .6rem .7rem; background: #fff;
}
.weight .n { font-size: 1.35rem; font-weight: 700; }
/* Each element's relation to the Day Master, named on its own tile so it is readable
   without opening the circle. The Day Master's tile says so, because every other label
   on the card is relative to it. */
.weight .rel { font-size: .75rem; font-weight: 700; margin-top: .15rem; }
.weight.dm { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }

/* The five-element circle. Closed by default: the card reads as it always did until
   somebody asks for more. */
.circle-fold { border-top: 1px solid var(--line); margin-top: 1rem; padding-top: .75rem; }
.circle-fold summary {
  cursor: pointer; font-size: .85rem; color: var(--muted);
  list-style: none; display: flex; align-items: center; gap: .45rem;
}
.circle-fold summary::-webkit-details-marker { display: none; }
.circle-fold summary::before {
  content: "\25B8"; display: inline-block; transition: transform .12s ease;
}
.circle-fold[open] summary::before { transform: rotate(90deg); }
.circle-fold summary:hover { color: var(--ink); }
.circle-fold summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.circle-fold figure { margin: .75rem 0 0; }
.circle-fold .note { margin: .5rem 0 .75rem; max-width: 46rem; }
.weight .k { font-size: .78rem; color: var(--muted); text-transform: capitalize; }
.weight .bar { height: 4px; border-radius: 2px; margin-top: .45rem; background: #eee; }
.weight .bar i {
  display: block; height: 100%; border-radius: 2px;
  /* Metal is white in the school's palette, so a bare fill would be invisible.
     The inset outline makes every element readable without changing its colour. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .28);
}
.weight.empty { border-color: #e9c4bd; background: #fdf7f6; }

/* The diagrams are drawn at 1060px and 900px, and left to themselves they fill the
   panel and dominate the page. Cap them at a size you can take in at a glance, and
   centre them. Export is unaffected — both routes read the viewBox, not the rendered
   width, so a PNG is still 3x the drawing however small it looks here. */
figure { margin: 0; }
figure svg { width: 100%; height: auto; display: block; margin: 0 auto; }
#diagram svg { max-width: 26rem; }        /* square */
#element-circle svg { max-width: 28rem; }
#legacy svg  { max-width: 34rem; }        /* landscape, 3:2 */

.note { color: var(--muted); font-size: .82rem; }
.actions { display: flex; gap: .7rem; margin: 0 0 1.5rem;
           flex-wrap: wrap; align-items: center; }

footer { color: var(--muted); font-size: .8rem; border-top: 1px solid var(--line);
         padding-top: 1rem; margin-top: 2.5rem; }

/* The deployed build, so a screenshot or a phone can say which version it is.
   build/stamp.py rewrites the date and letter; nothing else touches it. */
.build {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .72rem; letter-spacing: .04em; color: var(--muted);
  text-align: right; margin: 1.5rem 0 0; opacity: .75;
}

/* Print: a clean chart sheet, no chrome. This is the free second export route —
   Ctrl/Cmd+P gives the same thing the Download PDF button does. */
@page { size: A4; margin: 14mm; }
@media print {
  .cycle::after, .cycle::before,
  .weight .rel::after, .weight .rel::before { display: none !important; }
}

@media print {
  body { background: #fff; padding: 0; }
  form, .actions, button.mini, footer .screen-only, .note.screen-only { display: none !important; }
  .panel { border: none; padding: 0; margin-bottom: 1rem; break-inside: avoid; }
  figure { break-inside: avoid; }
  /* a printed sheet has the width to spare, so let them breathe */
  #diagram svg { max-width: 15cm; }
  #legacy svg  { max-width: 17cm; }
}

/* --- the method page ------------------------------------------------------------ */

.prose { max-width: 44rem; }
.prose h2 {
  font-size: 1.12rem; margin: 2.4rem 0 .7rem; padding-top: 1.4rem;
  border-top: 1px solid var(--line); font-weight: 700;
}
.prose h2:first-of-type { border-top: none; padding-top: 0; }
.prose h3 { font-size: .95rem; margin: 1.6rem 0 .5rem; font-weight: 700; }
.prose p { margin: 0 0 .85rem; }
.prose ul { margin: 0 0 .95rem; padding-left: 1.15rem; }
.prose li { margin-bottom: .45rem; }
.prose table { margin: 0 0 1.1rem; }
.prose td, .prose th { vertical-align: top; font-size: .9rem; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .88em;
  background: #f2ece4; padding: .05em .3em; border-radius: 3px;
}
.prose q { quotes: "\201C" "\201D"; font-style: italic; }
.prose em { font-style: italic; }

.crumb { font-size: .85rem; margin: 0 0 1.6rem; }
.crumb a, .prose a { color: var(--accent); text-decoration: none;
  border-bottom: 1px solid rgba(138, 51, 36, .3); }
.crumb a:hover, .prose a:hover { border-bottom-color: var(--accent); }

.toc {
  display: flex; flex-wrap: wrap; gap: .35rem .9rem;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .85rem 1.1rem; margin-bottom: 2rem; font-size: .85rem;
}

@media print {
  .toc, .crumb { display: none !important; }
  .prose h2 { break-after: avoid; }
  .prose h3 { break-after: avoid; }
  .prose table, .prose ul { break-inside: avoid; }
}
