/*
 * Jyotisha - white and green.
 *
 * White surfaces on a faint green ground, with a single green accent doing the
 * work of highlight, focus and emphasis. Retrograde is the one deliberate
 * exception: it is marked in a warm red, because it must read as different
 * rather than merely emphasised, and a second green would not.
 *
 * A dark variant follows the system setting; the print sheet stays on white.
 */

:root {
  /* The line the seconds hint holds open under a time field, and the same
     line the Gochar buttons hold open so the two columns end level. */
  --seconds-hint-line: 1.95rem;
  /* A saved card's action icons, and the room the card holds open for them. */
  --saved-icon: 1.95rem;
  --saved-icon-gap: 0.15rem;
  --saved-actions-inset: 0.45rem;
  /* Without this, scrollbars, date pickers and select arrows keep their light
     styling on a dark page: browser chrome follows this property, not the
     colours below it. */
  color-scheme: light;

  --paper: #f4faf6;
  --paper-tint: #eaf5ee;
  --surface: #ffffff;
  --row-hover: #f1f9f4;
  --line: #d4e9dc;
  --line-soft: #e4f1e9;

  --ink: #21302a;
  --ink-soft: #55645c;
  --ink-faint: #87a095;

  /*
   * The arrow every dropdown carries. A select will not take a pseudo-element
   * - it is the browser's to draw - so the mark is a background image, and a
   * background image cannot read currentColor. It is therefore written out
   * once per palette rather than tinted at the point of use.
   */
  --dropdown-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0h10L5 6z' fill='%2387a095'/%3E%3C/svg%3E");

  --green: #2f8f5f;
  --green-deep: #1f6b47;
  --green-soft: #dcefe4;
  /* Light enough that the row rules still read through it. */
  --varga-key: #ebf6ef;
  --retro: #b8483a;
  /* A chart with a question against it: amber, because the reading still
     stands and it is the record that wants checking. */
  --queried: #b0761a;
  --flag-vargottama: #6d4aa8;
  --flag-yogakaraka: #a8710c;
  --flag-combust: #7a8a99;
  --flag-exchange: #1d5fa8;
  /* Chart series. Validated against the light surface for lightness, chroma,
     CVD separation and contrast; the dark steps below are chosen for the dark
     surface rather than lightened from these. */
  --chart-vimsopaka: #2f8f5f;
  --chart-good: #a8710c;
  --chart-vargottama: #6d4aa8;
  --chart-exchange: #1d5fa8;
  /* One hue per dasha level. The indent alone could not carry three. */
  --dasha-ad: #1d5fa8;
  --dasha-pd: #9a6a10;
  /* Distinct from the blue above it and the amber above that, and from the
     page's green, red and purple; a muted teal is the gap left in the set. */
  --dasha-sd: #1d7a76;

  --radius: 16px;
  --radius-sm: 10px;
  /* Selects carry their own minimum height and their own idea of line-height,
     so identical padding does not produce identical boxes. Setting the height
     explicitly is what actually lines them up with the text inputs. */
  --control-height: 2.7rem;
  --shadow: 0 1px 2px rgba(31, 84, 58, 0.05), 0 8px 24px rgba(31, 84, 58, 0.07);
  --shadow-lift: 0 2px 6px rgba(31, 84, 58, 0.08), 0 18px 40px rgba(31, 84, 58, 0.12);

  --font: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
  --font-display: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0 1.25rem 4rem;
  background:
    radial-gradient(1100px 520px at 12% -8%, #ddf2e5 0%, transparent 62%),
    radial-gradient(900px 460px at 92% 2%, #e6f5ec 0%, transparent 58%),
    var(--paper);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--font);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/*
 * One measure, and everything on the page sits in it: the header and its tabs,
 * the card that names the chart, the two kundli figures, and the speculums
 * under them.
 *
 * The tables had room of their own for a while, breaking out of a 1120px page
 * to 1480px. It worked for the tables and showed as a step in the middle of
 * the page, a wide speculum under a narrow chart, which reads as a mistake
 * rather than as emphasis. So the page takes the middle of those two instead
 * and nothing breaks out of it.
 *
 * 1300px is wide enough that the seven-column comparison and the shadbala
 * speculum stop scrolling sideways on a desktop, and still leaves a margin
 * either side rather than running to the glass. Prose is not let loose by it:
 * the notes and passages keep their own ch measures, which is where reading
 * width is actually set.
 */
main, .site-header, .site-footer { max-width: 1300px; margin: 0 auto; }

/* ------------------------------------------------------------------ tabs */

/*
 * Wraps rather than scrolls. It used to say overflow-x: auto, and setting one
 * axis to anything but visible promotes the other from visible to auto - so the
 * -1px margin that laps the tabs over the border was one pixel of vertical
 * overflow, and the browser drew a vertical scrollbar for it.
 */
/* display:flex outranks the hidden attribute, and a strip that stands down
   when there is nothing to choose between has to actually go. */
.tabs[hidden] { display: none; }
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
}

.tab {
  font: inherit;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink-soft);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  padding: 0.7rem 1.05rem;
  margin-bottom: -1px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.12s ease, background 0.12s ease, border-color 0.12s ease;
}
.tab:hover { color: var(--green-deep); background: var(--green-soft); }
.tab[aria-selected="true"] {
  color: var(--green-deep);
  border-bottom-color: var(--green);
}

.tab-count {
  display: inline-block;
  min-width: 1.35rem;
  margin-left: 0.3rem;
  padding: 0.05rem 0.35rem;
  font-size: 0.75rem;
  font-weight: 700;
  text-align: center;
  color: var(--green-deep);
  background: var(--green-soft);
  border-radius: 999px;
}

.empty-chart { color: var(--ink-faint); text-align: center; padding: 3rem 1.5rem; }

/* ------------------------------------------------------ open kundali box */
/*
 * A box on the page, not a panel containing a box. There is no card around it:
 * the chrome was a white slab the width of the screen framing one short input,
 * which drew more attention to the frame than to the thing being framed and
 * pushed the chart down to do it.
 *
 * No visible label either. The box says what it is for in its own placeholder,
 * which leaves one thing on the line rather than two and lets it sit centred
 * rather than being pushed off centre by a label beside it.
 */
.chart-open { margin: 0 0 1.25rem; text-align: center; }
.chart-open .combobox {
  width: min(34rem, 100%);
  margin: 0 auto;
  text-align: left;   /* the dropdown reads from the left, as a list does */
}
/*
 * Seen only by someone with nothing saved, in place of the box rather than
 * under it, so it takes the room the box would have had.
 */
.chart-open .empty-chart { padding: 2.5rem 1.5rem; }

/* ----------------------------------------------------------- saved panel */

.saved-empty, .saved-note {
  font-size: 0.82rem;
  color: var(--ink-faint);
  line-height: 1.5;
  margin: 0;
}
.saved-note { margin-top: 0.9rem; padding-top: 0.8rem; border-top: 1px solid var(--line-soft); }
.saved-note[hidden] { display: none; }

/* Under the button it describes, which is where it is about to be true. */
.form-note {
  margin: 0.75rem 0 0;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

/*
 * A card for each saved chart, several to a row. A row across the page gave
 * three short facts a full screen width to sit in, so a list of ten was ten
 * lines of mostly empty space with the edit and the delete at the far edge.
 * The cards find their own number per row: as many as fit at a readable width.
 */
/* Clear of the cards. The box filters them; it is not the first of them. */
.saved-search { margin-bottom: 1rem; }

.saved-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.6rem;
}

.saved-card {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.7rem 0.8rem;
  background: var(--surface);
  /*
   * Room at the right for the three icons, which sit over the card's top
   * corner rather than taking a column of their own. Reckoned from the icons
   * rather than guessed at: it was 5.4rem against the 6.6rem they occupy, so
   * they hung a fifth of an inch over the name and a long one ran under them.
   * One measure, spent here and on the icons themselves, so the two cannot
   * drift apart again when an icon is added or resized.
   */
  padding-right: calc(3 * var(--saved-icon) + 2 * var(--saved-icon-gap) +
    var(--saved-actions-inset) + 0.3rem);
  transition: border-color 0.12s ease, background 0.12s ease;
  cursor: pointer;
}
.saved-card:hover { border-color: var(--green); background: var(--green-soft); }

.saved-open {
  font: inherit;
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.95rem;
  display: block;
  max-width: 100%;
  border-bottom: 1px solid transparent;
}
.saved-open:hover,
.saved-open:focus-visible { border-bottom-color: currentColor; }
.saved-name { font: inherit; }

/* When first, then where: the order anyone asks them in. */
.saved-born,
.saved-place {
  margin: 0.25rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}
.saved-place { color: var(--ink-faint); }

/*
 * Over the card's top corner rather than in a column of its own, which is why
 * the card carries the extra right padding. When the delete asks for
 * confirmation the pair needs the width of a sentence, so it takes the whole
 * card at that moment rather than overflowing it.
 */
.saved-actions {
  position: absolute;
  top: var(--saved-actions-inset);
  right: var(--saved-actions-inset);
  display: flex;
  align-items: center;
  gap: var(--saved-icon-gap);
  cursor: default;
}
.saved-actions.confirming {
  position: static;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

.saved-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--saved-icon);
  height: var(--saved-icon);
  padding: 0;
  color: var(--ink-faint);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease;
}
.saved-icon svg {
  width: 1rem;
  height: 1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.saved-icon:hover { color: var(--green-deep); background: var(--surface); }
.saved-remove:hover { color: var(--retro); }

/* Raised, the banner fills. An outline flag sitting among two other outline
   icons is not a state anybody would notice, and the fill is what makes the
   two drawings - the card's and the chart's - read as one control. */
.saved-flag:hover { color: var(--queried); }
.saved-flag.is-flagged { color: var(--queried); }
.saved-flag.is-flagged svg path + path { fill: currentColor; }
.icon-button.is-flagged {
  color: var(--queried);
  border-color: var(--queried);
  background: var(--surface);
}
.icon-button.is-flagged:hover { color: var(--queried); border-color: var(--queried); }
.icon-button.is-flagged svg path + path { fill: currentColor; }

/* On the chart there is room for the words, and no second chart to tell it
   apart from, so it says what it means rather than drawing a flag twice. */
.flag-mark {
  font: inherit;
  cursor: pointer;
  background: none;
  margin-left: 0.45rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--queried);
  border: 1px solid var(--queried);
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
  vertical-align: middle;
}
button.flag-mark:hover, button.flag-mark:focus-visible {
  color: var(--surface);
  background: var(--queried);
}
span.flag-mark { cursor: default; }

/* The confirm step replaces the icons in place, so the row never jumps and the
   answer sits where the question was asked. */
.saved-actions.confirming { gap: 0.3rem; }
.saved-confirm-label { font-size: 0.78rem; color: var(--ink-soft); }
/*
 * The delete confirmation. A dialog rather than a rebuild of the card's own
 * buttons: swapping those out detached the icon mid-click, and the card then
 * opened the chart instead of asking.
 */
.confirm-dialog {
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--surface);
  color: var(--ink);
  padding: 1.1rem 1.2rem;
  max-width: 24rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
.confirm-dialog::backdrop { background: rgba(0, 0, 0, 0.35); }
.confirm-dialog h2 {
  margin: 0 0 0.3rem;
  font-family: var(--font-display);
  font-size: 1rem;
}
.confirm-dialog-name { margin: 0 0 0.4rem; font-weight: 600; }
.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.9rem;
}
.saved-confirm, .saved-cancel {
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
  border: 1px solid var(--line);
  cursor: pointer;
}
.saved-confirm { color: #fff; background: var(--retro); border-color: var(--retro); }
.saved-confirm:hover { filter: brightness(1.08); }
.saved-cancel { color: var(--ink-soft); background: var(--surface); }
.saved-cancel:hover { color: var(--green-deep); border-color: var(--green); }

/* ------------------------------------------------- add, and save status */


/* Takes no room until it has something to say; a reserved empty line was most
   of the spare height in this card. */
.save-feedback {
  margin: 0.7rem 0 0;
  font-size: 0.84rem;
  color: var(--green-deep);
}
.save-feedback:empty { display: none; }


/* ------------------------------------------------------------------ header */

/*
 * There is no site header any more. The name and the account controls both sit
 * on the top row - name at its left, sign-in at its right - and a banner above
 * it cost a third of the first screen before a word could be read.
 */

/*
 * Name left, tabs right, on one line. The rule under them belongs to the bar
 * rather than to the tablist, so the name sits on it too instead of floating
 * above a line that starts at the first tab.
 */
.tab-bar {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 0.6rem 0.35rem;
  margin: 1.1rem 0 1.25rem;
  border-bottom: 1px solid var(--line);
}
/*
 * The tabs take the space between the two, so the name stays hard left and the
 * account controls hard right whether or not anyone is signed in - the row
 * must not shift when the buttons appear.
 */
.tab-bar .tabs {
  margin-left: auto;
  margin-bottom: 0;
  border-bottom: 0;
}
/*
 * Narrow screens keep the same arrangement rather than stacking three bands:
 * the name and the sign-in hold the first line, left and right, and the tabs
 * take the whole of the next one. Stacked, they cost a third of a phone screen
 * before the form began.
 */
@media (max-width: 1100px) {
  .tab-bar .account-controls { order: 1; margin-left: auto; }
  .tab-bar .tabs { order: 2; flex-basis: 100%; margin-left: 0; }
}
.site-name {
  font-family: var(--font-display);
  /* Smaller than it was: the name sits on the tab row, and set as large as
     a page heading it outweighed the tabs beside it, which are what a
     reader is actually choosing between. */
  font-size: clamp(1.15rem, 1.7vw, 1.45rem);
  font-weight: 500;
  letter-spacing: 0.04em;
  margin: 0 0 0.3rem;
  color: var(--green-deep);
  white-space: nowrap;
}

/*
 * At the right-hand end of the top row, after the tabs, and set at the tabs'
 * own size so the row reads as one line of type rather than two.
 */
.account-controls {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0;
}
.account-controls .account-button {
  min-width: 6.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.account-controls .account-button:hover {
  border-color: var(--green);
  background: var(--green-soft);
}
.account-controls .account-button:disabled { cursor: wait; }
.account-controls[hidden], .account-controls [hidden] { display: none; }
#auth-status { flex-basis: 100%; color: var(--ink-soft); font-size: 0.85rem; }
#auth-status:empty { display: none; }

/* Reserve account navigation while identity and permissions resolve together.
 * Hidden placeholders cannot receive focus or expose account-only actions. */
.account-pending #tab-billing[hidden], .account-pending #tab-admin[hidden] {
  display: inline-block;
  visibility: hidden;
}
.account-pending .account-controls,
.account-pending .account-controls[hidden] {
  display: flex;
  visibility: hidden;
}
.account-pending #auth-status { display: none; }

/* Billing follows the verified account, including keyboard navigation. */
#tab-billing[hidden], .billing-panel[hidden], .billing-panel [hidden] { display: none; }
.billing-plan {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.billing-plan h4 { margin: 0; font-size: 1.1rem; }
.billing-price { margin: 0.7rem 0; font-size: 1.8rem; color: var(--green-deep); }
.billing-price span { font-size: 0.95rem; color: var(--ink-soft); }
.billing-purchase .field-note { margin-bottom: 0; }
.billing-purchase button.primary:disabled { cursor: not-allowed; filter: none; }
.billing-history-heading { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.billing-history-heading h3 { margin-bottom: 0; }
.billing-table-wrap { max-width: 100%; overflow: auto; }
.billing-table-wrap table { width: 100%; min-width: 600px; }
.billing-table-wrap td { overflow-wrap: anywhere; }
.billing-table-wrap time { white-space: nowrap; }
.billing-table-wrap small { display: block; color: var(--ink-soft); margin-top: 0.3rem; }
#billing-more { margin-top: 1rem; }

#tab-admin[hidden], .admin-panel[hidden], .admin-panel [hidden] { display: none; }
.admin-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(135px, 1fr)); gap: 1rem; }
.admin-summary > div { padding: 1rem; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.admin-summary dt { color: var(--ink-soft); font-size: 0.9rem; }
.admin-summary dd { margin: 0.4rem 0 0; font-size: 1.8rem; color: var(--green-deep); }
.admin-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 1rem; }
.admin-toolbar .field { flex: 1 1 220px; min-width: 0; }
.admin-toolbar > button { min-height: var(--control-height); }
.admin-table-wrap { max-width: 100%; overflow: auto; }
.admin-table-wrap table { width: 100%; min-width: 760px; }
.admin-table-wrap td { overflow-wrap: anywhere; }
.admin-table-wrap small { display: block; color: var(--ink-soft); margin-top: 0.3rem; }
.admin-table-wrap button { font-size: 0.85rem; white-space: nowrap; }
.admin-table-wrap td:first-child { text-align: left; max-width: 260px; }
#admin-more, #admin-purchases-more, #admin-purchases-retry { margin-top: 1rem; }
#admin-purchases-user { overflow-wrap: anywhere; }

/* -------------------------------------------------------------------- card */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.6rem;
  margin-bottom: 1.25rem;
}

.card h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.2rem;
  letter-spacing: 0.02em;
  margin: 0 0 1rem;
  color: var(--green-deep);
}

/* -------------------------------------------------------------------- form */

/*
 * The track is 260px because the widest legend in the form is 240px: "Time of
 * birth" and the hint naming the clock, which is kept whole. At 210px that
 * legend wrapped, and a label a line taller pushed the hour, minute and second
 * boxes a line below the name, gender and date beside them - the row read as
 * two rows. The minimum is the measurement plus room for a wider rendering of
 * it, not a round number.
 *
 * It also settles the count: at the page's 1300px the tracks come to four,
 * which is what the first row holds, so the row ends at the card's edge
 * instead of leaving a fifth track empty beside the time.
 */
.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.1rem 1.25rem;
}

.field-wide { grid-column: 1 / -1; }
/*
 * And the field takes two of the grid's tracks, because one is 233px and the
 * two labels want 276px together - on a single track they wrapped, which is
 * the stacking this was meant to end.
 *
 * Narrow screens are handled below, not by the span clamping itself: with
 * auto-fit tracks a span of two creates the second track rather than making do
 * with one, which is the trap .field-place already carries a note about.
 */
.field-grid > .field-mark { grid-column: span 2; }
.client-details summary { cursor: pointer; color: var(--ink-soft); }
.client-details > .field-grid { margin-top: 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (max-width: 640px) {
  /* A two-column place span would create an extra, implicit grid column on
     narrow screens and squeeze the full-width note and client details. */
  .field-grid > .field-place { grid-column: 1 / -1; }
  /* Same reason: spanning two would invent a second column 67px wide and
     squeeze every field in the form, the marks included. */
  .field-grid > .field-mark { grid-column: 1 / -1; }
  .client-details > .field-grid { grid-template-columns: minmax(0, 1fr); }
}

/*
 * The place needs room for a town, a region and a country, and no more. A full
 * row gave that string the width of the whole card and left the public figure
 * tick orphaned under the note, so the two share a row: two columns for the
 * place, one for the tick.
 */
.field-place { grid-column: span 2; }

/*
 * A label with something beside it. The row carries the gap the label used to
 * carry, so the control below sits where it did, and the two are aligned on
 * their baselines rather than their boxes: they are different sizes and would
 * otherwise read as two lines that happen to overlap.
 */
.label-row {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.4rem;
}
.label-row label { margin-bottom: 0; }
/* align-self here because .link-button sets flex-start for the column it
   usually sits in, and that would beat the row's baseline. */
.label-row .link-button { font-size: 0.8rem; padding: 0; align-self: baseline; }
.field-mark .checkbox-field { margin: 0; min-height: var(--control-height); }
/*
 * Align Public Figure with the Rodden control. The admin source checkbox can
 * wrap on a narrow screen without squeezing either control.
 */
.mark-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.35rem 1rem; }
.field-rodden { flex: 0 1 9rem; }
/* A URL wants room to be read back; it still wraps before it crowds the row. */
.field-case-study { flex: 1 1 18rem; min-width: 0; max-width: 28rem; }
.field-mark .checkbox-field[hidden] { display: none; }
.field { display: flex; flex-direction: column; min-width: 0; }

/*
 * And hidden when it says it is hidden. The browser's own rule for [hidden] is
 * display: none, and any class rule here that sets a display of its own beats
 * it, the UA stylesheet losing to an author one. That is how the manual
 * coordinates came to sit open under the form and the saved count to show a
 * zero over an empty list: both were marked hidden and both were drawn anyway.
 *
 * Set narrowly rather than with !important on [hidden], which the print styles
 * rely on being able to override when they open every panel at once.
 */
.field[hidden], .tab-count[hidden] { display: none; }

label, legend, .dms-label, .gochar-group-label {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
  color: var(--ink-faint);
  margin-bottom: 0.4rem;
}

.hint { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--ink-faint); font-size: 0.88em; }
/* Keep the whole time hint together so "24-hour" is not stranded below it. */
.keep-together { white-space: nowrap; }

textarea {
  font: inherit;
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper-tint);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.65rem 0.75rem;
  width: 100%;
  resize: vertical;
  min-height: 3.2rem;
}
textarea:focus {
  background: var(--surface);
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(47, 143, 95, 0.16);
  outline: none;
}
textarea::placeholder { color: #a9bdb2; }

/* A checkbox reads as a statement, so the label sits beside it rather than
   above it as the other fields' labels do. */
.checkbox-field {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.6rem 0 0;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--ink-soft);
  cursor: pointer;
}
.checkbox-field input { width: auto; margin: 0; }

/*
 * The note panel, between the name card and the charts. It carries the card's
 * own frame so it reads as part of the heading block rather than as a first
 * chart, and the box inside it grows with what is typed rather than scrolling.
 */
.note-card { padding: 1rem 1.6rem 1.1rem; }
.note-card[hidden] { display: none; }
.note-card textarea {
  width: 100%;
  min-height: 4.5rem;
  resize: vertical;
  font: inherit;
  font-size: 0.92rem;
  line-height: 1.55;
}
/* Its own line, so the box does not jump when the word changes. */
.note-state {
  margin: 0.45rem 0 0;
  min-height: 1.1em;
  color: var(--ink-faint);
  font-size: 0.78rem;
}
.note-state.is-saved { color: var(--green-deep); }

/*
 * A yoga opened out: how it formed in this chart, and what the texts say it
 * gives. The row spans the table because it is prose rather than another set
 * of cells, and the measure is held in ch so it reads at a paragraph width
 * whatever the table does.
 */
.yoga-toggle {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.yoga-toggle:hover { color: var(--green-deep); }
.yoga-toggle[aria-expanded="true"] { color: var(--green-deep); font-weight: 600; }
.yoga-toggle::before {
  content: '\25b8';
  width: 0.7rem;
  flex: 0 0 auto;
  color: var(--ink-faint);
}
.yoga-toggle[aria-expanded="true"]::before { content: '\25be'; color: inherit; }
.yoga-detail > td {
  background: var(--paper-tint);
  padding: 0.9rem 1.1rem 1.1rem;
  white-space: normal;
  /* Expanded prose spans the table and keeps a reading edge. */
  text-align: left;
}
#yoga-list > .table-scroll { container-type: inline-size; }
.yoga-detail-content {
  /* The row's own width, less its padding. It was capped at 78ch, a reading
     measure borrowed from the prose elsewhere on the page, which left the
     right half of a wide row empty and folded sentences that had room to run.
     This is a panel inside a table rather than an article, and it reads as
     unfinished when it stops short of the rule beneath it.

     Still sticky and still measured against the scroller rather than the
     table: the table is wider than its box on a phone, and prose that sat at
     the table's width would start off the side of the screen. */
  position: sticky;
  left: 1.1rem;
  width: calc(100vw - 6rem);
  width: calc(100cqw - 2.2rem);
}
.yoga-detail-note + .yoga-detail-head { margin-top: 0.9rem; }
.yoga-detail-note + .yoga-detail-note { margin-top: 0.4rem; }

.yoga-detail-head {
  margin: 0 0 0.3rem;
  font-family: var(--font-display);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--green-deep);
}
.yoga-detail-head + * { margin-top: 0; }
.yoga-detail-text, .yoga-detail-points {
  margin: 0 0 0.9rem;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--ink-soft);
}
.yoga-detail-points { padding-left: 1.1rem; }
.yoga-detail-points li { margin-bottom: 0.35rem; }
.yoga-detail-note {
  margin: 0;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.person-note {
  margin: 0.7rem 0 0;
  padding-left: 0.8rem;
  border-left: 2px solid var(--green-soft);
  font-size: 0.9rem;
  color: var(--ink-soft);
  max-width: 70ch;
  white-space: pre-wrap;
}

.saved-key {
  margin: 0.6rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}
/* One line per mark actually on a card, so the key never explains a mark that
   is not there to see. */
.saved-key-item { display: block; }

/*
 * The key for the two rows the graha table writes short. Under the table it
 * belongs to rather than once on the page: there is a table per chart, and a
 * reader on the second should not have to go back to the first.
 */
.table-key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 1.25rem;
  margin: 0.5rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}
.table-key[hidden] { display: none; }

/* The two tables of one chart, chosen rather than stacked. Lighter than the
   chart strip above it, which is a strip of charts and not of views. */
.graha-panes { margin: 0.2rem 0 0.9rem; }
.graha-panes[hidden] { display: none; }
.graha-panes .tab { padding-inline: 0.7rem; font-size: 0.8rem; }

.celebrity-mark {
  margin-left: 0.45rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--green-deep);
  background: var(--green-soft);
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
  vertical-align: middle;
}
.source-mark { display: inline-block; }

input, select {
  font: inherit;
  line-height: 1.4;
  color: var(--ink);
  background: var(--paper-tint);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0 0.75rem;
  height: var(--control-height);
  width: 100%;
  min-width: 0;
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}

/* Checkboxes keep their own size; the height above is for the boxes you type
   or choose in. */
input[type="checkbox"] { height: auto; }

/*
 * One dropdown everywhere. Left to itself each browser draws its own arrow -
 * a chevron here, a filled triangle there, a different size and inset on each
 * platform - so the same page showed three or four kinds of dropdown
 * depending on where it was read. The mark is ours now, and the one the
 * chart menu's button carries is the same file.
 */
select, .chart-menu-button {
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--dropdown-mark);
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  padding-right: 2rem;
}
/* Multi-line selects keep the browser's own list and need no mark. */
select[multiple], select[size]:not([size="1"]) {
  background-image: none;
  padding-right: 0.75rem;
}

input:hover, select:hover, .chart-menu-button:hover { border-color: #b8ddc8; }

input:focus, select:focus {
  background: var(--surface);
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(47, 143, 95, 0.16);
  outline: none;
}

input:focus-visible, select:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}

input::placeholder { color: #a9bdb2; }

.time-field, .date-field { border: none; margin: 0; padding: 0; min-width: 0; }
.time-field legend, .date-field legend { padding: 0; }

/*
 * Day, month, year, with a gap between them and no slashes. The separator was
 * the browser's to draw and it drew a different one per locale; a space says
 * three numbers as plainly and cannot be read as a fourth character to type.
 * The year gets the room for four digits, the day and month two each.
 */
.date-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1.7fr;
  align-items: center;
  gap: 0.45rem;
}

/* 24-hour time: hour, minute and second with colons between. */
.time-grid {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: center;
  gap: 0.3rem;
}
.time-colon { color: var(--ink-faint); text-align: center; }

/* Shown while the seconds box has focus, which is exactly when it answers a
   question and never otherwise. Kept in the accessibility tree at all times -
   faded rather than removed - so a screen reader still reads it out when the
   field is reached. */
.seconds-hint {
  grid-column: 1 / -1;
  /*
   * The line it holds open is a measure in its own right, because the Gochar
   * buttons have to hold the same one open to end level with the inputs. Set
   * here and spent there, so the two cannot drift apart.
   */
  height: calc(var(--seconds-hint-line) - 0.4rem);
  margin: 0.4rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
  opacity: 0;
  transition: opacity 0.12s ease;
}
/*
 * Any seconds field, not the birth one alone. The Gochar form carries the same
 * hint under #gochar-second, where the rule never matched: it reserved its line
 * and stayed invisible however long the field was focused.
 */
input[id$="-second"]:focus ~ .seconds-hint { opacity: 1; }
#birth-hour, #birth-minute, #birth-second {
  text-align: center;
  padding-left: 0.3rem;
  padding-right: 0.3rem;
  font-variant-numeric: tabular-nums;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.manual-coords {
  border: 1px dashed var(--line);
  background: var(--paper-tint);
  border-radius: var(--radius-sm);
  padding: 1rem;
}

/*
 * A legend sits over the top border by default, which is right for a plain
 * rule and wrong for a panel with a fill: half of every letter stood on the
 * tint and half on the card behind it, with the border passing through. This
 * is the float trick, which makes the legend an ordinary block inside the
 * panel, so the dashed border runs unbroken and the words sit on one colour.
 */
.manual-coords legend {
  float: left;
  width: 100%;
  padding: 0;
  margin-bottom: 0.8rem;
}
.manual-coords::after { content: ''; display: table; clear: both; }
.manual-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1rem; }

/* Degrees, minutes, seconds and a hemisphere on one line, so the coordinate reads
   as the single value it is rather than four unrelated boxes. The marks sit
   between them for the same reason. */
/*
 * Only the display, now. It named a group of four boxes rather than one
 * control, so it is a span rather than a <label for>, and having missed the
 * label rule it had drifted into a style of its own: bigger, darker and less
 * spaced than the timezone label beside it and the legend above it. Three
 * labels in one panel, none of them matching.
 */
.dms-label { display: block; }
.dms-row { display: flex; align-items: center; gap: 0.2rem; }
.dms-row input { width: 100%; min-width: 0; padding: 0 0.4rem; text-align: center; }
.dms-row select { width: auto; padding: 0 0.4rem; flex: 0 0 auto; }
.dms-mark { color: var(--ink-faint); font-size: 0.85rem; }
/* The conversion is where a mistake hides, so the decimal is echoed back rather
   than worked out silently. Height is held so the row does not jump. */
.dms-decimal {
  margin: 0.35rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--ink-soft);
  min-height: 1.2em;
}
.dms-decimal.dms-bad { color: var(--retro); font-family: inherit; }

.field-note { margin: 0.45rem 0 0; font-size: 0.85rem; color: var(--ink-soft); min-height: 1.2em; }

.options { margin-top: 1.5rem; border-top: 1px solid var(--line-soft); padding-top: 1rem; }

/*
 * The catalogue, folded. The tab is what this chart has; what the page checks
 * for is a question about the page, and answering it under the findings put a
 * hundred and eight names, most of them absent, below a table of eight.
 */
.options summary, .technical summary, .flag-legend summary {
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
}
.options summary:hover, .technical summary:hover,
.flag-legend summary:hover { color: var(--green); }

/*
 * Chart settings carries nine choices, and each one needs a paragraph or two to
 * say why anybody would pick differently. Printed out they buried the controls:
 * the panel read as an essay with selects in it rather than a set of options.
 *
 * So the reasoning folds. The label and the select stay visible - that is what
 * the panel is for - and "why one over the other" opens the argument for anyone
 * deciding rather than merely reading.
 */
.field-why { margin-top: 0.45rem; }
.field-why summary {
  cursor: pointer;
  color: var(--ink-faint);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}
.field-why summary:hover { color: var(--green); }
.field-why[open] summary { margin-bottom: 0.35rem; }
.field-why .field-note { margin-top: 0; }

/* Settings sit closer together now that each one is a label, a control and a
   line, rather than a control and an essay. */
/*
 * Eleven settings stacked one to a row made a long scroll of mostly empty
 * space, each select the full width of the card for the sake of a phrase.
 * Three to a row on a wide window, two on a narrower one, one on a phone.
 * Positioned, because the explanation card hangs off it.
 */
/*
 * The presets, above the controls they move. They are a starting point rather
 * than a mode, so they are set like the secondary buttons elsewhere and not
 * like a group of tabs: nothing here stays lit afterwards, because the moment
 * a reader changes one select the lit button would be a lie about what the
 * page is reading.
 */
/* Unboxed, right-aligned controls. Wrap on narrow screens; help opens on demand. */
.presets {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem 0.9rem;
  margin: 0 0 1rem;
}
.preset-picker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
}
.preset-picker label { font-size: 0.82rem; color: var(--ink-soft); }
/* Wide enough for the longest name it holds, and no wider: every other select
   on the page fills its field, and this one is sitting in a sentence. */
.preset-picker select { width: auto; min-width: 12rem; }
.preset-picker button {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
.preset-picker button:hover {
  color: var(--green-deep);
  border-color: var(--green);
  background: var(--green-soft);
}
/*
 * What the preset is, and where it cannot reach. Kept at the note's size and
 * colour, being the same kind of thing the notes under the controls are.
 *
 * A line of its own rather than a panel behind a "Why?" toggle: it is the one
 * thing on that row which is not a control, and a reader should not have to go
 * looking for it. The text stays left-aligned where the row is right-aligned,
 * because a paragraph set ragged-left is read a line at a time.
 *
 * Neither note is drawn until it has something to say, so an unchosen reading
 * leaves no empty band above the settings.
 */
.preset-what {
  width: 100%;
  max-width: 46rem;
  margin: 0.2rem 0 0 auto;
  text-align: left;
}
.preset-what:empty { display: none; }
/* Automatic-save feedback stays left-aligned and occupies space only when needed. */
/*
 * On the row with the controls, not under them. It took the full width, which
 * is what put one short sentence on a line of its own with the picker and the
 * button stranded at the far end of the line above it.
 *
 * order pulls it in front of them in the row rather than after, and the auto
 * margin takes the space between: the controls stay at the right edge where
 * they were, and the sentence reads from the left. It still drops to its own
 * line when the two cannot share one, which is what flex-wrap is for.
 */
.preset-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.7rem;
  order: -1;
  margin-right: auto;
}
.preset-notice[hidden] { display: none; }
.preset-status { margin: 0; text-align: left; }

/*
 * The page for building custom settings of your own, in place of the settings
 * rather than over them. It takes the panel's whole width, which is the point:
 * the comparison is seven columns and a modal is narrower than what it covers.
 */
.preset-page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: start;
  gap: 1rem;
  margin-bottom: 1.25rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line-soft);
}
.preset-page-head p { margin: 0.2rem 0 0; }
#preset-back {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  flex: 0 0 auto;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
}
#preset-back:hover {
  color: var(--green-deep);
  border-color: var(--green);
  background: var(--green-soft);
}
/*
 * The two buttons sit together at the end of the heading's row, the reset
 * before the way out. The auto margin is on the first of them rather than on
 * Back, which is what used to carry it: with it there, the reset would have
 * been left stranded against the heading while only Back moved right.
 */
#preset-forget {
  margin-left: auto;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
}
#preset-forget:hover { color: var(--retro); border-color: var(--retro); }

/*
 * Seven columns and a row per setting: the name of the setting, the reader's
 * own choice, and the five published readings side by side. It scrolls
 * sideways rather than wrapping, because a row only means anything read
 * across.
 */
/*
 * Sideways only. The vertical axis is stated rather than left implicit,
 * because overflow-x alone makes the box a scroll container on both axes and
 * grows a vertical bar the moment anything overflows by a pixel. Nothing is
 * clipped by hidden here: the box is as tall as its rows and the dialog does
 * the vertical scrolling.
 */
.preset-editor { overflow-x: auto; overflow-y: hidden; }
/*
 * Fixed, and the columns share the width in a stated proportion. Left to size
 * themselves the cells took the width of their longest sentence - "Zone time,
 * from the place's timezone" and its like - and seven of those put the five
 * readings the table exists to compare off the side of the page.
 *
 * The words are not shortened to make them fit. They are the page's own words
 * for those options, and an abbreviation invented here would be a second name
 * for a reading, which is how two surfaces come to disagree. They wrap.
 */
.preset-table {
  --table-cell-block: 0.35rem;
  --table-cell-inline: 0.4rem;
  min-width: 48rem;
  table-layout: fixed;
  font-size: 0.82rem;
}
.preset-table th:first-child { width: 14%; }
.preset-table th:nth-child(2) { width: 20%; }
.preset-table th:nth-child(n + 3) { width: 13.2%; }
/* Not sticky: the dialog is what scrolls vertically, and a header pinned to
   this box would pin to a box that does not move. */
.preset-table thead th {
  padding-top: 0;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--surface);
}
/*
 * The row headings wrap too, and keep their sentence case: `th` on this page
 * is set in small capitals for tables of figures, where a heading is a word or
 * two. These are the names of settings and read as the labels they are copied
 * from.
 */
.preset-table tbody th {
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  white-space: normal;
}
.preset-table select { width: 100%; height: auto; padding: 0.2rem 0.4rem; }
/* Do not borrow the other tables' green hover band for this comparison. */
.preset-table tbody tr:hover,
.preset-table tbody tr:hover th[scope]:not([rowspan]) { background: var(--surface); }
/*
 * Taking a whole column, which is the job a "Start with" select used to do
 * above the table. A heading that fills its own column says what it does
 * where the doing happens.
 */
.preset-column-take {
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
}
.preset-column-take:hover { color: var(--green-deep); }
/* Recorded values are pressable; only differences from yours are green. */
.preset-cell {
  font: inherit;
  width: 100%;
  text-align: inherit;
  white-space: normal;
  line-height: 1.25;
  color: var(--ink);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.25rem 0.4rem;
  cursor: pointer;
}
button.preset-cell:hover { border-color: var(--ink-soft); }
/* Missing documentation is neither a choice nor a disagreement. */
.preset-cell-unrecorded { display: block; cursor: default; }
.preset-unrecorded-mark { color: var(--ink-soft); text-decoration: none; cursor: help; }
/*
 * The key, and the line that reports a save, both sit under the table rather
 * than inside its scrolling box. Neither reserves a line while it is empty:
 * .field-note holds one open so a status appearing does not shove the page
 * down, which is right where a line comes and goes and wrong at the foot of a
 * card, where it reads as the card having nothing to say.
 */
.preset-key { margin: 0.9rem 0 0; max-width: 46rem; min-height: 0; }
#preset-editor-status { min-height: 0; }
#preset-editor-status[hidden] { display: none; }
/*
 * A tint and nothing else. It also carried a border and a deeper green on the
 * words, which drew three marks around one fact and made every highlighted
 * cell read as a button pressed rather than as a value that differs. The
 * transparent border on .preset-cell stays, so nothing shifts when a cell is
 * hovered and given one.
 */
.preset-cell-differs { background: var(--green-soft); }
/*
 * The name of a group, opening its own tbody. The page keeps these settings in
 * two tabs - the readings that change the chart, and the ones that only move a
 * figure inside the strength tables - and twenty-four rows at one stretch
 * asked a reader to find that division for themselves.
 */
.preset-group-head th {
  padding-top: 1.1rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--green-deep);
  border-bottom: 1px solid var(--line);
}
/* The first group opens the table, where the column headings are already the
   rule above it. */
.preset-group:first-of-type .preset-group-head th { padding-top: 0.35rem; }
/* Source disagreement is independent of the reader's choice: say it in
   words, without borrowing the green reserved for individual differences. */
.preset-sources-differ {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--ink-soft);
}


.settings-group {
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  margin-bottom: 1rem;
}
.settings-group > summary {
  padding: 1rem;
  cursor: pointer;
  font-weight: 600;
}
.settings-group > .card { border: 0; margin: 0; }
/*
 * A subject within the group, headed rather than boxed: the group is already a
 * disclosure inside a card, and a third border around each subject would be a
 * box in a box in a box. A rule between them is enough to say where one
 * subject ends, and the first needs none, having the summary above it.
 */
.settings-subgroup + .settings-subgroup {
  margin-top: 1.7rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line-soft);
}
/*
 * Deliberately not the field labels' grey. These head the labels, and in the
 * same ink at the same size they read as one more label with nothing under it.
 */
.settings-subgroup-head {
  margin: 0 0 1.1rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--green-deep);
}
.settings-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.3rem 1.5rem;
}
@media (min-width: 40rem) {
  .settings-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 62rem) {
  .settings-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/*
 * The reasoning used to fold out of a <details> under each select, which put
 * eleven disclosure triangles on the page and made every row a different
 * height. It is kept in the document - the select points at it with
 * aria-describedby, so it is read out on focus - and taken out of the layout,
 * where the hover card reads it instead.
 */
.field-why {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  border: 0;
}

/*
 * The same card the chart uses for a graha, for the same reason: the
 * explanation is long enough to want room and rare enough not to want it
 * taking space until asked.
 */
.setting-card {
  position: absolute;
  transform: translateX(-50%);
  z-index: 5;
  min-width: 11rem;
  width: max-content;
  max-width: min(34rem, calc(100vw - 1.5rem));
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  pointer-events: none;
  text-align: left;
}
.setting-card[hidden] { display: none; }
.setting-card h4 {
  margin: 0 0 0.35rem;
  font-size: 0.95rem;
  color: var(--green-deep);
  font-weight: 700;
}
.setting-card .field-note {
  position: static;
  width: auto; height: auto;
  margin: 0; padding: 0;
  clip: auto;
  overflow: visible;
  font-size: 0.78rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* The label is what you hover, so it has to say so. */
.settings-panel .field label { cursor: help; }

/*
 * A select stretched to the width of the card reads as a text box waiting to
 * be filled in, not as a choice between two or three phrases - and the panel
 * is wide, so "Lahiri (Chitrapaksha)" sat alone in a box five times its
 * length. Capped at the width the longest option needs: "True declination,
 * latitude and all (Parashara's note)" is the longest of them at 53
 * characters, and 30rem carries it without clipping at the default size.
 *
 * A cap rather than a fixed width, so a narrow window still shrinks it, and
 * scoped to this panel so the chart selects and the place combobox, which want
 * the width they are given, are untouched.
 */
.settings-panel .field select { max-width: 30rem; }

/*
 * The hover card for a graha in a chart. The label can only carry initials and
 * a bracket or two, so everything else about that graha in that chart - its
 * sign and house, the states it is in, the yogas it takes part in - lives here
 * and appears on hover or focus.
 */
#chart-a, #chart-b, #chart-c { position: relative; }
#panel-vargas { position: relative; }

.graha-card {
  position: absolute;
  transform: translateX(-50%);
  z-index: 5;
  min-width: 11rem;
  /*
   * Wide enough that a finding's name and its frequency sit on one line. At
   * 21rem they did not, so every title wrapped - "Angle-/trine raja/yoga" -
   * and a graha with five findings became a tall thin column. The card is a
   * popover and may be wider than the chart column it belongs to; it is kept
   * on screen by the clamp in app.js rather than by the column's edges.
   *
   * width: max-content is what makes that cap mean anything. The card is
   * absolutely positioned with only `left` set, so without it the box shrinks
   * to fit whatever space is left between `left` and the right edge of the
   * chart column - and a graha further right got a narrower card from the same
   * rule. Two cards on one page could differ by half their width with nothing
   * to explain it. Taking the width from the content instead makes the cap the
   * only thing that decides it.
   */
  width: max-content;
  max-width: min(34rem, calc(100vw - 1.5rem));
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  pointer-events: none;   /* never steals the hover it was opened by */
  text-align: left;
}
.graha-card[hidden] { display: none; }
.graha-card-name {
  margin: 0;
  font-size: 0.95rem;
  color: var(--green-deep);
  font-weight: 700;
}
/*
 * The position was hung off the name too, which made the heading the one line
 * on the card set to nothing in particular: a flex container of its own, its
 * own dot, its own spacings to keep in step with the rest. The frames are
 * rows of the grid now, and what is left beside the name is the chara karaka,
 * which is not a frame and has no column to stand in.
 *
 * Lighter and lighter in weight, because it is a role the graha holds and not
 * part of what it is called: at the name's weight and colour it read as a
 * second half of the name.
 */
.graha-card-role {
  margin-left: 0.55rem;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ink-soft);
}
/*
 * The three frames a graha sits in at once, run together on one line with a
 * dot between them. Separate lines made each read as a finding of its own,
 * where house, sign and nakshatra are one placement said three ways.
 */
.graha-card-conditions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.55rem;
  margin: 0.25rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-soft);
}
/*
 * The placement, two rows of three in one grid. Each line was its own flex row
 * before, so each spaced itself by its own words and the dots fell in three
 * different places down the card. A shared grid gives the two rows the same
 * three columns, and since the dot is the first thing in a cell it lands where
 * the column starts.
 *
 * The columns take their width from their content rather than the card, and
 * justify-content keeps the leftover space at the end instead of handing it to
 * the tracks to spread themselves with.
 */
.graha-card-grid {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
  align-items: baseline;
  gap: 0.2rem 0.55rem;
  margin: 0.25rem 0 0;
  font-size: 0.8rem;
  color: var(--ink);
}
/*
 * Ruled off above and below: the placement is one thing, how the graha stands
 * is another, and the yogas a third. The same rule the list draws between one
 * finding and the next, so the card reads as one set of divisions.
 */
/*
 * Ruled off and nothing else. These are facts about the graha like the ones
 * above them, so they are set like them: the rule says where the placement
 * ends, and weight or colour on top of it would claim the line is a different
 * kind of thing to read.
 */
.graha-card-conditions {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--line-soft);
}
.graha-card-conditions { font-size: 0.8rem; color: var(--ink); }
.graha-card-sky-conditions {
  margin-top: 0.4rem;
  font-size: 0.8rem;
  color: var(--ink);
}
.graha-card-sky-conditions p { margin: 0.2rem 0 0; }

/* A dot between items, and never before the first or after the last. */
.graha-card-item + .graha-card-item::before {
  content: '\00b7';
  margin-right: 0.55rem;
  color: var(--ink-faint);
}
/*
 * In the grid the dot would also open the second row, because that cell still
 * follows a cell in the markup. Every third one starts a line, so every third
 * one drops it.
 */
.graha-card-grid > .graha-card-item:nth-child(3n + 1)::before { content: none; }
.graha-card-contacts {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.55rem;
}
/* Every item is a statement with its reason beneath it, so the list is the
   card's body rather than a tail on the end of it. */
/* The list rules a line between its own items but had none above the first, so
   the placement and dignity ran straight into the findings. Same rhythm as
   `li + li` below, so the whole card reads as one set of divisions. */
.graha-card-list {
  margin: 0.5rem 0 0;
  padding: 0.5rem 0 0;
  border-top: 1px solid var(--line-soft);
  list-style: none;
}
/*
 * One line each. Eight findings at three lines apiece ran the card past the
 * height of the chart it was drawn over, and the two lines under each name
 * were the rule and the reason - both of which the Yogas tab gives in full,
 * with the conditions the card never had room for. What is left is what the
 * card is for: which combinations this graha is in, and how rare each is.
 */
.graha-card-list li + li {
  margin-top: 0.2rem;
  padding-top: 0.2rem;
  border-top: 1px solid var(--line-soft);
}
/*
 * Three columns, not two ends and a drifter.
 *
 * space-between with three children puts the middle one halfway along,
 * wherever halfway happens to fall for that row, so the "from" read as a
 * ragged line of its own down the middle of the card. The name takes the
 * slack instead and the two that qualify it sit right, each in a column wide
 * enough to hold the longest of them.
 */
.graha-card-term {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink);
}
.graha-card-label { flex: 1; }

/*
 * The reserved columns are given back on a narrow screen.
 *
 * They reserve 8.5rem and 7rem with 1.5rem of gaps between, which is 17rem.
 * At 320px the card is capped at 100vw - 1.5rem and its padding takes another
 * 1.5rem, leaving 17rem of content: exactly the reservation, and nothing at
 * all for the name. At 375px the name got 3.4rem, which wraps "Angle-trine
 * raja yoga" into four lines.
 *
 * Below the width where a name has room to be read, the row wraps instead:
 * the name takes a line of its own and the two things that qualify it sit
 * under it, right, in the order they had.
 */
@media (max-width: 30rem) {
  .graha-card-term { flex-wrap: wrap; justify-content: flex-end; }
  .graha-card-label { flex: 1 1 100%; }
  /* Two selectors so the release outranks the single-class base rules below,
     irrespective of their later source order. */
  .graha-card-term .graha-card-whose,
  .graha-card-term .graha-card-freq { min-width: 0; }
}
/* How common the finding is. Recessive, because it qualifies the statement
   rather than competing with it - but present on every line, so the reader can
   weigh a rare yoga against a near-universal one at a glance. */
.graha-card-freq {
  flex: none;
  min-width: 7rem;
  text-align: right;
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--ink-soft);
  white-space: nowrap;
}
/* What the yoga is, from the library. Set apart from the reason it holds here,
   which is the line under it: one is the rule, the other this chart. */

/* The label is hoverable and reachable, so it needs a focus ring of its own -
   SVG text takes none by default. */
svg.kundli .planet { cursor: default; }
svg.kundli .planet:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* The mark legend. Nine entries of prose under every chart is a lot of page to
   scroll past once you know them, and they are the kind of thing read twice and
   then never again - so it is closed until asked for. */
.flag-legend {
  margin: 1.25rem 0 0;
  border-top: 1px solid var(--line-soft);
  padding-top: 0.9rem;
}
/*
 * One line above the grid it explains, rather than a block under the charts:
 * the six marks below are drawn as bare letters on purpose and have no hover.
 *
 * The comment used to sit between .flag-legend and .varga-key with no comma,
 * and a comment is whitespace to the parser, so the two had become the single
 * descendant selector `.flag-legend .varga-key`, which matches nothing. The
 * rule below is the one the varga key is actually drawn with; the duplicate of
 * it further down the file is what has been styling it all this time.
 */
.varga-key {
  margin: 0 0 0.6rem;
  font-size: 0.78rem;
  line-height: 1.8;
  color: var(--ink-soft);
}
.flag-note {
  margin: 0 0 0.6rem;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--ink-soft);
}
.flag-key { margin-top: 0.9rem; }
.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1rem 1.25rem;
  margin-top: 1rem;
}

.actions { display: flex; align-items: center; gap: 1rem; margin-top: 1.6rem; flex-wrap: wrap; }

button.primary {
  font: inherit;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #ffffff;
  background: linear-gradient(180deg, #35a06b 0%, #2a855a 100%);
  /*
   * Transparent rather than none, so the two buttons are the same height.
   * The secondary beside it carries a 1px border on the same padding, which
   * made it two pixels taller; centred in their row the pair sat a pixel out
   * of line, and the primary's lift shadow made that read as a slip rather
   * than as the shadow it is.
   */
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.75rem 1.7rem;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(25, 90, 60, 0.22), 0 6px 16px rgba(40, 130, 88, 0.22);
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}
button.primary:hover { filter: brightness(1.06); transform: translateY(-1px); }
button.primary:active { transform: translateY(0); }
button.primary:disabled { opacity: 0.6; cursor: progress; transform: none; }

/* Beside the primary and clearly not it: the same shape, none of the weight.
   Emptying a form is not the thing anybody came to the page to do. */
button.secondary {
  font: inherit;
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1.4rem;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
button.secondary:hover {
  color: var(--green-deep);
  border-color: var(--green);
  background: var(--green-soft);
}

.link-button {
  font: inherit;
  font-size: 0.875rem;
  color: var(--green);
  background: none;
  border: none;
  padding: 0.35rem 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  align-self: flex-start;
}
.link-button:hover { color: var(--green-deep); }

/*
 * The three switches over the diagrams, between the name and the charts.
 * Against the right margin: they belong to the figures below rather than to
 * the card above, and the eye reads the charts from the left.
 */
.chart-marks {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.4rem;
  margin: -0.4rem 0 0.7rem;
}
.mark-toggle {
  font: inherit;
  font-size: 0.8rem;
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  cursor: pointer;
}
.mark-toggle[aria-pressed="true"] {
  background: var(--green-soft);
  border-color: var(--green);
  color: var(--green-deep);
}
.mark-toggle:hover { border-color: var(--green); }
/* The longitude beside a graha: a shade smaller than the karaka, being the
   longest of the three things that can stand there. */
.graha-longitude { font-size: 0.68em; fill: var(--ink-soft); color: var(--ink-soft); }

/*
 * The moment under a transit figure, typed where it is read. Small boxes:
 * they sit where a caption was, and a caption is not a form to fill in but a
 * line to adjust.
 */
.transit-moment-edit {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  /* The space between the date and the clock is wider than the spaces
     inside either, or the six boxes read as one run of numbers. */
  gap: 0.35rem 1.2rem;
}
.transit-moment-edit .date-grid { grid-template-columns: 2.5rem 2.5rem 3.5rem; gap: 0.3rem; margin: 0; }
.transit-moment-edit .time-grid { grid-template-columns: repeat(3, 2.4rem auto); gap: 0.3rem; margin: 0; }
.transit-moment-edit input {
  text-align: center;
  padding: 0.25rem 0.3rem;
  font-size: 0.8rem;
}
.transit-moment-edit .time-colon { padding: 0; }
.transit-moment-edit[data-invalid="true"] input { border-color: var(--retro); }

.form-error { color: var(--retro); margin: 0; font-size: 0.9rem; }

/* ---------------------------------------------------------------- combobox */

.combobox { position: relative; }

.combobox ul {
  position: absolute;
  z-index: 20;
  top: calc(100% + 5px);
  left: 0;
  right: 0;
  max-height: 300px;
  overflow-y: auto;
  overflow-x: hidden;   /* long place names wrap; they must not scroll sideways */
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift);
}

.combobox li {
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.93rem;
}
.combobox li[aria-selected="true"], .combobox li:hover { background: var(--green-soft); }
.combobox li .place-meta { color: var(--ink-faint); font-size: 0.85em; display: block; }
.combobox li.empty { color: var(--ink-faint); cursor: default; }

/* ------------------------------------------------------------------ result */

/* Keep the birth details and Panchang compact above the charts. */
.result-header { padding: 1.2rem 1.5rem; }

.result-title-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.result-header h2 {
  font-family: var(--font-display);
  font-weight: 500;
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 1.4rem;
  color: var(--green-deep);
}

/* Chart actions stay alongside the name; birth details use the full row below. */
.result-title-row .celebrity-mark,
.result-title-row .flag-mark { max-width: 100%; white-space: normal; }
.result-title-row .identity-detail,
.result-title-row .celebrity-mark {
  margin: 0;
  padding: 0;
  background: none;
  border-radius: 0;
  font-family: var(--font);
  font-size: 0.9rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink-soft);
  vertical-align: baseline;
}
.result-title-row .identity-detail::before,
.result-title-row .celebrity-mark::before,
.birth-row .location-line::before {
  content: '\00b7';
  margin: 0 0.5em;
  color: var(--ink-faint);
}
.birth-row {
  color: var(--ink-soft);
  font-size: 0.9rem;
  line-height: 1.7;
  overflow-wrap: anywhere;
}
.birth-line { margin: 0; color: var(--ink-soft); font-size: 0.9rem; min-width: 0; }
.birth-row .birth-line { display: inline; }
/* Inline beside the date and time; the margin a line of its own needed went
   with the line. */
.location-line { overflow-wrap: anywhere; }
.time-offset-help {
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  padding: 0.15rem 0.35rem;
  cursor: help;
}
.time-offset-help:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.time-offset-explanation { margin: 0.25rem 0 0; max-width: 65ch; }

.result-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }

.icon-button[hidden] { display: none; }
.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  color: var(--ink-soft);
  background: var(--paper-tint);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease, border-color 0.12s ease;
}
.icon-button:hover { color: var(--green-deep); background: var(--green-soft); border-color: var(--green); }
.icon-button svg {
  width: 1.15rem;
  height: 1.15rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.key-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1rem 1.25rem;
  margin: 0;
}
.key-facts div { min-width: 0; }
.key-facts dt {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  font-weight: 600;
  color: var(--ink-faint);
}
.key-facts dd { margin: 0.2rem 0 0; font-size: 1.03rem; }
.key-facts dd .sub { display: block; font-size: 0.85rem; color: var(--ink-soft); }

/*
 * Kundali Milan: a name to match against, and the eight kootas under it.
 * The box is the one that opens a chart, so it is styled as that one; the
 * name stays in it after choosing, being the only thing on the page that
 * says whose chart the table below belongs to.
 */
/* Centred: one control on an otherwise empty panel, with the matching it
   makes centred under it. Against the left edge it read as the first field
   of a form that had lost the rest of itself. */
/*
 * The day the dasha tables answer for: a label, a date and the way back. It
 * stands above the strip of systems, since it governs all of them; under the
 * strip it looked like a field belonging to whichever system was open.
 */
.dasha-when-search {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin: 0 0 0.85rem;
}
.dasha-when-label { font-size: 0.8rem; font-weight: 600; color: var(--ink-soft); }
.dasha-when-search .date-grid { margin: 0; }
/* Sized to what is typed into them. The birth form's boxes fill a column of
   a form; these three stand in a row of their own, and at full width they
   read as somewhere to write a sentence. */
.dasha-when-search .date-grid { grid-template-columns: 3.4rem 3.4rem 4.8rem; }
.dasha-when-search .time-grid { margin: 0; grid-template-columns: repeat(3, 3.4rem auto); }
.dasha-when-search .date-grid input,
.dasha-when-search .time-grid input {
  text-align: center;
  padding-left: 0.4rem;
  padding-right: 0.4rem;
}
.dasha-when-search .time-colon { padding: 0 0.1rem; }
/* The clock sits against its date, not a field away from it. */
.dasha-when-search #dasha-at-clock-label { font-weight: 400; }
.dasha-when-search button { padding: 0.45rem 0.75rem; font-size: 0.85rem; font-weight: 400; }
.dasha-when-search .hint { margin: 0; }

/*
 * What every system is running on that day, read as a block rather than
 * hunted for one tab at a time. The labels line up in a column of their own
 * so the periods beside them can be compared down the page.
 */
/*
 * The open transit moments, and the two buttons that open and close one.
 * The strip is the app's own sub-tab strip, named by moments rather than by
 * subjects, since what a reader is choosing between here is times.
 */
.gochar-transit-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.9rem;
  margin-bottom: 0.9rem;
}
/* The strip keeps its own line, so its rule runs the width of the panel as
   every other strip here does; the two buttons sit under it rather than at
   the far edge of a row, where they read as belonging to nothing. */
.gochar-transit-tabs { margin: 0; flex: 1 1 100%; }
.gochar-transit-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.gochar-transit-actions button { padding: 0.45rem 0.75rem; font-size: 0.85rem; font-weight: 400; }

.dasha-readings { margin: 0 0 1rem; }
.dasha-readings-day { margin: 0 0 0.3rem; }
.dasha-reading-list { margin: 0; }
/* The guard matters: a row for a system the birth does not qualify for is
   hidden, and display:grid would outrank the attribute. */
.dasha-reading:not([hidden]) {
  display: grid;
  grid-template-columns: minmax(0, 11rem) 1fr;
  gap: 0.1rem 0.9rem;
  padding: 0.12rem 0;
}
.dasha-reading dt { color: var(--ink-soft); font-size: 0.85rem; }
.dasha-reading dt::after { content: ':'; }
.dasha-reading dd { margin: 0; color: var(--ink); }
@media (max-width: 30rem) {
  /* Too narrow for two columns: the label sits over its reading instead. */
  .dasha-reading:not([hidden]) { grid-template-columns: 1fr; gap: 0; padding-bottom: 0.4rem; }
}

.milan-combobox { max-width: 32rem; margin: 0 auto 0.75rem; }

/* The bindus of a sign, alone in the middle of a box where the grahas would
   otherwise stand. Set large because it is the whole of what that chart
   says, and in the ink the sign numbers use rather than a graha's. */
.kundli .bindu-total {
  font-size: 30px;
  font-weight: 600;
  fill: var(--green-deep);
}
#milan-status { text-align: center; }
.milan-table { width: 100%; }
/* A koota that scored nothing is the reason a total is what it is. */
.milan-table tbody tr.milan-nil th[scope="row"],
.milan-table tbody tr.milan-nil td { color: var(--retro); }
.milan-table tfoot th[scope="row"],
.milan-table tfoot td { font-weight: 700; }
.milan-dosha { margin-top: 1.25rem; }
.milan-dosha .panel-caption { text-align: left; margin-bottom: 0.4rem; }

.print-button { margin-top: 1.3rem; }

/* ------------------------------------------------------------------ charts */

/* Three charts, side by side, so two divisions can be read against the rashi
   chart without clicking between them. The track minimum is what keeps that
   honest: they reflow to two and then one rather than shrinking, a kundli
   below about 300px having stopped being readable. */
.chart-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
  gap: 1.25rem;
}
.chart-card {
  margin: 0 0 1.25rem;
  background: linear-gradient(180deg, var(--surface) 0%, #f7fcf9 100%);
}

.subtabs { margin-bottom: 1.1rem; }
.subtabs .tab { font-size: 0.88rem; padding: 0.55rem 0.95rem; }

/*
 * What is drawn goes above the chart and how it is read goes below it: the
 * style against the left margin, the division against the right, and under
 * the figure the rotation on the left with the way back to the ascendant on
 * the right. The four controls were a single row above the chart, which read
 * as one question in four parts when they are two questions about different
 * things.
 */
.chart-controls {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.9rem;
}
.chart-select {
  font-size: 0.85rem;
  /* The right side is the mark's lane. Set as one padding, the shorthand
     took it back and the triangle was drawn over the last letter of Graha. */
  padding: 0.45rem 1.7rem 0.45rem 0.5rem;
  background-position: right 0.55rem center;
  flex: 1 1 0;
  min-width: 0;
}
/*
 * The kind is one word where the other two are two or three, so it takes a
 * basis of its own rather than an even third. Named rather than counted: the
 * labels are children of the row too, so nth-child counts past them and lands
 * on the wrong control. The basis is spelled out because selects carry
 * width: 100% for stacked forms, which would make auto resolve to the row.
 */
.chart-select-kind { flex: 0 1 6.8rem; }
.chart-select-choice { flex: 0 0 5.4rem; width: 5.4rem; }
/* Sized to its own longest option rather than to a share of the row: it is
   against the right margin, so a box wider than its words is a box with a
   gap in front of them. */
.chart-select-varga { flex: 0 1 auto; width: auto; max-width: 60%; }
/* The division, with the menu that stands in for it. The two selects behind
   it are the controls of record and are not drawn. */
.chart-draws { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.chart-menu { position: relative; display: inline-flex; min-width: 0; max-width: 100%; }
/*
 * The selects behind the menu are hidden the usual way, and the usual way
 * sets a width of one pixel - which .chart-select-varga, a class of the same
 * weight further down this file, was overriding back to auto. An absolutely
 * positioned select at its full width then stood off the right edge of the
 * third card and scrolled the whole page sideways.
 */
.chart-select.visually-hidden { width: 1px; height: 1px; min-width: 0; }
/*
 * A button standing in for a select has to look like one: same tint, same
 * faint rule, same radius and the same height as every other control on the
 * page. Left to itself a button takes the browser's grey chrome, which is
 * the one thing on these cards that belonged to no theme at all.
 */
.chart-menu-button {
  width: auto;
  max-width: 100%;
  flex: 0 1 auto;
  min-width: 0;
  height: var(--control-height);
  /* Room on the right for the mark the shared rule draws there. */
  padding: 0 2rem 0 0.75rem;
  background-color: var(--paper-tint);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  text-align: left;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
  /*
   * A button does not wrap and will not shrink below its text, so on a phone
   * "Sarvashtakavarga" would push the row past the edge of the page. The
   * label gives way instead, and the menu beneath it still spells it out.
   */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Open is the button's version of focus, and says so the same way. */
.chart-menu-button[aria-expanded="true"] {
  background-color: var(--surface);
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(47, 143, 95, 0.16);
}
/* Under the button and against its right edge, which is the card's. */
.chart-menu-list, .chart-menu-flyout {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 40;
  min-width: 11rem;
  max-height: min(60vh, 22rem);
  /* Down only: every item is one line that may not wrap. */
  overflow-x: hidden;
  overflow-y: auto;
  padding: 0.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(31, 107, 71, 0.16);
}
.chart-menu-flyout { min-width: 7rem; max-height: none; }
/*
 * Many short labels read as a grid; see fillFlyout in select-menu.js.
 *
 * Guarded against [hidden], which hides by display: none at one class of
 * weight and loses to this rule's two. Without the guard the flyout could
 * not be closed at all once it had been laid out as a grid.
 */
.chart-menu-flyout.is-grid:not([hidden]) {
  display: grid;
  grid-template-columns: repeat(4, minmax(3.1rem, 1fr));
  gap: 1px;
  min-width: 0;
}
.chart-menu-flyout.is-grid .chart-menu-item {
  justify-content: center;
  padding: 0.38rem 0.3rem;
}
.chart-menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  padding: 0.38rem 0.6rem;
  border: 0;
  border-radius: 7px;
  background: none;
  font: inherit;
  font-size: 0.85rem;
  color: var(--ink);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.chart-menu-item:hover, .chart-menu-item:focus { background: var(--row-hover); outline: none; }
.chart-menu-item.is-current { font-weight: 600; color: var(--green-deep); }
.chart-menu-arrow { color: var(--ink-faint); }
.chart-menu-parent[aria-expanded="true"] { background: var(--row-hover); }
.chart-rotate { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.chart-card figcaption {
  font-family: var(--font-display);
  color: var(--green-deep);
  letter-spacing: 0.02em;
  font-size: 0.95rem;
  margin-top: 0.9rem;
  text-align: center;
}

.chart-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-top: 0.8rem;
}
.chart-actions button { padding: 0.45rem 0.75rem; font-size: 0.85rem; font-weight: 400; }
/* First in its row now, so it no longer pushes itself to the right. */
.chart-style-control { display: flex; align-items: center; gap: 0.4rem; flex: 0 0 7.5rem; min-width: 0; font-size: 0.85rem; color: var(--ink-soft); }
.chart-style-control select { width: 100%; min-width: 0; }

svg.kundli { width: 100%; height: auto; display: block; }

svg.kundli .frame, svg.kundli .cell {
  fill: none;
  stroke: #a9d7bd;
  stroke-width: 1.1;
  stroke-linejoin: round;
}
svg.kundli .frame-outer { stroke: var(--green); stroke-width: 2; }
svg.kundli .middle { fill: none; stroke: none; }

svg.kundli .first-house .cell { fill: rgba(47, 143, 95, 0.10); }

svg.kundli text {
  font-family: var(--font);
  fill: var(--ink);
  font-size: 15px;
}
svg.kundli .sign-num {
  fill: var(--ink-faint);
  font-size: 12px;
  letter-spacing: 0.06em;
  font-weight: 600;
}
svg.kundli .planet { fill: var(--ink); font-size: 15.5px; font-weight: 500; }
.chara-karaka { font-size: 0.75em; font-weight: 400; color: var(--ink-soft); fill: var(--ink-soft); }
svg.kundli .reference-mark { fill: var(--ink); font-weight: 600; cursor: help; }
svg.kundli .reference-mark:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* Planet names share the tables’ text color; only the bracketed marks carry
   green/red meanings. The ascendant keeps its heavier weight. */
svg.kundli .graha-lagna { font-weight: 700; }

/* ---------------------------------------------------- yogas and lessons */

/*
 * The findings are a table now. What is left here is what the table still uses;
 * the card rules that went with the old stacked layout - a bordered box, a
 * display-face heading, an italic family run in after the name, a line of
 * grahas under the summary - went with it rather than sitting unreferenced.
 */
.yoga-name {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--green-deep);
}
.yoga-reasons li { margin-bottom: 0.2rem; }

/*
 * The search, its label and whatever it has to report, on one line and on the
 * page rather than in a card. Stacked inside a card it spent three lines and a
 * raised surface on one box that is capped at 34rem anyway, and started the
 * course contents a long way down a screen with room to spare beside the box.
 * It wraps back into a stack when the row no longer fits.
 */
.tutorial-welcome {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.6rem 1.1rem; margin: 0 0 0.9rem;
}
.lesson-search {
  flex: 1 1 28rem; max-width: 40rem; margin-bottom: 0;
  flex-direction: row; align-items: center; gap: 0.7rem;
}
.lesson-search label { margin-bottom: 0; white-space: nowrap; }
/* The surface the card used to provide. Out here the box sits on the page's
   own tint, and the usual input fill is that same tint. */
.lesson-search input { flex: 1 1 auto; min-width: 0; background: var(--surface); }
/* Empty while a lesson is open: it answers a search, and what the course holds
   is answered beside the contents it describes. The reserved line keeps the
   row from shifting when an answer arrives. */
.tutorial-welcome > p { max-width: 75ch; margin: 0; }
/* The course's size, under the heading for the list of it. */
.outline-count {
  display: block; font-weight: 400; font-size: 0.8rem; color: var(--ink-soft);
  margin-top: 0.15rem;
}
.tutorial-layout { display: grid; grid-template-columns: 17rem minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.tutorial-layout > .card { min-width: 0; margin-top: 0; overflow-wrap: anywhere; }
.tutorial-sidebar { position: sticky; top: 1rem; max-height: calc(100vh - 2rem); overflow: auto; padding: 1rem; }
#lesson-outline > summary { cursor: pointer; font-weight: 600; }
#lesson-contents details { margin-top: 1rem; }
#lesson-contents summary { cursor: pointer; color: var(--green-deep); font-weight: 600; line-height: 1.5; }
#lesson-contents ol { list-style: none; padding: .4rem 0 0; margin: 0; }
.lesson-link, .lesson-result-link {
  display: block; width: 100%; text-align: left; font: inherit;
  color: var(--green-deep); background: transparent; border: 0; border-radius: var(--radius-sm);
  cursor: pointer; padding: .55rem .65rem; line-height: 1.5;
}
.lesson-link { font-size: .87rem; }
.lesson-link:hover, .lesson-result-link:hover { background: var(--green-soft); }
.lesson-link[aria-current="step"] { background: var(--green-soft); box-shadow: inset 3px 0 var(--green); font-weight: 600; }
.tutorial-reader { padding: 1.5rem 2rem; }
.tutorial-reader h3 { margin: .35rem 0 1rem; font-size: 1.6rem; }
.tutorial-eyebrow { color: var(--ink-soft); font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; margin-bottom: .5rem; }
.lesson-section-intro { color: var(--ink-soft); }
.lesson-objective { padding: .35rem 0 .35rem .85rem; border-left: 3px solid var(--green); color: var(--ink-soft); }
.tutorial-prose, .lesson-section-intro, .lesson-objective, .tutorial-practice { max-width: 72ch; }
.tutorial-prose p { margin: .8rem 0; line-height: 1.8; }
.tutorial-reader .passage { scroll-margin-top: 1.5rem; padding-top: 1.5rem; margin-top: 1.5rem; }
.tutorial-reader .passage-heading { font-size: 1.2rem; }
#lesson-title { scroll-margin-top: 1.5rem; }
#lesson-contents .lesson-submodule { margin: .5rem 0 .5rem .6rem; padding-left: .5rem; border-left: 1px solid var(--line); }
#lesson-contents .lesson-submodule > summary { font-size: .87rem; font-weight: 400; }
.lesson-reference { margin-top: 1.25rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.lesson-reference > summary { cursor: pointer; color: var(--green-deep); line-height: 1.5; }
.lesson-exercise + .lesson-exercise { margin-top: 1.25rem; padding-top: .5rem; border-top: 1px solid var(--line); }
.tutorial-practice { padding: 1rem 1.25rem; background: var(--green-soft); border-radius: var(--radius-sm); margin-top: 2rem; }
.tutorial-practice h4 { margin: 0 0 .65rem; }
.tutorial-practice summary { cursor: pointer; font-weight: 600; padding: .5rem 0; }
.lesson-pagination { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.lesson-pagination button { min-width: 0; max-width: 42%; white-space: normal; overflow-wrap: anywhere; }
.lesson-pagination .field-note { text-align: center; }
.lesson-nav-short { display: none; }
.lesson-search-group { margin: 1.5rem 0; }
.lesson-result-link { font-weight: 600; border: 1px solid var(--line); }
.tutorial-book { margin-top: 1.5rem; }
@media (max-width: 960px) {
  .tutorial-layout { grid-template-columns: minmax(0, 1fr); }
  .tutorial-sidebar { position: static; max-height: none; }
  .tutorial-reader { padding: 1.1rem; }
  .lesson-pagination { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
  .lesson-pagination .field-note { grid-column: 1 / -1; order: -1; }
  .lesson-pagination button { width: 100%; max-width: none; }
}
@media (max-width: 480px) {
  /* The row has stopped paying for itself: the label beside the box leaves it
     too narrow to read a query in, so the label goes back above it. */
  .lesson-search { flex-direction: column; align-items: stretch; gap: 0; }
  .lesson-search label { margin-bottom: 0.4rem; }
  .lesson-nav-title { display: none; }
  .lesson-nav-short { display: inline; }
}
.lesson-filters { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 1.2rem; }
.lesson-chip {
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--green-deep);
  background: var(--green-soft);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  cursor: pointer;
}
.lesson-chip:hover { border-color: var(--green); }

/* A subject and the conditions beneath it: parivartana with its three kinds,
   the Sun with its strong and weak. */
.lesson-topic {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 1.1rem 1.2rem;
  margin-bottom: 1.1rem;
}
.lesson-subject {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.3rem;
  color: var(--green-deep);
  margin: 0;
}
.lesson-topic-name {
  margin: 0.1rem 0 1rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  color: var(--ink-faint);
}
.passage-subtopic {
  margin-left: 1rem;
  padding-left: 1rem;
  border-left: 2px solid var(--green-soft);
  border-top: none;
}
.passage-subtopic .passage-heading { font-size: 0.98rem; }

.passage {
  border-top: 1px solid var(--line-soft);
  padding-top: 1.1rem;
  margin-top: 1.1rem;
}
.passage:first-child { border-top: none; padding-top: 0; margin-top: 0; }
.passage-heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.05rem;
  color: var(--green-deep);
  margin: 0 0 0.2rem;
}
.passage-meta {
  margin: 0 0 0.7rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-faint);
}
.passage-points { margin: 0; padding-left: 1.4rem; max-width: 74ch; }
.passage-points li { margin-bottom: 0.45rem; }
.passage-note {
  margin: 0.7rem 0 0;
  font-size: 0.85rem;
  color: var(--ink-faint);
  max-width: 74ch;
}

/* ------------------------------------------------------------------ tables */


/* Ten columns need sideways room; overflow-y is pinned so the promotion
   described above cannot add a vertical bar here either. */
.table-scroll { overflow-x: auto; overflow-y: hidden; }

/* Shared table contract: row labels left, facts centred under their headings.
   Use scope="row" / "rowgroup" for labels, including cells spanning rows.
   Do not align td:first-child: beneath a rowspan it is a value, not column one.
   Table-specific rules below describe content, not a second table baseline. */
table {
  --table-cell-block: 0.6rem;
  --table-cell-inline: 0.5rem;
  width: 100%;
  border-collapse: collapse;
  font-size: 0.93rem;
}

th, td {
  text-align: center;
  vertical-align: middle;
  padding: var(--table-cell-block) var(--table-cell-inline);
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}

/* Only the first header row starts in column one; later rows may sit under
   grouped headings while the label above spans both rows. */
thead > tr:first-child > th:first-child,
th[scope="row"], th[scope="rowgroup"] { text-align: left; }
tbody th[scope="row"], tbody th[scope="rowgroup"] { color: var(--ink); }

/*
 * The label column ruled off from the facts, as the bhava table already rules
 * off its own: what a reader looks up on the left, every answer about it on
 * the right, and the line says which is which before a word is read. On the
 * label rather than on the cell beside it, so it travels with the column when
 * that column is stuck and the table scrolls under it.
 */
table.graha-table thead > tr:first-child > th:first-child,
table.graha-table tbody th[scope="row"],
.aspect-table thead > tr:first-child > th:first-child,
.aspect-table tbody th[scope="row"] { border-right: 1px solid var(--line); }

th {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  font-weight: 700;
}

tbody tr:last-child td, tbody tr:last-child th { border-bottom: none; }
tbody tr:hover { background: var(--row-hover); }
td.numeric, .longitude { font-family: var(--font-mono); font-size: 0.87rem; }
td .retro-flag, td.retro-flag, th .retro-flag { color: var(--retro); }
/* Vargottama is a fact about the graha rather than a verdict on it, so the flag
   is dimmed instead of being coloured good or bad. */
/* Each flag carries its own colour, so three tokens sitting together read as
   three different facts rather than as one label. Retrograde keeps the red it
   has everywhere else; the other two take hues the page does not otherwise use,
   so neither can be mistaken for chrome. */
.flag { font-weight: 600; font-size: 0.9em; }
.flag-r { color: var(--retro); }
.flag-v { color: var(--flag-vargottama); }
.flag-y { color: var(--flag-yogakaraka); }
/* Combustion is the odd one out: the other three mark something a graha has,
   this marks something done to it. So it is dimmed rather than given a fourth
   accent, which is also what a burnt graha is. */
.flag-c { color: var(--flag-combust); }
.flag-x { color: var(--flag-exchange); }
/*
 * Dignity, drawn on the chart beside the states. Exaltation takes the page's
 * green and debilitation the red it uses for a fault; moolatrikona sits with
 * exaltation, being the lesser of the two strong seats. Own sign has no mark:
 * a graha in its own sign is its own dispositor, which the card already says.
 */
.flag-dr { color: var(--green-deep); }
.flag-e { color: var(--green-deep); }
.flag-m { color: var(--green-deep); }
.flag-d { color: var(--retro); }

/* Compact condition groups share colours in HTML tables and SVG charts. */
.flag-group { white-space: nowrap; }
.flag-group.flag-bad { color: var(--retro); fill: var(--retro); }
.flag-group.flag-good { color: var(--green-deep); fill: var(--green-deep); }

/* Dignity words are read by scanning, not line by line, so the tiers carry
   weight and colour. Kept to the page's two hues rather than a red-to-green
   ramp: the scale is a ranking, not a verdict on the chart. Debilitation and a
   great enemy's sign take the red, the two ends of the ladder being the two a
   reader looks for first.

   Written without a td in front of them. They were td rules while a dignity was
   always a cell; the grid turned and its dignity became a span inside one, and
   every colour here stopped reaching it silently - the words rendered, in plain
   ink, and nothing failed. */
.dig { white-space: nowrap; }
.dig-exalted, .dig-moolatrikona { color: var(--green-deep); font-weight: 600; }
.dig-own { color: var(--green-deep); }
.dig-adhimitra { color: var(--green); }
.dig-mitra { color: var(--ink); }
.dig-sama { color: var(--ink-soft); }
.dig-shatru { color: var(--ink-faint); }
.dig-adhishatru { color: var(--retro); }
.dig-debilitated { color: var(--retro); font-weight: 600; }

/* Grahas across the top and divisions down the side, so a cell is one graha in
   one division: its sign over its dignity, two lines in one td rather than two
   rows to be kept in step. Seven columns however many divisions the scheme has,
   which is what took the horizontal scroll out. */
/* ------------------------------------------------------- shadbala grid */

/* Dense strength grids use the shared cells with a smaller row gap. */
#shadbala-table, #vargas-table { --table-cell-block: 0.4rem; }
#shadbala-table td.numeric { font-variant-numeric: tabular-nums; }
#shadbala-table .bala-group th[scope="row"] { padding-left: 2.2rem; }
.bala-toggle {
  position: absolute;
  left: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  display: inline-grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0.25rem;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  cursor: pointer;
}
.bala-toggle:hover { border-color: var(--green); color: var(--green-deep); }
.bala-toggle:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* The five parts of Sthana bala are recessive: they are what the row under them
   is made of, not six measures of equal standing, and reading them as equals is
   what makes the block look like eleven shares of Shadbala rather than six.

   Recessive against the shares, which is a step down from --ink-soft and not a
   step down from --ink: every th here starts at --ink-faint, so setting the
   parts to --ink-soft lifted them above the rows they belong to rather than
   sinking them below. Both step up by one instead: the shares to body ink and
   the parts to --ink-soft, which keeps the ordering and keeps both above 4.5:1
   in either mode, where --ink-faint is 2.8:1 on white. */
#shadbala-table tr.bala-part td { color: var(--ink-soft); }
/*
 * A figure the total below it does not include: the Sun's and Moon's cheshta
 * bala, which kala bala already counts. Shown in the soft ink the parts use,
 * with the help cursor the rest of the table gives a cell that explains itself
 * on hover, so it reads as deliberate rather than as a column that will not add.
 */
#shadbala-table td.not-counted { color: var(--ink-soft); cursor: help; }
#shadbala-table tr.bala-part th[scope="row"] {
  padding-left: 1.1rem;
  color: var(--ink-soft);
}

/* And the share opens the block rather than closing it, so the rule falls above
   the name rather than under the parts. A total below reads right while a column
   is being added up; this is a table being looked things up in, and eight
   indented rows with their parent underneath are eight rows a reader who lands
   among them cannot name. */
#shadbala-table tr.bala-head > * { border-top: 1px solid var(--line); }
#shadbala-table tr.bala-sum > * {
  border-top: 1px solid var(--line);
  font-weight: 600;
}

/* A verdict is stated once, in the Verdict row, in words. It was also tinting
   the graha's heading, which is the same fact in two places and in a colour that
   is spoken for: red is retrograde and debilitated everywhere else on the page,
   so a weak Mercury read as a retrograde one. The heading carries [R] and [C]
   instead, the same two flags the Vimsopaka grid puts there. */

#vargas-table td.varga-cell { vertical-align: top; }
#vargas-table .varga-sign,
#vargas-table .varga-dignity { display: block; white-space: nowrap; }
#vargas-table .varga-sign { color: var(--ink-soft); font-size: 0.92em; }
#vargas-table .varga-dignity { font-size: 0.93em; }
/* The three divisions the chosen scheme leans on hardest, picked out of the
   table. A column again now that the grahas are rows, so the rules that bracket
   it are vertical and the class is on the heading and on every cell under it
   rather than on one tr. Its own tint rather than --green-soft, which was
   darker than --line-soft and swallowed the rules running through it.

   This went silent when the table turned: the selector still named a row, no
   row carried the class any more, and the three columns lost their tint with
   nothing failing. A test now reads this block for the column form. */
#vargas-table th.varga-key,
#vargas-table td.varga-key {
  background: var(--varga-key);
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
}
#vargas-table thead th.varga-key { color: var(--green-deep); }

/* The totals close the table. Read as a figure rather than as another dignity,
   and banded by Parashara's own four readings rather than by a gradient nobody
   agreed on. Left at the body weight: the band already colours it. */
#vargas-table tr.varga-totals > * { border-top: 1px solid var(--line); }
#vargas-table td.vimsopaka {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  border-left: 1px solid var(--line-soft);
}
td.vimsopaka-strong { color: var(--green-deep); }
td.vimsopaka-mediocre { color: var(--ink); }
td.vimsopaka-some { color: var(--ink-soft); }
td.vimsopaka-poor { color: var(--retro); }

/* The strongest bhava, so the eye has somewhere to start on twelve rows
   that are otherwise alike. A tint and nothing else, as the settings
   comparison uses for the same job. */
tr.bhava-strongest td, tr.bhava-strongest th { background: var(--green-soft); }

/* Vimsopaka spans each graha over two rows; a hover band would light only
   half of that graha's values. */
#vargas-table tbody tr:hover { background: none; }

/* Weights are lighter than their labels. Vimsopaka column headings stack the
   weight underneath; Shadbala row labels keep their ceilings alongside. */
#vargas-table th .varga-weight,
#shadbala-table th .varga-weight {
  display: inline;
  font-weight: 400;
  font-size: 0.8rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  margin-left: 0.35rem;
}
#vargas-table thead th .varga-weight {
  display: block;
  margin-left: 0;
}
/* More air here than in the grid beside it. There the label is "D9"; here it is
   a word set in caps and letter-spaced, and 0.35rem against that read as the
   last syllable of it - SAPTAVARGAJA315. */
#shadbala-table th .varga-weight { margin-left: 0.6rem; }

/* The same measure's name in English, beside the Sanskrit rather than under it
   or behind a hover. Set as running text - not caps, not tracked - so the two
   do not read as one long name, and recessive so the row is still found by the
   Sanskrit a reader is scanning for. */
#shadbala-table th .measure-en {
  font-weight: 400;
  font-size: 0.78rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  margin-left: 0.55rem;
}

/* Table or charts. A view switch rather than a data control, so it reads as two
   buttons rather than as another dropdown beside the scheme. */
/*
 * The notes toggle rides the tab strip, pushed to its end. A view-option like
 * the Table/Charts pair so the two read as the same kind of control, but it
 * stands alone rather than in a switch: there is no second state to name,
 * only whether the explaining is wanted.
 */
.view-switch { display: inline-flex; margin-left: auto; border-radius: 999px;
  background: var(--paper-tint); padding: 0.15rem; }
.view-option {
  font: inherit;
  font-size: 0.8rem;
  border: none;
  background: none;
  color: var(--ink-soft);
  padding: 0.3rem 0.85rem;
  border-radius: 999px;
  cursor: pointer;
}
.view-option[aria-pressed="true"] {
  background: var(--surface);
  color: var(--green-deep);
  font-weight: 600;
  box-shadow: var(--shadow);
}

/* The two are compared graha by graha, so they sit side by side where there is
   room and stack where there is not. min-width: 0 lets a figure shrink to its
   track instead of holding the grid open at the svg's natural width.
 *
 * Written against :not([hidden]) because this container is what the Table and
 * Charts switch toggles. A bare "display: grid" is an author rule and beats the
 * display: none the browser gives [hidden], so the charts stayed on screen
 * under the table. */
#vargas-charts:not([hidden]) {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
  gap: 1.4rem 1.8rem;
  align-items: start;
}
.varga-figure { margin: 0; min-width: 0; }
/* Centred over its own plot. Ranged left, a title sat over the axis labels
   rather than over the bars, and with two figures side by side the two titles
   lined up with each other instead of each with the thing it names. */
.chart-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1rem;
  color: var(--green-deep);
  text-align: center;
  margin-bottom: 0.4rem;
}
.varga-chart { width: 100%; height: auto; display: block; }
/* Recessive: the grid is scaffolding, not data. */
.chart-grid { stroke: var(--line-soft); stroke-width: 1; }
.chart-base { stroke: var(--line); stroke-width: 1; }
.chart-name, .chart-value { font-family: var(--font); fill: var(--ink-faint); }
.chart-name { font-size: 12px; fill: var(--ink-soft); }
/* Values wear text tokens; the bar beside them carries the identity. */
.chart-value { font-size: 10px; font-variant-numeric: tabular-nums; }
.series-vimsopaka rect { fill: var(--chart-vimsopaka); }
.series-good rect { fill: var(--chart-good); }

.series-vargottama rect { fill: var(--chart-vargottama); }
.chart-legend { display: flex; gap: 1rem; margin-top: 0.4rem; font-size: 0.8rem;
  color: var(--ink-soft); }
.legend-item { display: inline-flex; align-items: center; gap: 0.35rem; }
.legend-swatch { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.legend-swatch.series-good { background: var(--chart-good); }
.legend-swatch.series-vargottama { background: var(--chart-vargottama); }
/* A facet carries one series, so its title is the identity and the fill has
   nothing to tell apart. One colour for all five. */
.series-mark rect { fill: var(--chart-vimsopaka); }

/* A threshold drawn across a plot. The shadbala chart's hundred per cent is the
   whole of what that chart says - a bar is above the line or below it - so it is
   a line a reader can see rather than a gridline they have to trust. */
.chart-rule {
  stroke: var(--ink-faint);
  stroke-width: 1;
  stroke-dasharray: 4 3;
}
.chart-rule-label {
  font-family: var(--font);
  font-size: 9px;
  fill: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* The vimsopaka score beside the chart's title: one number, so it is written
   and not drawn. Recessive against the graha's name, which is what the chart is
   of; the score is what that graha is worth, not a second title. */
/* The works a passage was read out of. Smaller and quieter than the note above
   it: a citation is there to be checked rather than read through. */
.passage-source {
  font-size: 0.78rem;
  color: var(--ink-faint);
  line-height: 1.55;
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--line-soft);
}

.chart-aside {
  font-weight: 400;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
/* Bars retain condition colours; table symbols and axis labels stay neutral.
   Each bar also has its own label, count and full name on hover. */
.chart-bar.mark-v rect { fill: var(--chart-vargottama); }
.chart-bar.mark-x rect { fill: var(--chart-exchange); }
.chart-bar.mark-y rect { fill: var(--chart-good); }
.chart-bar.mark-dr rect { fill: var(--chart-vimsopaka); }
.chart-bar.mark-e rect { fill: var(--chart-vimsopaka); }
.chart-bar.mark-m rect { fill: var(--chart-vimsopaka); }
.chart-bar.mark-d rect { fill: var(--retro); }
.chart-bar.mark-c rect { fill: var(--flag-combust); }
/* Seven graha charts form rows of four and three on wide screens, with fewer
   columns when needed to keep the eight mark counts readable. */
.varga-facets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(13rem, calc(25% - 0.9rem))), 1fr));
  gap: 0.9rem 1.2rem;
  grid-column: 1 / -1;
}
.varga-facets .varga-figure { min-width: 0; }
.varga-facets .chart-title { font-size: 0.86rem; }
/* One size for every note on the page. A note under a table is the table's small
   print and was being set at body size, so it read as the main text of the panel
   and the table read as an illustration of it. The flag key's descriptions join
   them: three sizes of secondary prose in one panel was two too many.

   No measure cap. A cap left a third of the card empty beside a note that is
   already short and already small, and empty space put there on purpose reads
   the same as empty space left by mistake. Each note is bounded by what holds
   it: the card for a panel note, its own column for a chart note, its grid
   track for a flag description, and those are the widths that were chosen for
   reading in the first place. */
.varga-note, .chart-note, .flag-key dd {
  font-size: 0.82rem;
  color: var(--ink-soft);
  line-height: 1.55;
}
.chart-note { margin: 0.5rem 0 0; }

/* The scheme picker sits above its table, labelled inline: it changes what the
   table is, not merely how it looks, so it reads as part of the panel. */
.varga-scheme-row { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.9rem; }
.varga-scheme-row label {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}
/*
 * The selects share the row rather than packing to the left of it. With three
 * of them - the Yogas tab has graha, chart and reference - a fixed width left
 * a third of the line empty and the controls bunched at one end.
 *
 * Bounded, so the rows carrying a single select do not stretch one control
 * across the page: at three they hit the container first and fill it, at one
 * the cap holds it to a readable width.
 */
.varga-scheme-row select { width: auto; flex: 1 1 15rem; max-width: 24rem; }
.yoga-filters,
.yoga-filter-group { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.yoga-filters { gap: 0.65rem 0.85rem; margin-bottom: 0.9rem; }
.yoga-filter-group { max-width: 100%; }
.yoga-filter-group label {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}
.yoga-filter-group select { width: auto; min-width: 0; max-width: 100%; }
/* Four flags, four entries, laid across the width rather than run together
   down a 60ch column. A key is looked up one flag at a time, not read through,
   and centred prose makes the reader find where each sentence starts. */
/* One line above the grid it explains, rather than a block under the charts:
   the six marks below are drawn as bare letters on purpose and have no hover. */
.varga-key {
  margin: 0 0 0.6rem;
  font-size: 0.78rem;
  line-height: 1.8;
  color: var(--ink-soft);
}
.flag-note {
  margin: 0 0 0.6rem;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--ink-soft);
}
/* Vimsopaka legend and row-heading marks stay neutral; cell groups use red and green. */
p.varga-key .flag { color: inherit; }
#vargas-table .flag:not(.flag-group) { color: inherit; }
.flag-key {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0.7rem 1.8rem;
  margin: 0 0 1rem;
  padding: 0;
}
.flag-key dt { color: var(--ink); font-weight: 600; margin-bottom: 0.1rem; }
.flag-key dd { margin: 0; }
/* A yogakaraka is worth spotting at a glance; the bare house numbers beside it
   are not, so only the named case is picked out. */
td.rulership, td.dispositor { color: var(--ink-soft); }
/* A pair of codes read as a pair, so the slash wants to land in the same place
   down the column. Mono does that; the sign names beside it are left alone. */
td.nak-lords { font-family: var(--font-mono); color: var(--ink-soft); }
/*
 * The two reading columns carry the width; the name and the grahas standing
 * with it are a word or two and were being handed a quarter of the table each,
 * which left an aspect sitting a long way from the graha it belongs to.
 */
.aspect-table th[scope="row"], .aspect-table td:first-of-type {
  width: 1%;
  white-space: nowrap;
}
.aspect-table td:not(:first-of-type) { width: 50%; }
.aspect-peer { white-space: nowrap; cursor: help; }
/* A named modern rule rather than a classical one, so it reads as an aside.
   It was a column and is now one entry among the classical ones, so the class
   rides on a span inside the cell instead of on the cell. */
.rao-aspects { color: var(--ink-soft); font-style: italic; }
tr td.rulership:not(:empty) { white-space: nowrap; }
table.graha-table .graha-group-end { border-right: 1px solid var(--line-soft); }
/* A long nakshatra should spend height rather than widening every graha row.
   The spaces give the browser the meaningful break: Uttara Bhadrapada becomes
   two words on two lines, without breaking either word apart. */
table.graha-table td.nakshatra-name {
  width: 6.5rem;
  max-width: 6.5rem;
  white-space: normal;
}

/* The strip of chart tabs inside the Grahas panel. Smaller than the panel tabs
   above it: it chooses between three tables at most and should not compete with
   the row that chooses between five panels. */
.tabs.graha-charts { margin-bottom: 0.6rem; }
.tabs.graha-charts .tab { font-size: 0.78rem; padding: 0.35rem 0.7rem; }
/* A name that spans its rows belongs to all of them and to none in particular,
   so it stays out of the hover band, which is one row wide. Letting it tint
   meant hovering the first row lit the name and the block with it while
   hovering the second lit neither, so one gesture drew two different shapes.
   True of the Vargas grid as well, which spans a name the same way; --surface
   is the card these tables sit on, in either mode. */
tbody tr:hover th[rowspan] { background: var(--surface); }

/* The name column stays put while the rest scrolls. Every one of these tables is
   wider than its card - eleven columns in the graha table, sixteen divisions in
   the grid - and a row read four columns to the right is a row whose subject has
   gone off the left edge.

   It carries its own background because a sticky cell is painted over by what
   scrolls under it otherwise, and its divider is a box-shadow rather than a
   border: with border-collapse a border on a sticky cell is owned by the
   collapsed edge and scrolls away with the neighbour. */
.table-scroll thead > tr:first-child > th:first-child,
.table-scroll tbody th[scope="row"],
.table-scroll tbody th[scope="rowgroup"],
.table-scroll tfoot th[scope="row"] {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
  box-shadow: 1px 0 0 var(--line-soft);
}
.table-scroll thead > tr:first-child > th:first-child { z-index: 2; }
/* And it joins the hover band, so the band does not start at the second column.
   Not where the name spans a group: that one is out of the band by design, a
   spanning cell belonging to all of its rows and to none. */
tbody tr:hover th[scope]:not([rowspan]) { background: var(--row-hover); }

td.strong-flag { color: var(--green-deep); font-weight: 600; }
td.weak-flag { color: var(--retro); font-weight: 600; }

tr.current-dasha { background: rgba(47, 143, 95, 0.11); }
tr.current-dasha th:first-child { color: var(--green-deep); font-weight: 700; }
.dasha-summary { margin: 0.7rem 0; }
/* A caption over a second table inside a panel the tab already named. */
.panel-caption {
  margin: 1.4rem 0 0.5rem;
  font-size: 0.95rem;
  font-weight: 600;
  text-align: center;
}
.dasha-table tbody th { text-transform: none; letter-spacing: 0; font-size: 0.8rem; }
/*
 * Birth details: what was entered on one side, what the reckoning makes of it
 * on the other. Two columns while the measure holds them, one when it does
 * not. The tables are the ones the printed report carries on its cover.
 */
.birth-details-grid {
  display: grid;
  /* min() rather than a bare minimum: a 22rem column cannot shrink, and on a
     narrow phone an unshrinkable column is a page that scrolls sideways. */
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
  gap: 0 2.5rem;
  align-items: start;
}
.birth-detail-table { width: 100%; }
/* A label rather than a column head: read as words, not as small capitals. */
.birth-detail-table tbody th[scope="row"] {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.8rem;
  font-weight: 600;
  text-align: left;
}
.yogini-sign { white-space: nowrap; }
.yogini-sign-change { display: block; font-size: 0.72rem; color: var(--ink-soft); }
.yogini-focus { font-weight: 600; }
/*
 * Bhava Bala is eleven columns in four groups, and without a mark between them
 * it reads as eleven of one thing. Where the bhava runs; then the lord and the
 * three shares that add to the total, the total among them because it is their
 * sum and not a fourth thing; then the rupas, which is that total over sixty
 * and the only figure here on a different scale. A rule opens each, so a
 * reader lands in the right band before reading the number.
 *
 * Everything but the bhava is centred, headings with it. These are short fixed
 * shapes - a sign, a degree, a two-letter graha, a figure - with none of the
 * ragged lengths that make a left edge worth keeping.
 */
#bhava-table th:nth-child(2),
#bhava-table td:nth-child(2),
#bhava-table th:nth-child(6),
#bhava-table td:nth-child(6),
#bhava-table th:nth-child(11),
#bhava-table td:nth-child(11) { border-left: 1px solid var(--line); }

/*
 * Sixteen division columns, so a reader following one down the seven grahas has
 * three characters to hold the eye on. A hairline between every column does it,
 * and the total takes the full rule, being the one figure here that is not a
 * varga. The padding comes in because the room is what the transpose spends.
 */
#vargas-table tbody td,
#vargas-table thead th + th { border-left: 1px solid var(--line-soft); }
#vargas-table .varga-total-head,
#vargas-table .varga-total-cell { border-left: 1px solid var(--line); }
/*
 * The room the transpose spends. Sixteen division columns where there were
 * seven graha ones, so the cells give back their padding and a step of type;
 * measured, that and the shorter totals heading are what bring the grid inside
 * its box instead of scrolling 231 pixels.
 *
 * The sign line is what binds, not the rung beside it: shortening Great Friend
 * to two letters saved nothing measurable, so the rungs keep words a reader can
 * read and the full ones stay on the hover.
 */
#vargas-table td.varga-cell {
  padding-left: 0.22rem;
  padding-right: 0.22rem;
  font-size: 0.68rem;
}
#vargas-table .varga-dignity { font-size: 0.9em; }
/*
 * Where a nested block begins and ends.
 *
 * Every row of this table is the same shape - a lord, two dates and a length -
 * so an antardasha is told from the mahadasha above it by one indent and
 * nothing else. Read down a column of seventeen of them and the indent stops
 * registering, and a reader cannot see which mahadasha they belong to or where
 * they stop.
 *
 * Three marks, none of them a colour: a guide rule down the indent, so a
 * nested run reads as hanging off its parent; a closing rule under the last of
 * them, so the block has a floor; and the open parent's own label in the deep
 * green, so the head of the block is visible from inside it. The guide is
 * drawn as a background gradient rather than a border because the border on
 * these cells is already the table's own row rule.
 */
/*
 * [scope="row"] is not decoration. The sticky first column sets `background`
 * as a shorthand, which resets background-image to none, and its selector
 * outranks a plain `th` here: the guides went silently invisible when that
 * rule arrived. These carry one more class than it does, and set only the
 * image, so the opaque colour the sticky column needs is left alone.
 */
/*
 * Drawn on a layer of its own rather than as the cell's background, because a
 * border always paints above the background it crosses: every row rule cut a
 * one-pixel notch through every guide, and the guides read as dashed. Sizing
 * could not fix that - the notch was the rule's own colour, not a gap.
 *
 * The cell is already sticky, so it positions this without needing anything
 * further, and the layer reaches a pixel past the bottom edge to cross the row
 * rule instead of stopping at it.
 */
/*
 * The layer is as wide as the guides it carries and no wider.
 *
 * It used to stretch across the whole cell, which costs nothing on screen or
 * in an ordinary print - but a printer told not to print background graphics
 * does not drop such a layer, it paints it white, and the layer then covered
 * the row it was decorating. Every antardasha and pratyantardasha vanished
 * from the printed report, leaving mahadasha headings over blank space.
 * Bounded to the indent, the worst that setting can do is whiten the strip
 * the guides live in, which is empty anyway.
 *
 * The offsets are relative to the layer's own left edge, so each is 0.9rem
 * less than the indent it marks.
 */
.dasha-table .dasha-level-1 th[scope="row"]::after,
.dasha-table .dasha-level-2 th[scope="row"]::after,
.dasha-table .dasha-level-3 th[scope="row"]::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: -1px;
  left: 0.9rem;
  width: 2px;
  pointer-events: none;
  background-repeat: no-repeat;
  background-size: 2px 100%;
  background-image: linear-gradient(var(--dasha-ad) 0 0);
  background-position: 0 0;
}
.dasha-table .dasha-level-2 th[scope="row"]::after {
  width: calc(1.9rem + 2px);
  background-image: linear-gradient(var(--dasha-ad) 0 0), linear-gradient(var(--dasha-pd) 0 0);
  background-position: 0 0, 1.9rem 0;
}
/* The sookshma keeps every guide above it and adds its own, so a row four
   deep still shows which antardasha and which pratyantardasha it hangs from. */
.dasha-table .dasha-level-3 th[scope="row"]::after {
  width: calc(3.8rem + 2px);
  background-image: linear-gradient(var(--dasha-ad) 0 0), linear-gradient(var(--dasha-pd) 0 0),
    linear-gradient(var(--dasha-sd) 0 0);
  background-position: 0 0, 1.9rem 0, 3.8rem 0;
}
/* And the label in the same hue as the rule that leads to it. */
.dasha-table .dasha-level-1 th .dasha-toggle,
.dasha-table .dasha-level-1 th .dasha-leaf { color: var(--dasha-ad); }
.dasha-table .dasha-level-2 th .dasha-toggle,
.dasha-table .dasha-level-2 th .dasha-leaf { color: var(--dasha-pd); }
.dasha-table .dasha-level-3 th .dasha-toggle,
.dasha-table .dasha-level-3 th .dasha-leaf { color: var(--dasha-sd); }
.dasha-table .dasha-level-0 th .dasha-toggle { font-weight: 600; }
/* The floor of an open block, and the last one needs no guide below it. */
.dasha-table tr.dasha-last th,
.dasha-table tr.dasha-last td { border-bottom-color: var(--line); }
/*
 * The floor of a block stops that block's guide and no other. A sookshma run
 * ending does not end the antardasha or the pratyantardasha it hangs from, and
 * those guides carry on to their own last rows; stopping all three here drew a
 * notch across guides whose blocks were still open.
 *
 * A guide that continues is sized to the whole cell and one that ends is
 * sized a pixel shorter, stopping where the row rule begins and letting it
 * read as the floor.
 */
.dasha-table tr.dasha-last.dasha-level-1 th[scope="row"]::after {
  background-size: 2px calc(100% - 1px);
}
.dasha-table tr.dasha-last.dasha-level-2 th[scope="row"]::after {
  background-size: 2px 100%, 2px calc(100% - 1px);
}
.dasha-table tr.dasha-last.dasha-level-3 th[scope="row"]::after {
  background-size: 2px 100%, 2px 100%, 2px calc(100% - 1px);
}
.dasha-table .dasha-level-0 .dasha-toggle[aria-expanded="true"] { color: var(--green-deep); }
/* A step a reader can see. 1.4rem against 0.7 read as an accident of type. */
.dasha-table .dasha-level-1 th { padding-left: 1.9rem; }
.dasha-table .dasha-level-2 th { padding-left: 3.8rem; }
.dasha-table .dasha-level-3 th { padding-left: 5.7rem; }
.dasha-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.dasha-toggle:hover { color: var(--green-deep); }
.dasha-arrow { width: 0.7rem; }
.dasha-leaf { padding-left: 1rem; }
.dasha-current-mark {
  display: inline-block;
  margin-left: 0.5rem;
  font-size: 0.65rem;
  font-weight: 400;
  color: var(--green-deep);
}

.ashtakavarga-grid tbody th, .ashtakavarga-grid tfoot th {
  text-transform: none; letter-spacing: 0; font-size: 0.8rem;
}
.ashtakavarga-grid .av-house {
  display: block; font-weight: 400; letter-spacing: 0; margin-top: 0.2rem;
}
.ashtakavarga-grid .av-lagna { background: var(--green-soft); }
.ashtakavarga-grid .av-total { color: var(--green-deep); font-weight: 600; }
.ashtakavarga-grid tfoot th, .ashtakavarga-grid tfoot td { border-top: 1px solid var(--line); }
.ashtakavarga-grid .av-sum { border-left: 1px solid var(--line-soft); }

/* Aligned to the foot of its grid cell, so the buttons sit on the same
   baseline as the inputs beside them rather than against their legends. */
.gochar-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  /*
   * End level with the inputs, not with the row. The row's floor is the line
   * the seconds hint holds open under the time fields, which is blank unless
   * that field has focus, so buttons aligned to the row hung a clear step
   * below the boxes they belong beside with nothing on screen to explain it.
   */
  margin: 0 0 var(--seconds-hint-line);
  align-self: end;
}
.gochar-zone-line { margin: 0.9rem 0; }
/*
 * Three equal tracks left the buttons at the left of a 402px cell with nearly
 * 300px of nothing after them, so the row ended on a gap. The controls take
 * the width they need and the two fields share what is left, which also gives
 * the date and time inputs 478px apiece instead of 402.
 *
 * Only where there is room for all three. Below that the rule is dropped and
 * the shared auto-fit grid collapses them as before.
 */
@media (min-width: 60rem) {
  #gochar-form .field-grid { grid-template-columns: 1fr 1fr max-content; }
}
#gochar-entries-form { margin-top: 1rem; }
#gochar-entries-form input { width: 6rem; }
#gochar-tabs .tab { padding-inline: 0.6rem; }
.gochar-controls label { margin: 0; }
/*
 * A range is one value, so it wears one label and keeps its two boxes
 * together when the row wraps. The two had a label each, and those two labels
 * came to 211px against 134px of boxes - more width spent naming the thing
 * than showing it, and the reason this row broke onto a second line. The date
 * and time fields on the birth form are built the same way: one legend, the
 * boxes under it, the parts named for a screen reader and not on screen.
 */
.gochar-years { display: flex; align-items: center; gap: 0.35rem; }
.gochar-years-dash { color: var(--ink-faint); }
/*
 * A field among fields. It was a white card 13px taller than the selects and
 * inputs either side of it, because it wrapped a full-height select in padding
 * of its own; centred in the row, it overhung both ways. The chips set the
 * height now and the padding makes up the rest, so it ends level with the row
 * and carries the same fill as everything typed or chosen in it.
 */
.gochar-divisions {
  position: relative; display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.35rem; max-width: 100%; padding: 0.3rem 0.35rem;
  min-height: var(--control-height);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--paper-tint);
}
.gochar-division-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.gochar-division-chip { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.15rem 0.45rem; min-height: 1.9rem; border-radius: 0.3rem; background: var(--green-soft); color: var(--ink); white-space: nowrap; }
.gochar-division-chip button { display: inline-flex; align-items: center; justify-content: center; padding: 0; width: 1.6rem; height: 1.6rem; min-height: 0; border: 0; border-radius: 0.25rem; background: transparent; color: inherit; font-size: 1.2rem; line-height: 1; cursor: pointer; }
.gochar-division-chip button:hover { background: var(--line-soft); }
.gochar-divisions .gochar-division-add { border: 0; background-color: transparent;
  height: auto; min-height: 0; padding-block: 0.2rem; font-size: 0.9rem; }
.gochar-divisions .gochar-division-add:disabled { opacity: 0.65; }
.gochar-lord-heading { display: block; white-space: nowrap; }
.chara-controls { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: end; margin: 1rem 0; }
.chara-controls label { margin: 0; max-width: 100%; }
.chara-controls select { width: auto; max-width: 100%; display: block; margin-top: 0.3rem; }
#conditional-table { min-width: 34rem; }
#conditional-table td { white-space: normal; }
#conditional-table td:last-child { white-space: nowrap; }
#conditional-table .conditional-rule-note { display: block; margin-top: 0.3rem; font-size: 0.75rem; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--ink-soft); }
#conditional-table tbody + tbody tr:first-child > * { border-top: 1px solid var(--line); }
.chara-timeline { max-height: 32rem; overflow: auto; container-type: inline-size; }
#chara-analysis-table {
  table-layout: fixed;
  --chara-fact-width: 9rem;
  min-width: 100%; width: calc(4.5rem + var(--chara-data-columns, 0) * var(--chara-fact-width));
}
#chara-analysis-table col { width: var(--chara-fact-width); }
#chara-analysis-table .chara-reference-col { width: 4.5rem; }
#chara-analysis-table th, #chara-analysis-table td { white-space: normal; overflow-wrap: anywhere; }
#chara-analysis-table tbody th {
  text-transform: none; letter-spacing: normal; font-size: 0.85rem; font-weight: 400;
}
#chara-analysis-table .chara-grid-head th {
  position: sticky; top: 0; z-index: 2; background: var(--surface);
  color: var(--ink-soft); font-size: 0.75rem;
}
#chara-analysis-table .chara-grid-head th:first-child { left: 0; z-index: 3; text-align: left; }
#chara-analysis-table tr[data-reference] td,
#chara-analysis-table .chara-grid-head th + th { border-left: 1px solid var(--line-soft); }
#chara-analysis-table .chara-band > th {
  position: static; box-shadow: none; background: var(--paper-tint);
  border-top: 2px solid var(--line); color: var(--ink); font-weight: 400;
}
#chara-analysis-table .chara-band.current-dasha > th { background: var(--green-soft); }
.chara-band-inner, .chara-footer-inner { position: sticky; left: 0.5rem; width: calc(100cqw - 1rem); }
.chara-band-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 1rem; }
.chara-period-info { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem; }
.chara-theme { margin-left: auto; text-align: right; }
.chara-period-dates { font-size: 0.8rem; color: var(--ink-soft); }
.chara-period-signs .link-button { font-size: inherit; }
.chara-karakas { margin-top: 0.4rem; line-height: 1.6; }
.chara-placements:not([hidden]) { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin-top: 0.4rem; }
.chara-grid-toggle { justify-content: center; min-width: 1.75rem; min-height: 1.75rem; margin-top: 0.2rem; }
.chara-condition { color: var(--ink-soft); }
.chara-block-footer > td { text-align: left; }
.chara-evidence { max-width: 42rem; margin-inline: auto; }
.chara-evidence > div + div, .chara-nature-line + .chara-nature-line { margin-top: 0.3rem; }
.chara-reference > .chara-argala { margin-top: 0.65rem; padding-top: 0.65rem; border-top: 1px solid var(--line-soft); }
.chara-planet { white-space: nowrap; }
.chara-argala-pair + .chara-argala-pair, .chara-argala-reverse, .chara-argala-trine { margin-top: 0.6rem; }
.chara-argala-status { color: var(--ink-soft); font-size: 0.75rem; }
.chara-context-details { margin-top: 0.65rem; }
.chara-context-details summary, .chara-more-context > summary { cursor: pointer; color: var(--ink-soft); font-size: 0.8rem; }
.chara-context-details[open] > summary { margin-bottom: 0.5rem; }
.gochar-controls input, .gochar-controls select { width: auto; max-width: 100%; }
.gochar-controls .hint { margin: 0; }
#gochar-form { margin-top: 1rem; }
#gochar-form input { min-width: 0; text-align: center; }
.gochar-grid tbody th { text-transform: none; letter-spacing: 0; font-size: 0.8rem; }
.gochar-active, .gochar-active th[scope] { background: var(--green-soft); }
.gochar-timeline { max-height: 32rem; overflow-x: auto; overflow-y: auto; }
.gochar-timeline thead th { position: sticky; top: 0; background: var(--surface); z-index: 2; }
.gochar-timeline thead th:first-child { z-index: 3; }
/* Keep each Jupiter/Saturn pair together; highlighting must preserve the bands. */
.gochar-periods tbody tr > * { background: var(--surface); }
.gochar-periods tbody tr.gochar-period-alternate > * { background: var(--paper-tint); }
.gochar-periods tbody tr.gochar-active > .gochar-period { box-shadow: inset 3px 0 var(--green); font-weight: 600; }
.gochar-periods .gochar-period-start > * { border-top: 1px solid var(--line); }
.gochar-periods .gochar-period { vertical-align: middle; white-space: normal; min-width: 12rem; max-width: 18rem; }
.gochar-periods tbody th[scope="row"] { position: static; white-space: nowrap; }
.gochar-periods thead th:nth-child(-n + 2),
.gochar-periods .gochar-period,
.gochar-periods tbody th[scope="row"] { text-align: left; }
.gochar-periods .gochar-contact[data-target="house"] { border-left: 1px solid var(--line); }

.technical { margin-top: 1.25rem; }
.technical dl { margin-top: 1rem; }

/* ------------------------------------------------------------------ footer */

.site-footer { color: var(--ink-faint); font-size: 0.85rem; text-align: center; padding-top: 2rem; }
.site-footer a { color: var(--ink-soft); }

/* ----------------------------------------------------------- legal page */

.legal-header a { color: inherit; text-decoration: none; }
.legal-page { padding-top: 1rem; }
.legal-card { max-width: 48rem; margin: 0 auto; }
.legal-card h2 { margin-bottom: 0; }
.legal-card h3 { margin-top: 1.8rem; }
.legal-card p { max-width: 68ch; }
.legal-back { margin-top: 2rem; }

/* ------------------------------------------------------- dark, if asked for */

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --paper: #121a16;
    --paper-tint: #1a231e;
    --surface: #18211c;
    --row-hover: #1d2822;
    --line: #2b3a32;
    --line-soft: #243029;

    --ink: #e6efe9;
    --ink-soft: #a6b8ae;
    --ink-faint: #7b8f84;

    --dropdown-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0h10L5 6z' fill='%237b8f84'/%3E%3C/svg%3E");

    --green: #58c08a;
    --green-deep: #7fd3a5;
    --green-soft: #21362b;
    --varga-key: #1e2f26;
    --retro: #e8867a;
    --queried: #e0a94f;
    /* Lift the flag hues off the dark background. */
    --flag-vargottama: #b69ae0;
    --flag-yogakaraka: #e0b563;
    --flag-combust: #8fa0ad;
    --flag-exchange: #6fb0f5;
    --chart-vimsopaka: #3d9468;
    --chart-good: #b8801f;
    --chart-vargottama: #8b72c8;
    --chart-exchange: #4a86d8;
    --dasha-ad: #6aa3e8;
    --dasha-pd: #d9a441;
    --dasha-sd: #5fc3bd;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.32);
    --shadow-lift: 0 2px 6px rgba(0, 0, 0, 0.35), 0 18px 40px rgba(0, 0, 0, 0.45);
  }
  body {
    background:
      radial-gradient(1100px 520px at 12% -8%, #17271e 0%, transparent 62%),
      radial-gradient(900px 460px at 92% 2%, #15231c 0%, transparent 58%),
      var(--paper);
  }
  input::placeholder { color: #5f7268; }
  input:hover, select:hover { border-color: #3b4f44; }
  input:focus, select:focus { box-shadow: 0 0 0 3px rgba(88, 192, 138, 0.18); }
  button.primary {
    color: #08150e;
    background: linear-gradient(180deg, #5cc48b 0%, #45a973 100%);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 16px rgba(0, 0, 0, 0.35);
  }
  .chart-card { background: linear-gradient(180deg, var(--surface) 0%, #1b241f 100%); }
  svg.kundli .frame, svg.kundli .cell { stroke: #3b5a49; }
  svg.kundli .first-house .cell { fill: rgba(88, 192, 138, 0.12); }
  .saved-card:hover { background: #21362b; border-color: var(--green); }
  tbody tr:hover { background: var(--row-hover); }
  tr.current-dasha { background: rgba(88, 192, 138, 0.13); }
}

/* ------------------------------------------------------------------- print */

.kundali-report { display: none; }

@media print {
  /*
   * 12mm was a screen designer's guess at a safe margin. 9mm clears the
   * unprintable edge of every common desktop printer and gives back about an
   * eighth of the sheet, which on a report this long is several pages.
   */
  /*
   * A shallower top margin: the running head sits at the top of the content
   * area, and 9mm above a single 8pt line was more air than the foot of the
   * page gets. The rule under it rises with it, and the space that was above
   * the text now sits below the rule, where it separates the head from the
   * page it heads.
   */
  @page { size: A4 landscape; margin: 5mm 9mm 9mm; }
  /*
   * Repeated on every sheet: Chromium paints a fixed element once per page in
   * paged media.
   *
   * Pinned to the top of the content area and left there. Lifting it into the
   * page margin, by a negative top or a negative margin, makes Chromium drop
   * it to the foot of the sheet instead - so the only reliable place is here.
   */
  .kundali-report .report-sheet {
    width: 100%;
    border-collapse: collapse;
    /*
     * Fixed, so the wrapper takes the width of the page and not the width of
     * the widest thing inside it. Sized to content it grew past the sheet and
     * Chromium scaled every page down to fit.
     */
    table-layout: fixed;
  }
  /* The birth line takes what it needs; the site takes what is left. */
  .kundali-report .report-runner-birth { width: 70%; }
  .kundali-report .report-sheet > tbody > tr > td { padding: 0; border: 0; }
  /*
   * A rule under the running head, dividing it from the page it heads, and
   * room under the rule so the page does not begin against it. The rule is
   * drawn on the box inside the cell so that the cell's own padding falls
   * below it; a border on the cell would sit at the padding's outer edge with
   * the content hard against it.
   *
   * Reckoned from what arrives first, which is a chart card's own border: two
   * lines a millimetre apart read as a pair of rules rather than as a heading
   * and the page beneath it.
   */
  .kundali-report .report-sheet > thead > tr > th { border-bottom: 0; }
  .kundali-report .report-runner-line { border-bottom: 1px solid #ddd; padding-bottom: 1.5mm; }
  .kundali-report .report-runner {
    padding: 0 0 2.5mm;
    border: 0;
    text-align: right;
    font-weight: 400;
    font-size: 8pt;
    color: #555;
    white-space: nowrap;
  }
  :root {
    --paper: #fff; --paper-tint: #fff; --surface: #fff;
    --ink: #111; --ink-soft: #444; --ink-faint: #666;
    --line: #ccc; --line-soft: #ddd;
    --green: #1f6b47; --green-deep: #145336; --green-soft: #eef7f1;
    --varga-key: #f5faf7;
    --retro: #96382c;
    --shadow: none; --shadow-lift: none;
  }
  body { background: #fff; color: #111; padding: 0; }
  .card { border: 1px solid #ddd; box-shadow: none; background: #fff; break-inside: avoid; }
  .chart-card { background: #fff; }
  .tabs, .site-footer, .result-actions, .options, .save-feedback, .account-controls { display: none; }
  #panel-add, #panel-saved, #panel-lesson, #panel-settings, #panel-billing, #panel-admin, .empty-chart { display: none; }
  .chart-controls, .chart-actions { display: none; }
  body.kundali-printing > :not(.kundali-report) { display: none !important; }
  .kundali-report { display: block; font-size: 9pt; line-height: 1.4; }
  .kundali-report [hidden] { display: none !important; }
  /*
   * A hover and a click are nothing on paper. The notes are printed as they
   * stand on screen, so the sentences that ask for a gesture are taken out of
   * the printed copy rather than left telling a reader to do the impossible.
   */
  .screen-only { display: none !important; }
  .kundali-report .card { padding: 2.5mm; margin-bottom: 2.5mm; break-inside: auto; }
  /* Less frame around the diagram, so more of the column is the diagram. */
  .kundali-report .chart-card { break-inside: avoid; padding: 1.5mm; }
  /*
   * Headings are kept with what follows them, so the heading, the sub-heading,
   * the table head and its first row move as one block. Six millimetres above
   * each of two stacked headings made that block tall enough to be pushed off
   * the foot of a page that had room for it, leaving the summary page ending
   * at the charts with a third of it blank.
   */
  .kundali-report .report-section-heading { font-size: 12pt; margin: 3.5mm 0 1.5mm; break-after: avoid; }
  .kundali-report [role="tabpanel"] > [role="tabpanel"] > .report-section-heading { font-size: 11pt; }
  .kundali-report .table-scroll, .kundali-report .gochar-timeline,
  .kundali-report .chara-timeline { max-height: none; overflow: visible; }
  /*
   * Columns sized to their contents, not to an equal share of the page.
   *
   * Fixed layout gave "Role" the same width as "Longitude", so the wide column
   * wrapped every value onto two lines and the table stood at twice the height
   * it needed, while the narrow ones ran half empty. It also broke headings
   * mid-word - LONGITU DE, VIMBAL A - because overflow-wrap: anywhere will
   * break inside a word rather than overflow a column too narrow to hold it.
   *
   * Auto layout, headings that refuse to wrap, and breaking inside a word only
   * where a cell genuinely cannot fit it otherwise.
   */
  /*
   * The report keeps its colours whether or not the dialog was told to print
   * background graphics, which is a box nobody ticks and most readers never
   * see. Its fills are not decoration: the key column of the ashtakavarga,
   * the period running now, the band that separates a label from its value.
   * Without this the dasha guides still printed - a gradient counts as an
   * image to a recent Chrome - while every flat fill vanished, which is a
   * worse thing than either having them or not.
   *
   * Scoped to the printed clone, so nothing else on the page is affected.
   */
  .kundali-report, .kundali-report * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .kundali-report table { width: 100%; min-width: 0; max-width: 100%; table-layout: auto; font-size: 8pt; }
  .kundali-report th, .kundali-report td { padding: 0.7mm 1mm; min-width: 0; max-width: none;
    white-space: normal; overflow-wrap: break-word; position: static; font-size: inherit;
    line-height: 1.25; }
  /*
   * Headings on one line. This is what keeps the columns honest: a heading
   * that may not wrap claims the width it needs, the data under it then fits
   * on one line too, and the table stands at its true height. Letting them
   * wrap instead cost fourteen pages, because every column the browser could
   * narrow it did, and hundreds of data rows grew to two and three lines.
   *
   * The exception is a table with so many columns that one line of heading
   * each cannot fit the sheet, which would print with its last column cut off
   * the edge. Those are tagged by the report builder and allowed to wrap.
   */
  .kundali-report th { white-space: nowrap; }
  .kundali-report .report-wide th { white-space: normal; }
  /*
   * And they must fit, not merely overflow tidily. A table wider than the
   * printable area does not get clipped by Chromium: it shrinks the whole
   * sheet to fit, so one over-wide table in a 46-page report silently reduced
   * every other page from 8pt to about 7pt. Two did exactly that here.
   *
   * These two are allowed to break inside a word, which is what lets a column
   * narrow past its longest word, and set a step smaller. The combination is
   * ugly in the two tables that need it and keeps the other forty-four pages
   * at the size they were designed for.
   */
  .kundali-report .report-wide { font-size: 7pt; }
  .kundali-report .report-wide th, .kundali-report .report-wide td {
    overflow-wrap: anywhere; font-size: inherit; }
  .kundali-report thead { display: table-header-group; position: static; }
  .kundali-report tr { break-inside: avoid; }
  /*
   * Two columns for the long narrow tables, tagged by the report builder.
   * The rule for the heading is the point of the gap: columns that touch read
   * as one table and the eye runs across rows that are not rows.
   */
  /*
   * The expanded chara context is a stack of one-line facts - which benefics
   * occupy, which aspect, the argala and its obstruction - each sentence a
   * few words long against the full width of a landscape sheet. Three columns
   * read the same and take a third of the paper. A block is never split down
   * the middle, so a heading keeps the lines that belong to it.
   */
  /*
   * Yoga detail, set for paper. On screen each is a panel with room to
   * breathe: a heading, a line of prose, a gap, the next heading. Those gaps
   * are in rem, so at 8pt they stayed the size they were at 16px and a yoga
   * whose answer is four words - "Depends on involved houses" - took the
   * better part of an inch to say it.
   *
   * The sticky positioning and the container-query width go with them. Both
   * exist to hold the panel on screen while a wide table is scrolled sideways,
   * and nothing scrolls on paper.
   */
  .kundali-report .yoga-detail > td { padding: 1.5mm 2mm; }
  .kundali-report .yoga-detail-content { position: static; width: auto; left: auto; }
  .kundali-report .yoga-detail-head { margin-bottom: 0.4mm; font-size: 8.5pt; }
  .kundali-report .yoga-detail-text, .kundali-report .yoga-detail-points {
    margin-bottom: 1.5mm; line-height: 1.3; font-size: 8pt; }
  .kundali-report .yoga-detail-points li { margin-bottom: 0.6mm; }
  .kundali-report .yoga-detail-note + .yoga-detail-head { margin-top: 2mm; }
  .kundali-report .chara-more-context { column-count: 3; column-gap: 8mm; }
  .kundali-report .chara-context-details { break-inside: avoid; }
  /*
   * Two, not three. Three fits on the sheet and saves a further page, but at
   * that width every date wraps onto a second line, so the rows grow by as
   * much as the extra column saves and the table is harder to read for it.
   */
  .kundali-report .report-columns { column-count: 2; column-gap: 10mm; }
  .kundali-report .report-columns table { break-inside: auto; }
  .kundali-report summary { font-size: 10pt; font-weight: 600; break-after: avoid; }
  .kundali-report details { margin: 3mm 0; }
  .kundali-report .report-note { white-space: pre-wrap; }
  .kundali-report .report-scope { color: #444; font-size: 8pt; }
  /*
   * Two charts on the summary page, centred, and no wider than they were as
   * one of three. Two tracks rather than three so the pair sits in the middle
   * of the sheet instead of against the left edge with a gap where the third
   * used to be, which reads as a chart that failed to draw. Held to a third of
   * the width each: letting them take half a landscape sheet would have spent
   * on size what dropping the third chart just saved.
   */
  /*
   * The summary page: the two charts, then the rashi's own graha table under
   * them, in the half sheet that was blank below the charts.
   *
   * The table is brought here rather than left in the Grahas section, because
   * what the page then holds is the rashi, the navamsa, and what the rashi
   * contains. It takes the full width and stands at the same size as every
   * other table in the report: beside the charts it would have had to be set
   * two sizes down to fit, and the same table in two sizes reads as a mistake
   * rather than a choice.
   */
  /*
   * Whose chart this is, on a page of its own, and nothing else on it. It is
   * the one thing in the report that is about the person rather than the
   * reckoning, and it opens the document the way a title page does.
   */
  .kundali-report .result-header { break-after: page; }
  /*
   * Unless the details follow it, in which case the cover ends after those:
   * the break belongs to the last thing on the sheet, not to the card.
   */
  .kundali-report .result-header:has(+ .report-cover-row),
  /*
   * At the top left of the cover, where an invocation goes, and sized so it
   * reads as a mark on a letterhead rather than as the subject of the page.
   */
  /*
   * Two columns under the name card: the invocation and the reckoning on the
   * left, what was entered on the right, which is how a printed kundali sets
   * its first sheet.
   */
  .kundali-report .report-cover-row {
    /*
     * The invocation has the top half of the sheet to itself, centred, and
     * what was entered and what the reckoning makes of it fill the bottom
     * half. The name captions the first of those tables: the one place it is
     * printed, since the running head gives the birth on every page.
     */
    display: block;
    break-after: page;
  }
  .kundali-report .report-cover-left {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 88mm;
  }
  .kundali-report .report-cover-name {
    margin: 0 0 3mm;
    font-size: 15pt;
  }
  /* The separator the title row draws on screen, which this is not. */
  .kundali-report .report-cover-name .identity-detail::before {
    content: ' \00b7\0020';
    color: var(--ink-faint);
  }
  .kundali-report .report-cover-name .identity-detail {
    font-weight: 400;
    font-size: 0.72em;
    color: var(--ink-soft);
  }
  /*
   * The two tables side by side across the foot of the sheet. Stacked they
   * ran past it, and beside the invocation they left the lower half empty.
   */
  .kundali-report .report-cover-right {
    display: grid;
    /*
     * Each table as wide as it needs rather than half a sheet each: stretched
     * across the full measure, a label and its value stood 90mm apart with
     * nothing between them.
     */
    grid-template-columns: repeat(2, minmax(0, 118mm));
    justify-content: space-between;
    align-items: start;
    margin-top: 5mm;
  }
  /* Half a sheet is nineteen rows and a caption, which wants a tight row. */
  .kundali-report .report-cover-right th,
  .kundali-report .report-cover-right td { padding: 0.35mm 1mm; }
  /*
   * The name is the caption of the first table rather than a heading over it:
   * the table is plainly the birth details, and a word saying so would push
   * the one place the name is printed off the top of the column.
   */
  .kundali-report .report-cover-right .birth-detail:first-child .panel-caption {
    margin: 0 0 3mm;
    font-size: 15pt;
  }
  .kundali-report .report-cover-right .birth-detail + .birth-detail .panel-caption {
    margin-top: 0;
  }
  .kundali-report .report-invocation {
    display: block;
    /*
     * As large as half a sheet holds: the drawing is four parts wide to three
     * high, so the height is what binds and the width follows it.
     */
    max-height: 88mm;
    max-width: 120mm;
    width: auto;
    height: auto;
  }
  .kundali-report .birth-detail-table { width: 100%; }
  .kundali-report .birth-detail-table th[scope="row"] {
    text-transform: none;
    letter-spacing: 0;
    width: 42%;
    /*
     * The label is set larger than the value on screen, where it is a column
     * of its own. On paper that one rule was setting the height of every row
     * on the cover - a line box a third taller than the type in it - and
     * costing the invocation a quarter of its half of the sheet.
     */
    font-size: inherit;
  }
  .kundali-report .birth-detail-table td { text-align: right; }


  .kundali-report .report-summary-row { display: block; margin-bottom: 2.5mm; }

  /*
   * The grahas named the same way everywhere. Row and column headings are set
   * in capitals across the app, which suits SUN and MERCURY but turns the
   * printed abbreviations into ME and SU - the one place they would not match
   * the two letters the charts, the dasha and the ashtakavarga all use.
   */
  .kundali-report table.graha-table tbody th,
  .kundali-report #report-shadbala-table thead th + th {
    text-transform: none; letter-spacing: 0;
  }

  /*
   * A dasha row in one column: the graha against the left, the date against
   * the right, with whatever the column has spare between them. A date column
   * of its own was a narrow strip that broke "05 Jun 1967" over three lines
   * while the column beside it held "Sa" and an inch of nothing.
   */
  .kundali-report .dasha-line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0 4mm;
  }
  .kundali-report .dasha-when { white-space: nowrap; font-weight: 400; }
  /* The parent's span, under the name whose span it is. */
  .kundali-report .dasha-span {
    display: block;
    font-weight: 400;
    font-size: 0.9em;
    color: #555;
    white-space: nowrap;
  }
  /*
   * Three columns of it. Three only became possible once the grid beside it
   * was narrowed and the table folded to one column with the grahas in two
   * letters; before that it fragmented and the dates were sliced down the
   * middle - "18 Jul 2022" printing as "1 Ju 20". Four columns bring that
   * straight back: a column is 30mm at four and a date needs 34.
   */
  .kundali-report .report-dasha-column .table-scroll { column-count: 3; column-gap: 8mm; }
  /*
   * And the rows give back a sixth of a millimetre each, which is a line a
   * column: at 120 years of life the tenth mahadasha put three lines on a
   * sheet of their own. Padding only. These rows are set a step larger than
   * the rest of the report, which is how they are wanted.
   */
  .kundali-report .report-dasha-column th,
  .kundali-report .report-dasha-column td {
    padding-top: 0.55mm;
    padding-bottom: 0.55mm;
  }
  .kundali-report .report-dasha-column table { break-inside: auto; }
  /* A heading for a table stacked under another needs no space above it. */
  .kundali-report .report-stacked-heading { margin-top: 2mm; }
  /*
   * A share of a share, shown the way a subperiod is shown in the dasha beside
   * it: indented under its measure with a guide running down to it, so Uchcha
   * and Saptavargaja read as parts of Sthana rather than as six more measures.
   *
   * The indent is restated at the tighter rule's weight below: the padding set
   * for the whole block outranks it otherwise, and the guide then runs through
   * the first letter of every name it is meant to sit beside.
   */
  /*
   * Set from the slack beside it rather than by eye. Twenty-seven rows at the
   * report's usual spacing ran three past the foot, which left the rupas, the
   * rank and the verdict stranded on the next sheet under a repeated head -
   * the three rows a reader actually looks for. So the rows take every
   * millimetre the dasha column leaves and not one more: that column stands
   * about 187mm, this one about 174mm at this spacing, and the usual 0.7mm and
   * 1.25 would put it past 200mm. Loosening it further means losing a measure,
   * not gaining air.
   */
  .kundali-report .report-reading-row #report-shadbala-table th,
  .kundali-report .report-reading-row #report-shadbala-table td {
    padding: 0.5mm 1mm;
    line-height: 1.2;
  }
  .kundali-report .report-reading-row #report-shadbala-table .bala-sub th[scope="row"] {
    position: relative;
    padding-left: 5mm;
    font-weight: 400;
  }
  .kundali-report .bala-sub th[scope="row"]::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: -1px;
    left: 2mm;
    width: 2px;
    background: var(--dasha-ad, #3f6f9f);
    pointer-events: none;
  }
  .kundali-report .report-reading-row {
    display: grid;
    /*
     * The grid on the right takes the width it needs - fourteen columns have a
     * floor below which they cannot be squeezed - and the dasha takes what is
     * left. Halving the sheet instead pushed the grid five pixels over the
     * edge, and Chromium answers that by shrinking every page.
     */
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0 10mm;
    align-items: start;
    break-before: page;
  }
  .kundali-report .chart-pair {
    /*
     * Three across, each taking a third of whatever the sheet actually has.
     * Fixed millimetre columns left a strip unused down the right; a fraction
     * of the free space cannot, and the charts grow to fill it because the
     * diagram is square and sized from its container's width.
     */
    /*
     * As large as the sheet allows, which is set by height rather than width.
     * The charts, the graha table and its key have to finish on one page; past
     * about 90mm they do not, and the key - the thing that explains the table -
     * is pushed onto the next sheet away from it. 88mm leaves a couple of
     * millimetres for a chart whose rows run taller than this one's.
     */
    grid-template-columns: repeat(3, 88mm);
    justify-content: center;
    gap: 3mm;
    margin-bottom: 2.5mm;
  }
  /*
   * A heading that opens a page takes no space above it: the rule under the
   * running head is already the line it sits below, and the margin meant for
   * separating one section from the last one is separating it from nothing.
   */
  /*
   * Bhava Bala over Vimsopaka Bala, each the full width, on a sheet of their
   * own. The gap is the only thing holding them apart: both are grids of
   * figures of the same weight, and touching they read as one table whose
   * rows change meaning halfway down.
   */
  .kundali-report .report-strength-row { break-before: page; }
  .kundali-report .report-strength-row > * + * { margin-top: 4mm; }
  /*
   * Both tables a step up, because the page has it to give. Horizontally they
   * are stretched rather than squeezed - the bhava columns want 200mm of the
   * 279mm they are given and the varga grid 207mm - and vertically the sheet
   * was a sixth empty under them.
   *
   * The varga grid is tagged wide and set a step smaller by the rule that
   * keeps a seventeen-column table from running off the sheet. On this page it
   * has no need of that step, so it comes up to the report's own 8pt. Half a
   * point more apiece puts the pair at 185mm of the 188 the sheet has, which
   * is the slack a chart with one more line of wrap needs, so the grid stops
   * there and the bhava table takes the half point.
   */
  .kundali-report .report-strength-row table,
  .kundali-report .report-transit-page #report-vargas-table { font-size: 8.5pt; }
  .kundali-report .report-transit-page .report-wide { font-size: 8pt; }
  /*
   * A caption stays with the table it names, and the kakshya table moves
   * whole: the Gochar sheet carries three tables about one moment, and the
   * last of them was printing a heading and one row before the page turned.
   */
  .kundali-report .panel-caption { break-after: avoid; }
  /*
   * The gochara reading and the kakshya reading beside each other, under the
   * positions both are taken from.
   */
  /*
   * One chart, so it takes a third of the sheet rather than the whole of it:
   * the tables under it are the reading, and the diagram is where a reader
   * checks a house against what they have just read.
   */
  /*
   * The sixteen divisions, three to a row and two rows to a sheet. The
   * diagram is square and carries a caption, so a row at the full third of
   * the sheet stands 95mm and only one of them fits; at 78mm the row is 85mm
   * and the sixteen take three sheets rather than six.
   */
  .kundali-report .report-varga-charts { break-before: page; }
  .kundali-report .report-varga-charts:not(:last-child) { break-after: page; }
  .kundali-report .report-varga-charts > .report-section-heading { margin-top: 0; }
  .kundali-report .report-varga-grid {
    grid-template-columns: repeat(3, 78mm);
    justify-content: center;
    gap: 3mm;
  }
  .kundali-report .report-gochar-head > * { margin-top: 0; }
  .kundali-report .report-gochar-head .report-scope { margin-bottom: 1.5mm; }
  .kundali-report .report-gochar-head {
    display: grid;
    grid-template-columns: 82mm minmax(0, 1fr);
    gap: 0 8mm;
    align-items: start;
  }
  .kundali-report .report-gochar-chart {
    grid-template-columns: 82mm;
    margin-bottom: 0;
  }
  .kundali-report .report-gochar-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 8mm;
    align-items: start;
  }
  .kundali-report .report-gochar-pair .panel-caption { margin-top: 2.5mm; }
  /*
   * Three tables and a chart on one sheet, and room to spare under them once
   * they are placed: the transit table is nine rows and the two under it six
   * and seven, so the rows take the sheet's slack rather than leaving 20mm
   * of nothing at its foot.
   */
  .kundali-report #report-panel-gochar-current th,
  .kundali-report #report-panel-gochar-current td {
    padding-top: 1.2mm;
    padding-bottom: 1.2mm;
  }
  .kundali-report .table-scroll:has(#report-gochar-kakshya),
  .kundali-report .table-scroll:has(#report-gochar-phala) { break-inside: avoid; }

  /*
   * Yogini and chara, folded to a line each and flowed down five columns, the
   * way the Vimshottari is flowed down three in the half sheet it shares with
   * the ashtakavarga. Five because this page has the whole width: a line is a
   * name and a date, about fifty millimetres of the fifty-one a fifth of the
   * sheet gives it, and four left a finger's width of nothing in every column.
   */
  /*
   * The sheet after the dashas starts a sheet of its own. The Grahas section
   * was beginning in whatever was left at the foot of the last dasha page: a
   * heading and the top two rows of a wide table under six columns of periods.
   */
  /*
   * The break after is for whatever follows, so the last sheet does not ask
   * for one: as the final block, the dasha page's break-after printed an
   * empty sheet with nothing on it but the running head.
   */
  .kundali-report .report-dasha-page { break-before: page; }
  .kundali-report .report-dasha-page:not(:last-child) { break-after: page; }
  /*
   * Sade Sati closes the sequence and the Grahas section starts a sheet of
   * its own after it, for the reason the dashas do: a heading and two rows of
   * a wide table under a timeline is neither one section nor the other.
   */
  /*
   * The two of them on one sheet, and the Sade Sati flowed down three strips
   * rather than two: twenty-five phases of a lifetime, each a phase, a sign
   * and two dates, which is narrow once the times are off them.
   */
  .kundali-report .report-transit-page { break-before: page; }
  .kundali-report .report-transit-page:not(:last-child) { break-after: page; }
  .kundali-report .report-transit-page > [role="tabpanel"] + [role="tabpanel"],
  .kundali-report .report-transit-page > * + * {
    margin-top: 2.5mm;
  }
  /*
   * The residential strengths and the friendship grid side by side: one is
   * nine rows of six figures and the other a seven by seven of two letters,
   * and neither is worth a band of its own.
   */
  .kundali-report .report-friendship-row {
    display: grid;
    /*
     * A measured share rather than min-content. Sized to its narrowest the
     * grid was a block of two-letter words with no air in it, while the five
     * columns of strengths beside it had the rest of the sheet to spread
     * over; sized to its widest it took the line under it laid out flat,
     * which is a sentence, and squeezed the strengths instead.
     */
    grid-template-columns: minmax(0, 1fr) 72mm;
    gap: 0 8mm;
    /*
     * Stretched, not started: the strengths are nine rows and the grid seven,
     * and left to their own heights the two ended a centimetre apart with the
     * white between them reading as a mistake. The grid takes the difference
     * into its rows.
     */
    align-items: stretch;
  }
  .kundali-report .report-friendship-row > :last-child {
    display: flex;
    flex-direction: column;
  }
  .kundali-report .report-friendship-row > :last-child .table-scroll {
    flex: 1 1 auto;
  }
  .kundali-report .report-friendship-row .friendship-grid { height: 100%; }
  .kundali-report .report-friendship-row > * { margin-top: 0; }
  .kundali-report .report-friendship-row .report-section-heading { margin-top: 0; }
  /*
   * Sized to its own content. At the report's full width the grid handed the
   * slack to its first column, which put the row of graha names a hand's
   * breadth left of the figures and over the table beside it.
   */
  .kundali-report .friendship-grid { width: 100%; text-align: center; }
  .kundali-report .friendship-grid th,
  .kundali-report .friendship-grid td {
    padding-top: 1.1mm;
    padding-bottom: 1.1mm;
  }
  .kundali-report .friendship-grid th[scope="row"] { text-align: left; }
  .kundali-report .friendship-grid th { text-transform: none; letter-spacing: 0; }
  .kundali-report .report-sade-page .table-scroll {
    column-count: 3;
    column-gap: 8mm;
  }
  .kundali-report .report-sade-page table { break-inside: auto; }
  /*
   * The phase heads the row, which is what sets it bold and tints it, and it
   * reads as a name rather than as a heading: the row headers in this report
   * are otherwise set in caps and letter-spaced.
   */
  .kundali-report .report-sade-page tbody th[scope="row"] {
    text-transform: none;
    letter-spacing: 0;
    text-align: left;
  }
  /*
   * The three columns measured out rather than negotiated. Left to itself the
   * browser gave the period whatever it asked for and broke "Panoti 8th" in
   * two beside it; held to one line instead, a single clipped period -
   * "Before 15 Aug 1990 - 15 Dec 1990" - made the table wider than the sheet
   * and shrank every other page with it. Fixed shares settle both.
   */
  .kundali-report .report-sade-page table { table-layout: fixed; }
  /*
   * Set tight, because the sheet it shares is set by the table above it:
   * Bhava Bala's twelve rows and these forty-five phases come to 184mm of a
   * page that holds 180, and the three millimetres are a row apiece here.
   */
  .kundali-report .report-sade-page tbody th,
  .kundali-report .report-sade-page tbody td {
    padding-top: 0.3mm;
    padding-bottom: 0.3mm;
  }

  .kundali-report .report-sade-page th:nth-child(1) { width: 26%; }
  .kundali-report .report-sade-page th:nth-child(2) { width: 52%; }
  .kundali-report .report-sade-page th:nth-child(3) { width: 22%; }
  /*
   * The annual chart at the head of the year it belongs to, a little smaller
   * than the natal pair: the summary table and the reading under it have to
   * reach the same sheet, and the charts are a reference for those rather
   * than the thing the page is about.
   */
  .kundali-report .report-varsha-charts {
    /*
     * As large as the column beside them allows. The positions table wants
     * 119.6mm at its narrowest and the sheet is 279mm, so 73mm apiece leaves
     * it the 122mm it has to have and spends everything else on the charts.
     * They cost no height either: the facts and the positions stacked beside
     * them stand taller than the diagrams do.
     */
    grid-template-columns: repeat(2, 73mm);
    margin-bottom: 0;
  }
  .kundali-report .report-varsha-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0 8mm;
    align-items: start;
  }
  /* The first row of the table level with the top of the diagrams beside it. */
  .kundali-report .report-varsha-facts > :first-child { margin-top: 0; }
  /*
   * Headings in this column may wrap. A heading that may not is what sets a
   * column's floor, and "Aspect to annual Lagna" over "Candidate roles" put
   * the Varshesha table's floor at 150mm in a column with 122mm. The rows
   * under them are a word or two apiece and were never the problem.
   */
  .kundali-report .report-varsha-facts th { white-space: normal; }
  .kundali-report .report-varsha-lord { margin-top: 2.5mm; }
  /*
   * The aspects under the diagrams, headings wrapping as they do beside, and
   * the column no wider than the pair above it: sized to its own content it
   * took the width the table would have liked and left the facts and the
   * positions wrapping every other line.
   */
  .kundali-report .report-varsha-left { width: 157mm; }
  /*
   * The mudda rows tight, as the dasha sheets are. Ten periods of a lord and
   * two dates is a list rather than a table of figures, and at the report's
   * usual cell padding it pushed the aspects, which are read against it, onto
   * the sheet after the charts they belong to.
   */
  .kundali-report .report-varsha-left #report-varsha-dasha th,
  .kundali-report .report-varsha-left #report-varsha-dasha td {
    padding-top: 0.3mm;
    padding-bottom: 0.3mm;
    line-height: 1.15;
  }
  .kundali-report .report-varsha-left > [role="tabpanel"] { margin-top: 1.5mm; }
  /*
   * Ten lines of a lord and a date: two columns of five rather than one
   * column down a sheet that is 149mm wide here.
   */
  .kundali-report .report-varsha-left #report-varsha-dasha { width: auto; }
  .kundali-report .report-varsha-band .report-varsha-span {
    margin: 0 0 1mm;
    text-align: center;
    font-size: 0.88em;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-faint);
  }
  .kundali-report .report-varsha-band #report-varsha-dasha {
    text-align: center;
    table-layout: fixed;
  }
  .kundali-report .report-varsha-band { margin-top: 2mm; }
  /* A band ends where the next lord's name begins it again. */
  .kundali-report .report-varsha-band #report-varsha-dasha .mudda-dates td {
    padding-bottom: 1.6mm;
  }
  /*
   * The line sits in the row's heading cell, which this report sets in caps
   * and letter-spaces, so the date beside the lord printed "24 MAR 2026".
   * The lord keeps the weight a heading has; nothing else about it does.
   */
  .kundali-report .report-varsha-band #report-varsha-dasha th {
    text-transform: none;
    letter-spacing: 0;
    text-align: center;
  }
  .kundali-report .report-varsha-left th { white-space: normal; }
  /*
   * Rows set open rather than tight. The aspects were a step down and packed
   * to share the column with the charts and the dasha; with the notes and
   * the Panchavargiya working off the sheet there is room to read them at the
   * report's own size, and room for every table on the page to breathe.
   */
  .kundali-report .report-varsha-row th,
  .kundali-report .report-varsha-row td {
    padding-top: 0.9mm;
    padding-bottom: 0.9mm;
  }
  /*
   * The aspects at the report's own size with their rows well open. They were
   * set small and tight to share the column with the dasha; the dasha spans
   * the foot of the sheet now and the pairs are named in two letters, so the
   * table is both shorter and narrower than the column it sits in.
   */
  .kundali-report .report-varsha-left #report-varsha-aspects th,
  .kundali-report .report-varsha-left #report-varsha-aspects td {
    padding-top: 1.4mm;
    padding-bottom: 1.4mm;
  }
  /*
   * Nine narrow columns, so the pairs sit upright over them and the figures
   * under each are centred rather than ranged against a rule that is not
   * there. A step smaller, as the varga grid is, for the same reason.
   */
  .kundali-report .report-varsha-aspect-grid { font-size: 7pt; text-align: center; }
  .kundali-report .report-varsha-aspect-grid th[scope="row"] { text-align: left; }
  .kundali-report .report-varsha-aspect-grid th,
  .kundali-report .report-varsha-aspect-grid td { padding: 0.6mm 0.8mm; }
  .kundali-report .report-varsha-lord .report-section-heading { margin-top: 0; }
  /*
   * Each dasha opens a sheet. Following straight on, a table began wherever
   * the one before it left off, and a table that starts half a page down has
   * half a page less to fill its columns with: padanadhamsa fits five columns
   * from the top of a sheet and overran them from the middle of one, leaving
   * its note on the page after the last of its periods.
   */
  .kundali-report .report-dasha-page > [role="tabpanel"] { break-before: page; }
  .kundali-report .report-dasha-page .table-scroll {
    column-count: 5;
    column-gap: 6mm;
  }
  .kundali-report .report-dasha-page table { break-inside: auto; }
  /*
   * The note in the flow, so it finishes the table in whichever column the
   * table finishes in - here the fifth of the last sheet, which the periods
   * left empty. Set to span all five instead, it has to clear a column box
   * that is a whole page tall, and was printing on the sheet after the table
   * it explains.
   */
  .kundali-report .report-dasha-page .table-scroll > .hint {
    margin: 3mm 0 0;
    break-inside: avoid;
  }
  /*
   * On this page, at the size of every other table on the sheet. The period
   * column is set a step larger on screen, in rem, and that rule outranks the
   * one that puts the report at 8pt - so these rows print at 9.6pt, and at
   * that size a line wants 53mm of a column with 51. A table whose content
   * will not fit its column does not wrap: it runs past the right edge of the
   * paper, taking the last column's dates with it, and Chromium answers by
   * shrinking every other page to match.
   *
   * Only here. The Vimshottari keeps the larger setting it was built with: it
   * has three columns of a half sheet rather than five of a whole one, and
   * the room to spend on them.
   */
  .kundali-report .report-dasha-page .dasha-table tbody th { font-size: inherit; }
  /*
   * Tighter, where tighter buys a sheet. A line is a name and a date, and the
   * padding meant to hold cells apart in a table of figures is holding apart
   * what reads as a list: at the report's usual 0.7mm a padanadhamsa wanted
   * 5.72 columns of the five a sheet has, and spent a second sheet on the
   * 0.72. A yogini wants 8.59 and is a two-sheet table at either setting, so
   * it keeps the spacing the rest of the report has.
   */
  .kundali-report .report-dasha-tight .dasha-table tbody th {
    padding-top: 0.3mm;
    padding-bottom: 0.3mm;
    line-height: 1.15;
  }
  /* The span and the progression under a name, set closer to it. */
  .kundali-report .report-dasha-tight .dasha-span { line-height: 1.15; }
  /*
   * Six columns, for a table narrow enough to hold them. Chara names signs in
   * three letters, so its longest line is "MD Sag" against a date and it
   * stands 42.9mm wide where a yogini's "MD Bhramari Ma" stands 55.4mm. A
   * sixth of the sheet is 42.3mm at this gutter, which the line gives back by
   * closing the space between the name and the date: that gap is only ever
   * seen at the line's narrowest, and narrowest is where it decides whether
   * the table fits a sheet.
   */
  .kundali-report .report-dasha-six .table-scroll {
    column-count: 6;
    column-gap: 5mm;
  }
  .kundali-report .report-dasha-six .dasha-line { gap: 0 2mm; }
  /*
   * A note in a narrow column is held open by its longest word: padanadhamsa
   * ends on "365.25875-day year", which is wider than a sixth of the sheet
   * and was setting the width of the whole table.
   */
  .kundali-report .report-dasha-six .hint { overflow-wrap: anywhere; }
  /*
   * Padanadhamsa is the short one: sixteen mahadashas where chara has twenty
   * and yogini thirty-two, so at six columns it was filling three quarters of
   * a sheet and leaving the rest white. Its rows take back most of the
   * padding the other two give up, which spreads them over the page it has.
   */
  .kundali-report .report-dasha-roomy .dasha-table tbody th {
    padding-top: 0.6mm;
    padding-bottom: 0.6mm;
  }
  /*
   * The nakshatra a mahadasha progresses from, its lord and the sign it
   * reaches: a second line under the span, set like it and no heavier - it
   * belongs to the period above it rather than announcing a new one.
   */
  .kundali-report .dasha-where { font-size: 0.85em; white-space: normal; }
  /*
   * Each cell of the varga grid is two lines - the sign, and under it the rung
   * the score was made of. The rules that stack them hang off the table's id,
   * and the report renames every id it copies, so on paper the two spans ran
   * together inline: "ScoGE", with a cell wrapping wherever the width ran out
   * and the rows ragged for it. Hung off the classes here, which the copy
   * keeps.
   */
  .kundali-report .varga-cell { vertical-align: top; }
  .kundali-report .varga-sign,
  .kundali-report .varga-dignity { display: block; white-space: nowrap; }
  .kundali-report .varga-sign { color: var(--ink-soft); font-size: 0.92em; }
  .kundali-report .varga-dignity { font-size: 0.9em; }
  .kundali-report .report-strength-row > [role="tabpanel"] + [role="tabpanel"] {
    margin-top: 3mm;
  }
  .kundali-report .report-summary-row .report-section-heading,
  .kundali-report .report-strength-row > :first-child .report-section-heading,
  .kundali-report .report-transit-page > :first-child .report-section-heading,
  .kundali-report .report-dasha-page > [role="tabpanel"] .report-section-heading,
  .kundali-report .report-subperiods > .report-section-heading,
  .kundali-report .report-transit-page > :first-child .report-section-heading,
  .kundali-report .report-varsha-page > .report-section-heading,
  .kundali-report .report-reading-row .report-section-heading { margin-top: 0; }
  /*
   * The key is four lines explaining one table; split across a page break,
   * half of it explains a table the reader has already turned past. Kept
   * whole, and set tight enough that it still lands under its own table
   * rather than being pushed over on its own.
   */
  .kundali-report .table-key {
    break-inside: avoid;
    margin-top: 1mm;
    gap: 0 4mm;
    font-size: 7.5pt;
    line-height: 1.25;
  }
  svg.kundli text { fill: #111; }
  svg.kundli .frame, svg.kundli .cell { stroke: #9bbcab; }
  svg.kundli .frame-outer { stroke: #1f6b47; }
  tbody tr:hover { background: none; }
  th, td { border-bottom: 1px solid #ddd; }
}

/*
 * The four lords of the birth, above the strength table. Data rather than
 * prose, so it is set apart from the note under the table: the label recedes
 * and the graha carries the weight, and the four wrap rather than scroll on a
 * narrow screen.
 */
.lords-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.4rem;
  margin: 0 0 0.75rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.lords-strip:empty { display: none; }
.lords-strip b { color: var(--ink); font-weight: 600; }

/*
 * What a graha rules and what looks at it, on its hover card. A label that
 * recedes and a value that does not, so the two read as a pair rather than as
 * another sentence.
 */
.graha-card-fact {
  margin: 0.15rem 0 0;
  font-size: 0.82rem;
  color: var(--ink);
}
.graha-card-fact-label { color: var(--ink-soft); }

/*
 * The yogas as a table. The Graha column is the point of it: whose yoga this
 * is, as against who takes part, which is the next column along. A dash there
 * is an answer and not a gap, so it is set in the muted ink rather than hidden.
 */
.yoga-table th[scope="row"] {
  font-weight: 600;
  white-space: nowrap;
  vertical-align: top;
  padding-right: 1rem;
}
/*
 * "Viewed" and "Counted" carry their "from" on the row beneath, so the rule
 * between the header rows would cut one label in half. The frequency heading
 * keeps its rule: it spans two columns that measure different things, and the
 * line is what says so.
 */
.yoga-table .yoga-splithead { border-bottom: 0; padding-bottom: 0; }
/* The label on a note that names a thing rather than explaining one. */
.yoga-detail-label { font-weight: 600; }
.yoga-table .yoga-subhead {
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
}
.yoga-table td { vertical-align: top; }
.yoga-table .yoga-part { color: var(--ink-soft); font-size: 0.85rem; }
.yoga-table .yoga-graha { font-weight: 600; white-space: nowrap; text-transform: none; letter-spacing: normal; }
.yoga-table .yoga-graha.is-shared { font-weight: 400; color: var(--ink-soft); }
/*
 * The yoga's own name now carries the row, so it is the sticky column. It holds
 * the expand button, which must stay reachable, and the longest names run to
 * "Shankha yoga (BPHS: movable)" - so it wraps rather than pushing every other
 * column off the right.
 */
.yoga-table th.yoga-name[scope="row"] {
  /*
   * The base `th` is a column heading: 0.68rem, uppercase, tracked out. That
   * suited the old first column, which held a list of grahas as a label, and
   * is wrong for the yoga's own name, which is what the row is. It takes the
   * table's own size, so the name reads as large as the figures beside it
   * rather than a quarter smaller.
   */
  font-size: inherit;
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
  min-width: 9rem;
  max-width: 14rem;
}
/* The three that answer "what is this about", kept out of the prose weight. */
.yoga-table .yoga-kind,
.yoga-table .yoga-affects { white-space: nowrap; }
@media (max-width: 640px) {
  /* Narrower than the screen, so the sticky column cannot cover the rest. */
  .yoga-table th.yoga-name[scope="row"] { min-width: 7rem; max-width: 9rem; }
}
.yoga-table .yoga-effect { font-weight: 600; }
/*
 * The classification wraps, and has to say so.
 *
 * Cells inherit white-space: nowrap from the table, and a max-width cannot
 * bind text that will not break: a ten-area list measured 1181px inside a
 * 288px cell and ran straight across Tendency and the frequencies, printing
 * "Good" and "7.8%" on top of the words. The width was already stated here and
 * was being ignored for want of this one line.
 */
.yoga-table .yoga-classification {
  min-width: 10rem;
  max-width: 18rem;
  white-space: normal;
}
.yoga-family { display: block; font-weight: 600; }
.yoga-areas { display: block; font-size: 0.85rem; color: var(--ink-soft); }
.yoga-table .yoga-effect-good { color: var(--green-deep); }
.yoga-table .yoga-effect-bad { color: var(--red); }
.yoga-table .yoga-effect-mixed { color: var(--ink-soft); }
.yoga-table .yoga-summary { margin: 0; }
.yoga-table .yoga-reasons {
  margin: 0.3rem 0 0;
  padding-left: 1.1rem;
  color: var(--ink-soft);
  font-size: 0.85rem;
}
.yoga-table .yoga-houses { display: block; margin-top: 0.2rem; }

/* The house frame a yoga was detected from, between its name and frequency. */
.graha-card-whose {
  flex: none;
  min-width: 8.5rem;
  text-align: right;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-soft);
}
/* Worked calculations stay beside the strength they explain. */
.strength-workings { margin-top: 1.25rem; }
.strength-workings > summary { cursor: pointer; padding: .65rem 0; font-weight: 600; }
.strength-workings .varga-scheme-row { margin-top: .75rem; }
.strength-workings table { min-width: 42rem; }
.strength-workings tfoot { font-weight: 600; }
#book-study > .varga-scheme-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr);
  gap: .5rem .75rem;
}
#book-study > .varga-scheme-row select { width: 100%; max-width: none; }
#book-comparison table { min-width: 56rem; table-layout: fixed; }
#book-comparison th, #book-comparison td { white-space: normal; }
#book-comparison th:nth-child(1) { width: 10%; }
#book-comparison th:nth-child(2) { width: 31%; }
#book-comparison th:nth-child(3), #book-comparison th:nth-child(4),
#book-comparison th:nth-child(5) { width: 10%; }
#book-comparison th:nth-child(6) { width: 29%; }
.book-chart { max-width: 440px; margin: 1rem auto; }
.book-chart svg { width: 100%; height: auto; }
@media (max-width: 640px) {
  #book-study > .varga-scheme-row { grid-template-columns: minmax(0, 1fr); }
}

/* Annual horoscope controls wrap without widening the page. */
.varsha-controls { display: flex; flex-wrap: wrap; align-items: end; gap: 0.8rem; margin: 1rem 0; }
.varsha-controls[hidden] { display: none; }
.varsha-controls label { display: flex; flex-direction: column; gap: 0.35rem; max-width: 100%; }
.varsha-controls input, .varsha-controls select { max-width: 100%; }
.varsha-charts { max-width: 980px; margin-top: 1.2rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
#panel-varshaphal .table-scroll { margin-bottom: 1.25rem; }
#panel-varshaphal th, #panel-varshaphal td { white-space: nowrap; }
#panel-varshaphal h4 { margin-top: 1.5rem; }

/* Screen navigation has three levels: sections, view pills, and view switches. */
@media screen {
  #result .tabs.subtabs:not(.table-tabs) {
    border-bottom: 0; gap: 0.4rem; align-items: center;
  }
  #result .tabs.subtabs:not(.table-tabs) .tab {
    border: 1px solid var(--line); border-radius: 999px;
    margin-bottom: 0; padding: 0.35rem 0.8rem; font-size: 0.82rem;
  }
  #result .tabs.subtabs:not(.table-tabs) .tab[aria-selected="true"] {
    background: var(--green-soft); border-color: var(--green); color: var(--green-deep);
  }
  /* The guard matters: a pane switch belonging to a hidden table is hidden
     by the attribute, and display would outrank it. */
  #result .tabs.subtabs.graha-panes:not([hidden]) {
    display: inline-flex; background: var(--paper-tint); border-radius: var(--radius-sm);
    padding: 0.2rem; gap: 0;
  }
  #result .tabs.subtabs.graha-panes .tab { border-color: transparent; border-radius: var(--radius-sm); }
  .panel-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem; margin-bottom: 0.9rem; }
  .panel-toolbar > .tabs { flex: 1 1 auto; margin-bottom: 0; }
  .panel-toolbar .view-switch { margin-left: auto; flex-shrink: 0; }
  .panel-toolbar .view-switch[hidden] { display: none; }
  .view-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-left: auto; }
  .view-actions button { padding: 0.4rem 0.65rem; font-size: 0.82rem; }
  .gochar-transit-row > .gochar-transit-tabs { flex: 1 1 0; min-width: 0; margin: 0; }
  .gochar-transit-actions { margin-left: auto; }
  #gochar-add-transit { font-size: 1.2rem; min-width: 2.5rem; min-height: 2.5rem; padding: 0.25rem; }
  .dasha-clock { display: inline-flex; align-items: center; gap: 0.65rem; }
  .dasha-reading-toggle { display: none; }
  .table-scroll[data-more-right="true"], #result .tabs[data-more-right="true"] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
  }
  .table-scroll:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
  .result-actions .icon-button { width: auto; height: auto; min-height: 2.5rem; gap: 0.35rem; padding: 0.4rem 0.55rem; }
  .action-label { font-size: 0.75rem; font-weight: 500; }
  .yoga-filters { align-items: end; }
  .yoga-filter-group { display: flex; flex-direction: column; align-items: stretch; gap: 0.3rem; }
  .yoga-filter-group label { font-size: 0.75rem; color: var(--ink-soft); }
  .milan-preview { max-width: 48rem; margin: 1.25rem auto; }
  .milan-attributes { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.8rem 1.2rem; }
  .milan-attributes dt { font-size: 0.8rem; color: var(--ink-soft); }
  .milan-attributes dd { margin: 0.25rem 0 0; }
  .milan-attributes > div:last-child { grid-column: 1 / -1; }
  .tutorial-reader[aria-busy="true"] > :not(.lesson-loading) { display: none; }
  .lesson-loading { margin: 0; padding: 2rem 0; color: var(--ink-soft); }
  .lesson-loading::before { content: ''; display: block; width: 40%; height: 0.5rem; background: var(--line); border-radius: 1rem; margin-bottom: 1rem; }
  @media (max-width: 600px) {
    #result .tabs { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; max-width: 100%; padding-bottom: 0.4rem; }
    #result .tabs .tab { flex-shrink: 0; }
    #result .table-tabs .tab { padding: 0.6rem 0.8rem; }
    .panel-toolbar > .tabs { flex-basis: 0; min-width: 0; }
    /* The four actions carry their words now, which is wider than the name
       column could give up: on a narrow screen they take a line of their
       own rather than squeezing the name to nothing, which left it reading
       one letter per line. */
    .result-title-row { grid-template-columns: minmax(0, 1fr); }
    .result-actions { flex-wrap: wrap; justify-content: flex-start; }
    .dasha-readings[data-has-current="true"]:not([data-expanded="true"]) .dasha-reading:not([data-current="true"]) { display: none; }
    .dasha-reading-toggle:not([hidden]) { display: inline-block; margin-bottom: 0.5rem; }
    .dasha-when-search { gap: 0.5rem; }
    .dasha-when-search .date-grid { grid-template-columns: 3rem 3rem 4rem; }
    .dasha-when-search .time-grid { grid-template-columns: repeat(3, 3rem auto); }
  }
}
.yoga-relative-grade { display: block; font-size: 0.75em; font-weight: 400; color: var(--ink-soft); white-space: normal; }
