/* How a day looks (its fill and edge, and today's and a day below $0's) is in stylesheet.css's tokens (--DAY_FILL and
   the rest): the date picker draws its days the same way. */

/* Static hit area (keeps the original bounds) */
.elastic-table td {
  position: relative;
  padding: 0;
  vertical-align: top;
  text-align: left;
  font-size: 1vmin;
  transition: transform 0.25s ease-in-out, box-shadow 0.25s ease-in-out, z-index 0.25s ease-in-out;
  z-index: 1;
}

/* Table Layout: as wide as its card */
.elastic-table {
  width: 100%;
  height: 60vh;
  table-layout: fixed;

  /* Separate days, with a small gap between them */
  border-collapse: separate;
  border-spacing: clamp(2px, 0.55vw, 7px);

  /* Prevent text highlighting while drag-zooming on PC */
  user-select: none;
  -webkit-user-select: none;
}

/* The actual element that scales, zooms, and tilts: a small glass tile with a faint blue edge (drawn inside it, so it
   takes no room) */
.cell-content {
  pointer-events: none;
  background: var(--DAY_FILL);
  box-shadow: inset 0 0 0 1px var(--DAY_EDGE);
  border-radius: var(--DAY_RADIUS);
  padding: 4px;
  box-sizing: border-box;

  /* Entries never wrap: a day cuts them off at its edges (a zoomed day lets them run past, over the dimmed page) */
  white-space: nowrap;
  overflow: hidden;

  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column; /* One element per line (date, system lines, entries) */
  align-items: flex-start;
  justify-content: flex-start;
  /* No will-change here: it kept a graphics layer for each of the 28 days at all times, and phones (Safari
     especially) ran out of room for them, leaving parts of days unpainted until the calendar was touched.
     A zoom gets its layer while it runs. */
  transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
}

/* A day's lines keep their height (more lines than fit are cut off at its bottom, or scroll when it's zoomed on a phone) */
.cell-content > * {
  flex-shrink: 0;
}

/* A day that isn't zoomed (or magnified) cuts a line too long for it short, with "..." at its edge */
.elastic-table td:not(.is-editing):not(.is-magnified) .cell-content > :not(.cell-action-btn):not(.historyDate) {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/*
 * PC Mouse Interaction (Magnifying Glass Effect): holding the mouse down on a day magnifies it
 * (Process Budget.js adds .is-magnified)
 */
/* 1. Base hover effect (keeps z-index clean on PC) */
@media (hover: hover) and (pointer: fine) {
  .elastic-table td:hover {
    z-index: 10;
  }
}

/* 2. The held day stays above the ones next to it, magnified with all of its text showing */
.elastic-table td.is-magnified {
  z-index: 20;
}

.elastic-table td.is-magnified .cell-content {
  transform: scale(2);
  transition: transform 0.1s ease-out;
  overflow: visible;
  user-select: none; /* Prevents text highlighting while dragging */
  -webkit-user-select: none;
}

/* Edit mode: Stays zoomed until clicked outside. It gets a shadow that follows its round corners, so it pops out. */
.elastic-table td.is-editing {
  transform: scale(2); /* Zoom level */
  z-index: 60; /* Above the other days and the dimmed page (.dayZoomBackdrop) */
  position: relative;
  transition: transform 0.4s cubic-bezier(0.33, 0, 0.2, 1);
  filter: drop-shadow(0 8px 12px rgba(var(--SHADE_RGB), 0.6));
}

/* A zoomed day on a computer is as tall as its lines (at least as tall as the day), and its entries run past its
   edges */
.elastic-table td.is-editing .cell-content {
  overflow: visible;
}

.elastic-table td.is-editing:not(.is-fullZoom) .cell-content {
  height: auto;
  min-height: 100%;
}

/* A zoomed or magnified day is solid, so the page behind doesn't show through its entries (today still glows, and a
   day below $0 stays red: see Calendar days below) */
.elastic-table td.is-editing:not(.is-fullZoom) .cell-content,
.elastic-table td.is-magnified .cell-content {
  background: var(--DAY_SOLID);
}

/* How much a day is zoomed: 2 on a computer (scaled, so the v inside divides by it to stay the same size on
   screen); on phones, whatever fills the screen (Process Budget.js sets it) */
.elastic-table td.is-editing,
.elastic-table td.is-magnified {
  --zoom: 2;
}

/* Phones: a tapped day is as wide as most of the screen and as tall as its lines (Process Budget.js works out where and
   how big), over a dimmed page. It's laid out at that size (its spacing and corners times --zoom, its text times
   --zoomText) instead of scaled up from the tiny day, so its text is sharp. Its content is as big as the screen (--viewW
   by --viewH, moved to the screen's top left corner; taller, for a day taller than the screen, which the page scrolls to,
   since it's part of the page), and draws the day itself (::before) at --dayX, --dayY, --dayW by --dayH, with its lines
   starting inside it: a line too long for the screen ends in "..." at the screen's edge (tapping it shows it whole).
   Only Process Budget.js's grow and shrink animations scale it. */
.elastic-table td.is-editing.is-fullZoom {
  transform: none;
  z-index: 60;
  background-color: transparent;
  box-shadow: none;
  filter: none; /* The day it draws has its own shadow (a filter here would shade every line too) */
  transition: none;
}

.elastic-table td.is-editing.is-fullZoom .cell-content {
  z-index: 0; /* The day (::before) goes under its lines, not under the page */
  width: var(--viewW, 100vw);
  height: var(--viewH, 100vh);
  /* The lines start inside the day; under the last one, room for the space under the day */
  padding:
    calc(var(--dayY, 0px) + 4px * var(--zoomText, 1))
    calc(4px * var(--zoomText, 1))
    calc(var(--viewH, 100vh) - var(--dayY, 0px) - var(--dayH, 0px))
    calc(var(--dayX, 0px) + 4px * var(--zoomText, 1));
  font-size: calc(1em * var(--zoomText, var(--zoom, 1)));
  overflow: visible; /* (It doesn't scroll: the page does, which it's part of) */
  pointer-events: auto; /* It covers the screen now, so taps land on it (Process Budget.js closes it for ones beside the day) */
  background: none;
  box-shadow: none;
  border-radius: 0;
}

.elastic-table td.is-editing.is-fullZoom .cell-content::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: var(--dayY, 0px);
  left: var(--dayX, 0px);
  width: var(--dayW, 100%);
  height: var(--dayH, 100%);
  /* Like every day, but solid here, so the page behind doesn't show through its entries. Its edge is an inset
     shadow, not a border, so the v stays in the very corner. */
  background: var(--DAY_SOLID);
  border-radius: calc(var(--DAY_RADIUS) * var(--zoom, 1));
  box-shadow: inset 0 0 0 1px rgba(var(--GLOW_LIGHT_RGB), 0.4), 0 2px 12px rgba(var(--SHADE_RGB), 0.7);
}

/* Its lines stop at the screen's right edge (with a little room, and the content's padding after them), ending in "..."
   when they're longer, so nothing in it reaches past the screen sideways */
.elastic-table td.is-editing.is-fullZoom .cell-content > :not(.cell-action-btn) {
  max-width: calc(var(--viewW, 100vw) - var(--dayX, 0px) - 8px * var(--zoomText, 1) - 2vw);
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Today keeps its glow, and red days stay red, when zoomed */
.elastic-table td.is-editing.is-fullZoom.isToday .cell-content::before {
  background: var(--GLOW_FILL), var(--DAY_SOLID);
  box-shadow: inset 0 0 0 1px var(--GLOW_EDGE), 0 0 14px rgba(var(--GLOW_RGB), 0.65);
}

.elastic-table td.is-editing.is-fullZoom.isNegative .cell-content::before {
  background: var(--NEGATIVE_DAY_SOLID);
  box-shadow: inset 0 0 0 1px var(--NEGATIVE_DAY_EDGE), 0 2px 12px rgba(var(--SHADE_RGB), 0.7);
}

.elastic-table td.is-editing.is-fullZoom.isToday.isNegative .cell-content::before {
  background: var(--NEGATIVE_GLOW_FILL), var(--NEGATIVE_DAY_SOLID);
  box-shadow: inset 0 0 0 1px var(--NEGATIVE_DAY_EDGE), 0 0 14px rgba(255, 50, 70, 0.6);
}

/* The page dims under a zoomed day (on a computer too), and its lines get a dark edge, so entries running past
   its edges are easy to read over the page */
.dayZoomBackdrop {
  position: absolute;
  inset: 0;
  z-index: 55;
  display: none;
  background: rgba(var(--SHADE_RGB), 0.7);
}

.elastic-table td.is-editing .cell-content {
  text-shadow: 0 0 3px rgb(var(--HALO_RGB)), 0 0 6px rgb(var(--HALO_RGB));
}

.dayZoomBackdrop.shown {
  display: block;
}

.elastic-table td:not(.is-editing) {
  z-index: 1;
}

/* Reduced motion (the device's, or Settings' animations switch: html.lessMotion): days zoom and magnify without easing
   into it */
@media (prefers-reduced-motion: reduce) {
  .elastic-table td,
  .elastic-table td .cell-content,
  .elastic-table td.is-editing,
  .elastic-table td.is-magnified .cell-content {
    transition: none;
  }
}

html.lessMotion .elastic-table td,
html.lessMotion .elastic-table td .cell-content,
html.lessMotion .elastic-table td.is-editing,
html.lessMotion .elastic-table td.is-magnified .cell-content {
  transition: none;
}

/* Anchor the first column so it zooms to the right */
.elastic-table td:first-child,
.elastic-table td:first-child .cell-content {
  transform-origin: left center;
}

/* Anchor the last column so it zooms to the left */
.elastic-table td:last-child,
.elastic-table td:last-child .cell-content {
  transform-origin: right center;
}

/* A zoomed day's round buttons in its top right corner: × (close) in the corner, and + (New Entry on that day) to its
   left, each a glass circle like the site's other buttons. Their sizes are divided by the day's zoom, so on screen
   they're the same however far the day is zoomed: --DAY_BUTTON_SPOT across, with a --DAY_BUTTON_SIZE mark,
   --DAY_BUTTON_INSET from the corner and from each other. */
:root {
  --DAY_BUTTON_SPOT: 30px;
  --DAY_BUTTON_SIZE: 17px;
  --DAY_BUTTON_INSET: 4px;
}

.cell-action-btn {
  position: absolute;
  top: calc(var(--DAY_BUTTON_INSET) / var(--zoom, 1));
  right: calc(var(--DAY_BUTTON_INSET) / var(--zoom, 1));
  box-sizing: border-box;
  width: calc(var(--DAY_BUTTON_SPOT) / var(--zoom, 1));
  height: calc(var(--DAY_BUTTON_SPOT) / var(--zoom, 1));
  margin: 0 !important;
  padding: 0 !important;
  pointer-events: auto;
  background: var(--GLASS_BUTTON);
  border: calc(1.5px / var(--zoom, 1)) solid var(--GLASS_LINE_BRIGHT);
  border-radius: 50%;
  outline: none;
  box-shadow: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--TEXT_BRIGHT);
  font-size: calc(var(--DAY_BUTTON_SIZE) / var(--zoom, 1));
  line-height: 1;
  font-family: sans-serif;
  text-shadow: none;
  cursor: pointer;
  z-index: 5;

  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease, visibility 0.2s ease, transform var(--SLOW_TRANSFORM), border-color var(--SLOW_BORDER);
}

.cell-action-btn.cellAdd {
  right: calc((2 * var(--DAY_BUTTON_INSET) + var(--DAY_BUTTON_SPOT)) / var(--zoom, 1));
}

.cell-action-btn:hover,
.cell-action-btn:focus-visible {
  transform: scale(1.08);
  border-color: var(--GLOW_EDGE);
  box-shadow: var(--HOVER_SHADOW);
}

.elastic-table td.is-magnified .cell-action-btn,
.elastic-table td.is-editing .cell-action-btn {
  opacity: 1;
  visibility: visible;
}

/* A phone's zoomed day isn't scaled, so its buttons are just their size, in the top right corner of the day it draws */
.elastic-table td.is-fullZoom .cell-action-btn {
  top: calc(var(--dayY, 0px) + var(--DAY_BUTTON_INSET));
  left: calc(var(--dayX, 0px) + var(--dayW, 100%) - var(--DAY_BUTTON_SPOT) - var(--DAY_BUTTON_INSET));
  right: auto;
  width: var(--DAY_BUTTON_SPOT);
  height: var(--DAY_BUTTON_SPOT);
  border-width: 1.5px;
  font-size: var(--DAY_BUTTON_SIZE);
}

.elastic-table td.is-fullZoom .cell-action-btn.cellAdd {
  left: calc(var(--dayX, 0px) + var(--dayW, 100%) - 2 * var(--DAY_BUTTON_SPOT) - 2 * var(--DAY_BUTTON_INSET));
}

/*========================================*
 *  MENU DATA PAGES (Recurring, History, Tracker, ...)
 *========================================*
 *  Same look as the calendar: glass cards and tables over the starfield, light text, neon blue accents, and red for
 *  what's chosen.
 */

:root {
  --PANEL_DEEP: rgba(40, 42, 110, 0.7);   /* Table titles and title cells */
  --PANEL_SOFT: rgba(24, 26, 72, 0.35);
  --PANEL_DARK: rgba(8, 9, 30, 0.62);
  --PANEL_LINE: rgba(128, 140, 255, 0.16);
  --PANEL_BORDER: rgba(150, 165, 255, 0.35);
  --PANEL_RADIUS: var(--GLASS_RADIUS);
  /* (Floating windows' glass, --HOVER_GRADIENT and --FLOAT_SHADOW, is in stylesheet.css: the date picker uses it too) */
  --NEGATIVE_TEXT: #ff6b7a;              /* Costs (negative entries) */
  --POSITIVE_TEXT: #5ee39a;              /* Gains (positive entries) */
  --ZERO_TEXT: #6f7396;                  /* $0.00 entries: a darker grey */
  --PLACEHOLDER_TEXT: #ffd447;           /* Placeholder entries, whatever their amount */
  --NEGATIVE_ON_RED: #ff9aa5;            /* Costs in a day below $0: lighter, to stand out on its red */
  --UI_TEXT: clamp(13px, 2.6vmin, 18px); /* Panels, search, toolbars */
  /* New Entry's ring hovered (the chosen color's neon), and in a theme, the ring itself (its glow's colors, themes.css) */
  --RING_HOVER_FILL: conic-gradient(from 200deg, #ff2a2a, #ff6a1a, #ffb03a, #ff6a1a, #ff2a2a);
  --RING_FILL: conic-gradient(from 200deg, rgb(var(--GLOW_RGB)), rgb(var(--GLOW_LIGHT_RGB)), rgb(var(--GLOW_RGB)));
}

/* Page links on the Menu page: a glass card each, with its name and what it's for */
.menuLinks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(10px, 2vmin, 18px);
  width: min(94vw, 760px);
  margin: 2vmin auto 4vmin;
}

.menuLinks a.menuLink {
  display: flex;
  flex-direction: column;
  gap: 0.35em;
  margin: 0;
  padding: 1em 1.2em;
  font-size: clamp(14px, 2.8vmin, 18px);
  text-align: left;
  text-decoration: none;
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: var(--GLASS_RADIUS);
  box-shadow: var(--GLASS_SHADOW);
  transition: transform var(--SLOW_TRANSFORM), box-shadow var(--SLOW_SHADOW), border-color var(--SLOW_BORDER);
}

.menuLinks a.menuLink:hover,
.menuLinks a.menuLink:focus-visible {
  transform: scale(1.03);
  text-shadow: none;
  outline: none;
  border-color: var(--GLOW_EDGE);
  background: var(--GLOW_FILL), var(--GLASS);
  box-shadow: var(--GLOW_SHADOW);
}

.menuLinkName {
  font-size: clamp(17px, 3.6vmin, 24px);
  color: var(--TEXT_BRIGHT);
}

/* Bob's picture beside his name: a small circle, about two lines of his name tall, like his picture on Home */
.menuLinkName.hasPicture {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.menuLinkPicture {
  flex-shrink: 0;
  width: 2em;
  height: 2em;
  border-radius: 50%;
  object-fit: cover;
  background: var(--BOX_FILL);
  border: 2px solid var(--PANEL_BORDER);
  box-shadow: 0 0 10px rgba(var(--GLOW_RGB), 0.35);
}

.menuLinkAbout {
  font-size: clamp(12px, 2.4vmin, 15px);
  color: var(--TEXT_DIM);
}

/* Status + empty states */
.dataStatus,
.dataEmpty {
  font-size: clamp(14px, 3vmin, 20px);
  opacity: 0.8;
  margin: 4vmin auto;
}

/* A quiet tip under a table */
.dataHint {
  margin: -2vmin auto 3vmin;
  font-size: var(--UI_TEXT);
  opacity: 0.7;
}

/* Horizontal scroll for wide tables (phones). Only sideways: a box that can scroll up and down too (overflow-x
   alone makes overflow-y auto) takes an up or down swipe from the page on iPhones, so the page doesn't move. Its
   scroll bar is thin and blue. */
.dataScroll {
  width: 94vw;
  max-width: 100%;
  margin: 0 auto 4vmin;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--GLOW_LIGHT_RGB), 0.45) transparent;
}

/* Base data table */
.dataTable {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0.4vmin;
  font-size: clamp(10px, 2.4vmin, 18px);
  text-align: left;
  user-select: text;
  -webkit-user-select: text;
}

.dataTable th {
  padding: 1.2vmin 1.5vmin;
  font-size: clamp(12px, 2.7vmin, 21px);
  font-weight: normal;
  text-align: center;
  white-space: nowrap;
  color: var(--TEXT_BRIGHT);
  /* The neon bar under the column titles is one gradient across the whole row: Budget UI.js (spanHeaderBar) sets
     --barWidth (the row's width) and each title's --barX (where it sits in the row), so each title shows its own
     piece of the same gradient. Before that, each title shows the whole gradient. */
  background:
    linear-gradient(90deg, var(--NEON_CYAN), var(--NEON_BLUE), var(--NEON_VIOLET), var(--NEON_PINK)) var(--barX, 0px) 100% / var(--barWidth, 100%) 2px no-repeat,
    linear-gradient(to bottom, var(--PANEL_DEEP), var(--PANEL_SOFT));
  border-bottom: none;
  box-shadow: 0 6px 12px -8px rgba(var(--GLOW_RGB), 0.9);
}

.dataTable th:first-child {
  border-top-left-radius: 10px;
}

.dataTable th:last-child {
  border-top-right-radius: 10px;
}

.dataTable td {
  padding: 0.8vmin 1.5vmin;
  vertical-align: top;
  background: var(--PANEL_DARK);
  border-bottom: 1px solid var(--PANEL_LINE);
}

/* First-column titles get the deep panel, like the spreadsheet's colored title column */
.dataTable .titleCell {
  text-align: right;
  white-space: nowrap;
  background: linear-gradient(to left, var(--PANEL_DEEP), var(--PANEL_SOFT));
}

.dataTable .typeCell {
  text-align: center;
  white-space: nowrap;
}

.dataTable .amountCell {
  text-align: center;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.dataTable .amountCell.negative {
  color: var(--NEGATIVE_TEXT);
}

.dataTable .amountCell.positive {
  color: var(--POSITIVE_TEXT);
}

.dataTable .aliasCell {
  min-width: 16vmin;
  font-size: 0.85em;
  opacity: 0.85;
}

/* The tracker fits the screen, with no sideways scrolling: a row's title and the amounts' column titles can take two
   lines, and the Aliases column gets the room that's left (its box scrolls, and a tap opens it all the way) */
.trackerTable th,
.trackerTable td.titleCell {
  white-space: normal;
}

/* Where it's tight (Edit, with its ≡ and checkbox columns, and Search's results, in the narrower search box; and any
   phone, below), it packs closer: the title column keeps about a fifth of the table, so a long title goes on two lines
   and a word too long for it breaks (with a hyphen where the browser can), and there's less space around each cell */
.trackerTable:where(.isEditing, .pageSearchTable) td.titleCell {
  width: 22%;
  overflow-wrap: anywhere;
  -webkit-hyphens: auto;
  hyphens: auto;
}

.trackerTable:where(.isEditing, .pageSearchTable) th,
.trackerTable:where(.isEditing, .pageSearchTable) td {
  padding-left: 1vmin;
  padding-right: 1vmin;
}

.trackerTable:where(.isEditing, .pageSearchTable) .aliasCell {
  min-width: 10vmin;
}

.trackerTable.isEditing .moveBar {
  width: 1.8em;
}

@media (max-width: 560px) {
  .trackerTable th,
  .trackerTable td {
    padding-left: 1vmin;
    padding-right: 1vmin;
  }

  .trackerTable td.titleCell {
    width: 22%;
    overflow-wrap: anywhere;
    -webkit-hyphens: auto;
    hyphens: auto;
  }
}

@media (max-width: 400px) {
  .trackerTable th,
  .trackerTable td {
    padding-left: 0.6vmin;
    padding-right: 0.6vmin;
  }
}

@media (max-width: 359px) {
  .dataTable .aliasCell {
    min-width: 12vmin;
  }

  .trackerTable:where(.isEditing, .pageSearchTable) .aliasCell {
    min-width: 6vmin;
  }

  /* Edit's ≡ and checkbox columns leave no room for the aliases here, so Edit leaves them out (Done brings them back) */
  .trackerTable.isEditing .aliasHead,
  .trackerTable.isEditing .aliasCell {
    display: none;
  }
}

/* A row's aliases scroll in a box about two lines tall (Budget Pages.js aliasBox): tapped, it opens all the way */
.dataTable .aliasBox {
  max-height: 2.7em;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--GLOW_LIGHT_RGB), 0.45) transparent;
}

.dataTable .aliasBox.isClipped {
  cursor: zoom-in;
  -webkit-mask-image: linear-gradient(to bottom, #000 60%, rgba(0, 0, 0, 0.35));
  mask-image: linear-gradient(to bottom, #000 60%, rgba(0, 0, 0, 0.35));
}

.dataTable .aliasBox.isOpen {
  max-height: none;
  overflow: visible;
  cursor: zoom-out;
}

/* Category separator rows */
.dataTable .categoryRow td {
  text-align: center;
  font-size: 1.2em;
  padding: 1vmin;
  color: var(--TEXT_BRIGHT);
  background: linear-gradient(to right, transparent, var(--PANEL_DEEP), transparent);
  border-bottom: none;
  text-shadow: var(--TITLE_GLOW);
}

/* History: a week on each row, like the calendar's days (they zoom the same way). Each day shows just its date,
   big, until it's zoomed or magnified; then it shows the day as it was (its full date, In Bank, and entries). */
.elastic-table.historyGrid {
  height: auto;
  margin: 0 auto 4vmin;
}

/* The weekdays over the days (Home's calendar and History) */
.elastic-table th {
  height: 1px; /* As short as its words (the table's height goes to the days) */
  padding: 0 0 0.8vmin;
  font-size: clamp(9px, 2vmin, 14px);
  font-weight: normal;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--TEXT_DIM);
}

.historyGrid td {
  height: max(11vmin, 46px);
}

.historyGrid .historyDate {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: auto;
  font-size: clamp(12px, 3.2vmin, 26px);
  font-weight: bold;
  line-height: 1.1;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.historyGrid .historyYear {
  font-size: 0.6em;
  font-weight: normal;
  opacity: 0.7;
}

.historyGrid td:not(.is-editing):not(.is-magnified) .cell-content > :not(.historyDate):not(.cell-action-btn),
.historyGrid td:is(.is-editing, .is-magnified) .historyDate {
  display: none;
}

/* The guest row (Process Budget.js ONE DAY AFTER ANOTHER): seven days laid over a row of the page's days, for a day
   the page doesn't have (History's on Home, the calendar's on History, and the 28 days after the calendar on both). Only
   the one that's zoomed (or shrinking back) shows, or can be tapped. */
.elastic-table.guestDays {
  position: absolute;
  height: auto;
  margin: 0;
  visibility: hidden;
  pointer-events: none;
}

.elastic-table.guestDays td:is(.is-editing, .isZoomClosing) {
  visibility: visible;
  pointer-events: auto;
}

/* Only a calendar day's In Bank can be set (History's and the days after the calendar's can't) */
.elastic-table.guestDays td:not([data-kind="calendar"]) .lineInBank {
  pointer-events: none;
}

/* Recurring Entries and Change Logs fit the screen, with no sideways scrolling: column titles can take two lines, and the
   title (or action) column gets the room that's left, left-aligned, its text cut short with "..." (Budget Pages.js
   clippedCell: tapping it shows it whole, wrapped, and tapping again cuts it short) */
.dataTable.recurringTable,
.dataTable.logsTable {
  table-layout: auto;
}

.recurringTable th,
.logsTable th {
  white-space: normal;
}

/* Recurring's Monthly and Yearly under the card's title: each on one line */
.keepTogether {
  white-space: nowrap;
}

.dataTable .clipText {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dataTable .clipText.isClipped {
  cursor: zoom-in;
}

.dataTable .clipText.isOpen {
  overflow: visible;
  white-space: normal;
  overflow-wrap: anywhere;
  cursor: zoom-out;
}

.recurringTable .titleHead,
.recurringTable td.titleCell,
.logsTable .actionHead,
.logsTable td.actionCell {
  text-align: left;
}

.recurringTable td.titleCell {
  width: 100%;
  max-width: 0; /* It takes the room the other columns leave, and no more */
  white-space: normal;
}

/* Where the dates break onto two lines (so a row is two lines tall anyway), a long title uses its second line before
   it's cut short */
@media (max-width: 699px) {
  .recurringTable .clipText:not(.isOpen) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

.recurringTable td.dateCell,
.recurringTable td.frequencyCell {
  text-align: center;
}

.recurringTable td.frequencyCell {
  white-space: normal;
}

/* With room to spare, the column titles, dates, and frequencies stay on one line (only the title column gives way) */
@media (min-width: 700px) {
  .recurringTable th,
  .recurringTable td.dateCell,
  .recurringTable td.frequencyCell {
    white-space: nowrap;
  }

  /* (Some browsers break at a date's <wbr> even then) */
  .recurringTable td.dateCell wbr {
    display: none;
  }
}

/* Change Logs: the time on two lines (its time over its day), and the details in a box about two lines tall that scrolls
   (tapping it opens it all the way, like the tracker's aliases) */
.logsTable .timeCell {
  font-size: 0.9em;
  opacity: 0.85;
}

.logsTable td.actionCell {
  width: 32%;
  max-width: 0;
  white-space: normal;
}

.logsTable .detailsCell {
  font-size: 0.9em;
}

.dataTable .aliasBox.detailsBox {
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* An Equity account's balance with Separate Interest: the rest, and its interest on a line of its own */
.accountsTable td.withInterest .interestLine {
  display: block;
  font-size: 0.85em;
  opacity: 0.8;
  white-space: nowrap;
}

/* Search's Go To Equity, under its results when it looks past today */
.searchAccountsRow {
  justify-content: center;
  margin-top: 0.8em;
}

/* Each change's Undo, at the right ("Undone" once it was) */
.logsTable .undoCell {
  white-space: nowrap;
  text-align: center;
}

.logsTable .logUndo {
  padding: 0.3em 0.7em;
  font-size: 0.85em;
}

.logsTable .logUndone {
  font-size: 0.85em;
  opacity: 0.65;
}

.logsTable tr.errorRow td {
  background: rgba(120, 0, 20, 0.6);
}

.logsTable tr.notFoundRow td {
  background: rgba(90, 40, 0, 0.5);
}

/*========================================*
 *  ENTRY LINES (calendar, history, panels)
 *========================================*/

.lineDate {
  font-weight: bold;
  color: var(--TEXT_BRIGHT);
}

/* An entry's words follow its amount: a gain green, a cost red, and $0.00 a darker grey. The lines the budget writes
   itself (In Bank, Gains, Costs) stay the day's light grey (a day below $0 turns red itself). Placeholders are yellow
   whatever their amount (at the end). */
.lineEntry.positive,
.positive {
  color: var(--POSITIVE_TEXT);
}

.lineEntry.negative,
.negative {
  color: var(--NEGATIVE_TEXT);
}

/* A cost in a day below $0: a lighter red, so it stands out on the day's own red (a placeholder stays yellow) */
.elastic-table td.isNegative .lineEntry.negative:not(.isPlaceholder) {
  color: var(--NEGATIVE_ON_RED);
}

.lineEntry.isZero,
.upcomingEntry.isZero,
.accountEntryLine.isZero {
  color: var(--ZERO_TEXT);
}

/* An entry with a note is underlined wherever it shows: on a day, in Upcoming, Search, an account's entries, Quick
   Entry's waiting entries, and a recurring entry's title when it has a note of its own (the note is in its options).
   The line stays close under the text: lines that cut off with "..." would cut off one further down. */
.hasNote {
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

/* Calendar days: today glows (a blue-violet radial gradient from its center, a bright edge, and a glow around it),
   and a day below $0 turns red (today glows red then). Not a phone's zoomed day: its content is as big as the screen
   and draws the day itself (::before, above). */
.elastic-table td.isToday:not(.is-fullZoom) .cell-content {
  background: var(--GLOW_FILL), var(--DAY_FILL);
  box-shadow: inset 0 0 0 1px var(--GLOW_EDGE), 0 0 12px rgba(var(--GLOW_RGB), 0.65);
}

.elastic-table td.isNegative:not(.is-fullZoom) .cell-content {
  background: var(--NEGATIVE_DAY_FILL);
  box-shadow: inset 0 0 0 1px var(--NEGATIVE_DAY_EDGE), 0 0 8px rgba(255, 40, 60, 0.3);
}

.elastic-table td.isToday.isNegative:not(.is-fullZoom) .cell-content {
  background: var(--NEGATIVE_GLOW_FILL), var(--NEGATIVE_DAY_FILL);
  box-shadow: inset 0 0 0 1px var(--NEGATIVE_DAY_EDGE), 0 0 12px rgba(255, 50, 70, 0.6);
}

/* ...and solid while a computer zooms or magnifies them */
.elastic-table td.isToday:is(.is-editing, .is-magnified):not(.is-fullZoom) .cell-content {
  background: var(--GLOW_FILL), var(--DAY_SOLID);
}

.elastic-table td.isNegative:is(.is-editing, .is-magnified):not(.is-fullZoom) .cell-content {
  background: var(--NEGATIVE_DAY_SOLID);
}

.elastic-table td.isToday.isNegative:is(.is-editing, .is-magnified):not(.is-fullZoom) .cell-content {
  background: var(--NEGATIVE_GLOW_FILL), var(--NEGATIVE_DAY_SOLID);
}

/* Entries are tappable once their day is zoomed, on Home and History (sized with the text, so they look the same at any
   zoom), and so is the day's In Bank on Home (History's In Bank is a record) */
.elastic-table td.is-editing .lineEntry,
.elastic-table:not(.historyGrid) td.is-editing .lineInBank {
  pointer-events: auto;
  cursor: pointer;
  border-radius: 0.3em;
  padding: 0 0.2em;
  margin: 0 -0.2em;
}

.elastic-table td.is-editing .lineEntry:hover,
.elastic-table:not(.historyGrid) td.is-editing .lineInBank:hover {
  background: rgba(var(--TINT_RGB), 0.1);
}

/* Date picking: tap a day to fill the waiting date field (its calendar button opens the date picker instead) */
body.datePicking .elastic-table {
  outline: 2px dashed rgba(var(--PICK_RGB), 0.55);
  outline-offset: 6px;
  border-radius: 6px;
}

body.datePicking .elastic-table td {
  cursor: crosshair;
}

.elastic-table td.pickedFlash .cell-content {
  animation: pickedFlash 0.7s ease-out;
}

@keyframes pickedFlash {
  from { box-shadow: 0 0 0 3px var(--LINK_LIGHT), 0 0 22px var(--LINK_LIGHT); }
  to   { box-shadow: 0 0 0 0 transparent; }
}

/*========================================*
 *  BUTTONS (panels, toolbars, search)
 *========================================*/

.budgetButton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45em;
  margin: 0;
  padding: 0.45em 1.1em;
  font-size: var(--UI_TEXT);
  white-space: nowrap;
}

/* (Recommended .primary buttons glow, not-recommended .danger ones are darker, and chosen ones have the red-orange ring:
   stylesheet.css BUTTONS and GRADIENT BORDERS) */

.budgetButton:disabled {
  opacity: 0.45;
  pointer-events: none;
}

/*========================================*
 *  PANELS (new entry, entry options, recurring, tracker, sections)
 *========================================*/

.budgetPanel {
  box-sizing: border-box;
  color: var(--BASE_COLOR);
  text-align: left;
  font-size: var(--UI_TEXT);
  background: var(--HOVER_GRADIENT);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: 18px;
  box-shadow: var(--FLOAT_SHADOW);
  user-select: text;
  -webkit-user-select: text;
}

.budgetPanel.large {
  width: min(94vw, 560px);
  margin: 2vmin auto 3vmin;
}

/* Large panels float over the top of the screen (the page under them doesn't move). They're in the screen layer
   (stylesheet.css), so they're placed on the visible screen, and they're part of the page once they're open: a tall one
   doesn't scroll inside itself, it runs past the screen's bottom, and the page scrolls to the rest of it (boxes in it
   that scroll, like an account's entries, still do). */
.budgetPanel.large.floating {
  position: fixed;
  z-index: 1300;
  top: max(2vh, env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  margin: 0 auto;
  background: var(--HOVER_GRADIENT);
}

/* Small panels sit by what opened them (Budget UI.js positionNear), on the visible screen; a tall one runs past its
   bottom, like a large one */
.budgetPanel.small {
  position: absolute;
  z-index: 1300;
  width: min(88vw, 340px);
  background: var(--HOVER_GRADIENT);
}

/* (Date boxes, their calendar button, and the date picker are in stylesheet.css: the login page has one too) */

/* Recurring frequency: Every [number] [Days / Weeks / Months] */
.frequencyRow {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.budgetPanel .frequencyRow .frequencyCount {
  flex: 0 0 4.5em;
  width: 4.5em;
  text-align: center;
}

.budgetPanel .frequencyRow .frequencyUnit {
  flex: 1 1 auto;
  width: auto;
}

.budgetPanel.isBusy {
  opacity: 0.75;
  cursor: progress;
}

.budgetPanel.isClosing {
  pointer-events: none;
}

.panelHeader {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1em;
  padding: 0.8em 1em 0.2em;
}

.budgetPanel:focus {
  outline: none;
}

.panelHeader :is(h2, h3) {
  margin: 0;
  font-size: 1.25em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.panelClose {
  display: inline-block;
  margin: 0;
  padding: 0 0.25em;
  border: none;
  background: none;
  font-size: 1.6em;
  line-height: 1;
  color: var(--BASE_COLOR);
}

.panelClose:hover {
  box-shadow: none;
}

.panelBody {
  align-items: stretch;
  gap: 0.75em;
  padding: 0.6em 1em 1em;
  box-sizing: border-box;
}

.panelField {
  display: flex;
  flex-direction: column;
  gap: 0.3em;
}

.fieldLabel {
  font-size: 0.85em;
  opacity: 0.9;
}

.fieldLabel .optional,
.panelHint {
  opacity: 0.65;
  font-size: 0.85em;
}

/* A tiny ? after a field's label (like Refraction Type) that shows a short explanation under the field */
.fieldHelpButton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 1.45em;
  height: 1.45em;
  margin: 0 0 0 0.45em;
  padding: 0;
  vertical-align: middle;
  font-size: 0.85em;
  line-height: 1;
  color: var(--BASE_COLOR);
  background: var(--BOX_FILL);
  border: 1.5px solid var(--PANEL_BORDER);
  border-radius: 50%;
}

.fieldHelpButton:hover,
.fieldHelpButton:focus-visible,
.fieldHelpButton[aria-expanded="true"] {
  transform: none;
  color: var(--TEXT_HOT);
  box-shadow: 0 0 8px rgba(var(--PICK_RGB), 0.55);
}

.fieldHelp {
  padding: 0.55em 0.8em;
  font-size: 0.85em;
  line-height: 1.45;
  text-align: left;
  background: rgba(var(--INSET_RGB), 0.35);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.fieldHelp ul {
  margin: 0;
  padding-left: 1.1em;
}

.fieldHelp li + li {
  margin-top: 0.35em;
}

/* Boxes never ask for more room than their row has: iPhones size a box that has no width of its own by the font's
   average letter, which for the site's font (it has Chinese and Japanese too) made a title's box wider than its panel,
   so the panel scrolled sideways. max-width: 100% and min-width: 0 let it shrink to its row (and its row to the panel). */
.budgetPanel input[type="text"],
.budgetPanel textarea,
.budgetPanel select,
.searchBar input,
.searchBar select {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  margin: 0;
  padding: 0.5em 0.8em;
  font-family: var(--FONT);
  font-size: var(--UI_TEXT);
  text-align: left;
  color: var(--TEXT_BRIGHT);
  background: var(--BOX_FILL);
  border: 1.5px solid var(--PANEL_BORDER);
  border-radius: 10px;
  user-select: text;
  -webkit-user-select: text;
}

/* Touch screens: 16px at least, or iPhones zoom in on a box when it's tapped (and the zoom cuts off the floating
   box it's in, at both sides) */
@media (pointer: coarse) {
  .budgetPanel input[type="text"],
  .budgetPanel textarea,
  .budgetPanel select,
  .searchBar input,
  .searchBar select {
    font-size: max(16px, var(--UI_TEXT));
  }
}

.budgetPanel textarea {
  resize: vertical;
}

.budgetPanel input[type="text"]:hover,
.budgetPanel input[type="text"]:focus,
.budgetPanel textarea:hover,
.budgetPanel textarea:focus,
.budgetPanel select:focus,
.searchBar input:hover,
.searchBar input:focus,
.searchBar select:focus {
  transform: none;
  text-shadow: none;
  box-shadow: none;
  outline: none;
}

.budgetPanel input:disabled,
.budgetPanel textarea:disabled {
  opacity: 0.6;
}

.budgetPanel input.positive {
  color: var(--POSITIVE_TEXT);
}

.budgetPanel select option,
.budgetCard select option,
.searchBar select option {
  background: var(--LIST_FILL);
}

.amountRow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em;
}

.amountRow input {
  flex: 1 1 8em;
  width: auto;
  min-width: 0;
}

/* An amount's $ / % switch (shown while an Equity account is picked): small, before the box */
.amountRow .unitToggle {
  flex: 0 0 auto;
  flex-wrap: nowrap;
}

.amountRow .unitToggle .budgetButton {
  padding: 0.35em 0.7em;
}

.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em;
}

.segmented .budgetButton {
  padding: 0.35em 0.85em;
  font-size: 0.9em;
}

/* The chosen one: the red-orange border and a red glow, over a red radial gradient from its center */
.segmented .budgetButton[aria-checked="true"],
.choiceList .budgetButton[aria-checked="true"] {
  color: var(--TEXT_HOT);
  background: var(--PICK_FILL), rgba(var(--PICK_RGB), 0.22);
  box-shadow: 0 0 10px rgba(var(--PICK_RGB), 0.6);
}

/* A choice list (Budget UI.js choiceList: what a goal is for): buttons that wrap, each with its name and, under it, a
   second line (an account's balance, smaller and dimmer, red below $0). A long name wraps inside its button. */
.choiceList {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em;
}

.choiceList .budgetButton {
  flex-direction: column;
  gap: 0.1em;
  max-width: 100%;
  min-width: 0;
  padding: 0.35em 0.85em;
  font-size: 0.9em;
  line-height: 1.2;
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: center;
}

.choiceList .choiceDetail {
  font-size: 0.85em;
  color: var(--TEXT_DIM);
  font-variant-numeric: tabular-nums;
}

.choiceList .choiceDetail.negative {
  color: var(--NEGATIVE_TEXT);
}

.choiceList .budgetButton[aria-checked="true"] .choiceDetail:not(.negative) {
  color: var(--BASE_COLOR);
}

/* A dropdown (Budget UI.js dropdownList: an entry's Equity account): a box like the other boxes, with the picked one in
   it and a ▾, and the list that drops down under it (stylesheet.css .pickerList), each one its name over its balance
   (smaller and dimmer, red below $0). The picked one has a faint red-orange tint, and the one the pointer or the keys
   are on the full red-orange. */
.dropdown {
  position: relative;
  min-width: 0;
}

button.dropdownBox {
  display: flex;
  align-items: center;
  gap: 0.6em;
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  padding: 0.45em 0.8em;
  font-size: var(--UI_TEXT);
  line-height: 1.25;
  text-align: left;
  color: var(--TEXT_BRIGHT);
  background: var(--BOX_FILL);
  border: 1.5px solid var(--PANEL_BORDER);
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
}

button.dropdownBox:hover,
button.dropdownBox[aria-expanded="true"] {
  transform: none;
  color: var(--TEXT_BRIGHT);
  border-color: var(--GLASS_LINE_BRIGHT);
  box-shadow: none;
}

button.dropdownBox:focus-visible {
  outline: none;
  border-color: var(--GLOW_EDGE);
}

.dropdownPicked,
.dropdownOption {
  display: flex;
  flex-direction: column;
  gap: 0.1em;
  min-width: 0;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.dropdownPicked {
  flex: 1 1 auto;
}

.dropdownArrow {
  flex: none;
  color: var(--TEXT_DIM);
  font-size: 0.9em;
}

.dropdownList .dropdownOption {
  padding: 0.4em 0.8em;
}

.dropdownList .dropdownOption[aria-selected="true"]:not(.isActive):not(:hover) {
  background: rgba(var(--PICK_RGB), 0.16);
}

.dropdown .choiceDetail {
  font-size: 0.85em;
  color: var(--TEXT_DIM);
  font-variant-numeric: tabular-nums;
}

.dropdown .choiceDetail.negative {
  color: var(--NEGATIVE_TEXT);
}

.dropdownOption:hover .choiceDetail:not(.negative),
.dropdownOption.isActive .choiceDetail:not(.negative) {
  color: var(--BASE_COLOR);
}

.checkboxField {
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin: 0;
  font-size: 1em;
  color: var(--BASE_COLOR);
}

/* The Placeholder switch: its word in a placeholder's yellow */
.placeholderField .checkboxField span {
  color: var(--PLACEHOLDER_TEXT);
}

/* Title lists (tracker aliases, the search bar): a title box, its buttons, and × on each line. Every part can shrink to
   the panel's width (see the boxes above). */
.termList {
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  min-width: 0;
}

.termField,
.panelField,
.searchTerms {
  min-width: 0;
}

/* Each line in its own box, so its buttons clearly go with its title when the line wraps */
.termRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4em 0.5em;
  padding: 0.45em 0.5em;
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
  background: rgba(var(--INSET_RGB), 0.2);
}

.budgetPanel .termRow .termInput {
  flex: 1 1 9em;
  width: auto;
}

/* A line's buttons and its ×, together: × right after the last button, and all of it at the right when it
   wraps under the title (instead of × on a line of its own) */
.termControls {
  display: flex;
  flex: 0 1 auto;
  align-items: center;
  gap: 0.4em;
  min-width: 0;
  margin-left: auto;
}

.termRow .segmented {
  flex: 0 1 auto;
  min-width: 0;
}

.budgetButton.termAdd {
  margin-top: 0.5em;
  padding: 0.25em 0.9em;
  font-size: calc(var(--UI_TEXT) * 0.9);
}

/* A connected spreadsheet's typed Equity account (a list of the names alone; entries pick theirs with a choiceList) */
.budgetPanel select.accountSelect {
  width: auto;
  min-width: 12em;
  max-width: 100%;
  align-self: flex-start;
}

/* The entry an entry's options are for, whole: a long title wraps instead of being cut short like on its day */
.panelEntry {
  padding: 0.45em 0.7em;
  border-radius: 8px;
  background: rgba(var(--INSET_RGB), 0.4);
  font-size: 1.05em;
  white-space: normal;
  overflow-wrap: anywhere;
}

.panelError {
  margin: 0;
  font-size: 0.9em;
  color: var(--NEGATIVE_TEXT);
}

/* Paragraphs in a panel (the global p is much bigger) */
.panelText {
  margin: 0;
  font-size: 1em;
  line-height: 1.4;
}

.panelButtons {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.5em;
  margin-top: 0.2em;
}

/* Toasts (e.g. a change that couldn't be saved yet), stacked at the bottom so two at once are both readable */
.toastStack {
  position: fixed;
  left: 50%;
  bottom: 4vh;
  z-index: 2000;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6em;
  width: max-content;
  max-width: 90vw;
  font-size: var(--UI_TEXT);
  pointer-events: none;
}

.budgetToast {
  max-width: 90vw;
  box-sizing: border-box;
  pointer-events: auto;
  padding: 0.7em 1.2em;
  font-size: var(--UI_TEXT);
  color: var(--TEXT_BRIGHT);
  background: var(--HOVER_GRADIENT);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: var(--PANEL_RADIUS);
  box-shadow: var(--FLOAT_SHADOW);
  transition: opacity 0.5s ease;
}

.budgetToast.warning {
  border-color: var(--NEGATIVE_TEXT);
}

.budgetToast.leaving {
  opacity: 0;
}

/*========================================*
 *  HOME PAGE: GETTING STARTED, SEARCH BAR, INFO ROW, TOOLBAR
 *========================================*/

/* A new budget's first steps (shown until they're done, or hidden with ×) */
.budgetCard.gettingStarted {
  position: relative;
  width: var(--PAGE_WIDTH);
  margin: 0 auto clamp(10px, 2vmin, 18px);
}

.gettingStarted .panelClose {
  position: absolute;
  top: 0.5em;
  right: 0.5em;
}

.gettingStarted h3 {
  padding-right: 2em; /* Room for × */
}

.startSteps {
  margin: 0 0 0.6em;
  padding-left: 1.4em;
  line-height: 1.5;
}

.startSteps li {
  margin: 0 0 1em;
}

/* A done step starts with In Bank's green check (Sprites.js's image for ✅) */
.startSteps li.done > strong::before {
  content: "";
  display: inline-block;
  width: 1.15em;
  height: 1.15em;
  margin-right: 0.35em;
  vertical-align: -0.22em;
  background: url("/Resources/Sprites/InBank.webp?v=40a6bd5f60") center / contain no-repeat;
}

.startSteps .panelButtons {
  justify-content: flex-start;
  margin-top: 0.4em;
}

/* The global form centers a column; these fields sit in a row that wraps on phones */
.startForm {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5em;
  margin-top: 0.5em;
}

.budgetCard .startForm input[type="text"] {
  flex: 1 1 11em;
  width: auto;
  min-width: 0;
}

/* Search: the Search button above the calendar opens it, floating over the page like a large panel (it
   lives in the screen layer, see wireSearch in Budget Search.js). Its results show under its form (in a box that
   scrolls); a tall one runs past the screen's bottom, and the page scrolls to the rest. */
.searchBar {
  position: fixed;
  z-index: 1300;
  top: max(2vh, env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  box-sizing: border-box;
  width: min(94vw, 760px);
  margin: 0 auto;
  padding: 0 1em 1em;
  font-size: var(--UI_TEXT);
  text-align: left;
  color: var(--BASE_COLOR);
  background: var(--HOVER_GRADIENT);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: 18px;
  box-shadow: var(--FLOAT_SHADOW);
}

.searchBar .panelHeader {
  padding: 0.8em 0 0.4em;
}

.searchBar form {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1vmin;
}

.searchBar input {
  flex: 1 1 9em;
  width: auto;
  min-width: 0;
  border-radius: 9999px;
  padding: 0.45em 1em;
}

/* Safari's own text box look (an inner shadow, its own padding and line height) can cut the words off at the edges
   of a round box, so the box is drawn only by these rules */
.searchBar input[type="text"] {
  -webkit-appearance: none;
  appearance: none;
  line-height: 1.35;
  text-overflow: ellipsis;
}

/* The titles to search for: one line each, with All / Costs / Gains / Tracker and × */
.searchTerms {
  flex: 1 1 100%;
  font-size: var(--UI_TEXT);
}

.searchTerms .termList {
  gap: 1vmin;
}

/* A single line sits right on the bar; once there are more, each gets its own box */
.searchTerms .termRow {
  justify-content: center;
  gap: 1vmin;
  padding: 0;
  border: none;
  background: none;
}

.searchTerms .termList:has(.termRow + .termRow) .termRow {
  padding: 0.45em 0.5em;
  border: 1px solid var(--PANEL_LINE);
  background: rgba(var(--INSET_RGB), 0.2);
}

.searchBar .termInput {
  flex: 3 1 10em;
}

/* A title's Exact switch, right beside its box (Tracker titles don't have one) */
.termRow .termExact {
  flex: 0 0 auto;
  gap: 0.4em;
  font-size: 0.9em;
  white-space: nowrap;
  cursor: pointer;
}

.termRow .termExact[hidden] {
  display: none;
}

.searchBar .termExact input.pillSwitch {
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
}

.searchTerms .segmented {
  justify-content: center;
}

.searchTerms .termRemove {
  margin-left: 0;
}

/* The ? before the first title's All, and what it shows under the titles (Budget UI.js termList) */
.termControls .termHelpButton {
  flex: 0 0 auto;
  margin: 0;
}

.termRow + .termRow .termHelpButton {
  display: none;
}

.searchTerms .termHelp {
  margin-top: 0.6em;
}

/* Search's filters: a refraction type and an Equity account, side by side across the box (columns that can shrink below a
   box's own width, so they never push past the edges) */
.searchFilters {
  display: grid;
  flex: 1 1 100%;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.6em;
  margin-top: 0.6em;
}

.searchFilters .selectInput {
  width: 100%;
  min-width: 0;
}

/* + Add Title, From, To, and Search stay together when the bar wraps (on phones, they wrap under each other) */
.searchDates {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  flex: 1 1 100%;
  gap: 1vmin;
}

/* In the search box: From and To (each a full row on phones, side by side on wider screens), then
   + Add Title at the left and Search at the right. The columns can shrink below a date box's own width (a text box
   is about 20 letters wide unless told otherwise), so the two side by side never push past the box's edges. */
.searchBar .searchDates {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.6em;
  min-width: 0;
  margin-top: 0.4em;
}

.searchBar .searchDates .dateRow {
  grid-column: 1 / -1;
}

.searchBar #searchAdd {
  grid-column: 1;
  justify-self: start;
}

.searchBar .searchDates [type="submit"] {
  grid-column: 2;
  grid-row: 3;
  justify-self: end;
}

.searchBar #searchAdd {
  grid-row: 3;
}

@media (min-width: 560px) {
  .searchBar .searchDates .dateRow {
    grid-column: auto;
  }

  .searchBar #searchAdd,
  .searchBar .searchDates [type="submit"] {
    grid-row: 2;
  }
}

.searchDates .budgetButton.termAdd {
  margin-top: 0;
  padding: 0.45em 1em;
}

/* Tracker's and Change Logs' Search: one box for the words, its results under it (Budget Pages.js PAGE SEARCH) */
.searchBar .pageSearchInput {
  display: block;
  box-sizing: border-box;
  width: 100%;
  max-width: none;
  margin: 0.2em 0 0;
}

/* Equity: the total with In Bank, today and on the calendar's last day, and In Bank, over the accounts */
.accountsTotal {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6em clamp(14px, 4vw, 40px);
  margin: 0 auto 1.2em;
  padding: 0.8em 1em;
  font-size: var(--UI_TEXT);
  text-align: center;
  background: var(--PANEL_DARK);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 12px;
}

.accountsTotal .infoLabel {
  margin-bottom: 0.15em;
}

.accountsTotal .totalAmount {
  font-size: 1.25em;
  color: var(--TEXT_BRIGHT);
  font-variant-numeric: tabular-nums;
}

.accountsTotal .totalFigure.main .totalAmount {
  font-size: 1.7em;
}

.accountsTotal .totalAmount.negative {
  color: var(--NEGATIVE_TEXT);
}

/* An account's Interest and Escrow: each switch, and while it's on, its boxes (Interest today under Separate Interest) */
.interestFields,
.interestDetails,
.escrowFields,
.escrowDetails {
  display: flex;
  flex-direction: column;
  gap: 0.6em;
}

/* The lines between an account's balance and max, its interest, and its escrow */
.budgetPanel hr.panelLine {
  width: 100%;
  margin: 0.15em 0;
  border: 0;
  border-top: 1px solid var(--PANEL_LINE);
}

.startForm .startSign {
  flex: 0 0 auto;
}

/* Search's results: what's after today is tinted, and a line under its own heading sets it apart from today and
   before */
.searchTable tr.searchComing td {
  background: rgba(70, 60, 170, 0.32);
}

.searchTable tr.searchDivider td {
  padding: 0.5em 0.6em 0.3em;
  font-size: 0.85em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--TEXT_DIM);
  background: none;
  border-bottom: 2px solid var(--NEON_VIOLET);
}

.searchTable tr.searchComing + tr.searchDivider td {
  padding-top: 1em;
}

/* Results show under the search's form, inside the box */
.searchResults {
  margin-top: 0.9em;
  padding: 0.8em 1em;
  text-align: left;
  font-size: var(--UI_TEXT);
  background: rgba(var(--INSET_RGB), 0.3);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.searchHeader {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1em;
}

.searchSummary,
.searchTotal,
.searchMessage {
  margin: 0 0 0.5em;
  font-size: var(--UI_TEXT);
}

.searchTotal {
  font-size: 0.95em;
}

/* "Tap a result to change it." (Budget Search.js): each result opens its options */
.searchHint {
  margin: -0.3em 0 0.5em;
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

/* A result's day stays on one line ("Fri 11/12/2026") */
.searchTable td.searchDate {
  white-space: nowrap;
}

.searchTable tr.clickable {
  cursor: pointer;
}

.searchTable tr.clickable:hover td {
  background: rgba(var(--TINT_RGB), 0.06);
}

.searchScroll {
  width: 100%;
  max-height: 50vh;
  overflow-y: auto;
  margin: 0;
}

.searchTable th:first-child,
.searchTable td:first-child {
  width: 2em;
  text-align: center;
}

/*========================================*
 *  THE BUDGET'S FOUR PAGES (Home, Recurring Entries, History, Equity): TABS, BUTTONS, AND CARDS
 *========================================*
 *  Under the header: the four pages as tabs at the left (the one showing glows), beside a glass card with the
 *  page's own buttons. Under them, the page in a glass card with its icon and title.
 */

.pageTop {
  display: grid;
  grid-template-columns: clamp(98px, 27vw, 230px) minmax(0, 1fr);
  gap: clamp(8px, 1.6vw, 18px);
  width: var(--PAGE_WIDTH);
  margin: 0 auto clamp(10px, 2.2vmin, 22px);
}

.pageTabs {
  position: relative; /* The glow sliding to a tab that was tapped (below) */
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 1vmin, 10px);
}

/* A tab: its icon and name on glass. Tabs share the column's height, so they line up with the card beside them. Each is
   its own layer (isolation), so its glow's light (::after, below) goes between its glass and its words. */
.pageTabs a.pageTab {
  position: relative;
  isolation: isolate;
  display: flex;
  flex: 1 1 0;
  align-items: center;
  gap: 0.55em;
  box-sizing: border-box;
  min-height: 2.6em;
  margin: 0;
  padding: 0.45em 0.7em;
  font-size: clamp(11px, 3vw, 16px);
  line-height: 1.1;
  text-align: left;
  text-decoration: none;
  color: var(--BASE_COLOR);
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: 12px;
  box-shadow: var(--GLASS_SHADOW);
  transition: transform var(--SLOW_TRANSFORM), box-shadow var(--SLOW_SHADOW), border-color var(--SLOW_BORDER), color var(--SLOW_COLOR);
}

.pageTabs a.pageTab:hover,
.pageTabs a.pageTab:focus-visible {
  transform: none;
  color: var(--TEXT_BRIGHT);
  text-shadow: none;
  outline: none;
  border-color: var(--GLASS_LINE_BRIGHT);
  box-shadow: var(--GLASS_SHADOW), 0 0 10px rgba(var(--GLOW_RGB), 0.35);
}

/* The page that's showing glows: a bright edge and its glow, a blue-violet radial gradient from its center (::after), and
   a neon dot on its left edge (::before) */
.pageTabs a.pageTab[aria-current="page"] {
  color: var(--TEXT_BRIGHT);
  border-color: var(--GLOW_EDGE);
  box-shadow: 0 0 16px rgba(var(--GLOW_RGB), 0.55);
  cursor: default;
}

.pageTabs a.pageTab::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--GLOW_FILL);
  box-shadow: inset 0 0 12px rgba(var(--GLOW_RGB), 0.25);
  opacity: 0;
  pointer-events: none;
}

.pageTabs a.pageTab[aria-current="page"]::after {
  opacity: 1;
}

.pageTabs a.pageTab[aria-current="page"]::before,
.tabGlow::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -3px;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: linear-gradient(var(--NEON_CYAN), var(--NEON_VIOLET));
  box-shadow: 0 0 8px var(--NEON_BLUE);
}

/* A tab tapped: while the page slides out, the bright edge, its glow, and the dot (a copy of them, Layout.js
   glideTabGlow) slide over to it, and the light inside fades out of the tab it left and into the tapped one (in
   --GLIDE_TIME, as long as the slide), so the tapped tab ends up just like the next page's current tab */
.tabGlow {
  position: absolute;
  z-index: 1;
  box-sizing: border-box;
  border: 1px solid var(--GLOW_EDGE);
  border-radius: 12px;
  box-shadow: 0 0 16px rgba(var(--GLOW_RGB), 0.55);
  pointer-events: none;
}

.pageTabs.isGliding a.pageTab[aria-current="page"] {
  color: var(--BASE_COLOR);
  border-color: var(--GLASS_LINE);
  box-shadow: var(--GLASS_SHADOW);
}

.pageTabs.isGliding a.pageTab[aria-current="page"]::before {
  content: none;
}

.pageTabs.isGliding a.pageTab::after,
.pageTabs.isGliding .tabIcon {
  transition: opacity var(--GLIDE_TIME, 0.45s) ease, filter var(--GLIDE_TIME, 0.45s) ease;
}

.pageTabs.isGliding a.pageTab[aria-current="page"]::after {
  opacity: 0;
}

.pageTabs.isGliding a.pageTab.isGlideTarget {
  color: var(--TEXT_BRIGHT);
}

.pageTabs.isGliding a.pageTab.isGlideTarget::after {
  opacity: 1;
}

.tabIcon {
  flex-shrink: 0;
  width: 1.3em;
  height: 1.3em;
  border-radius: 0;
  object-fit: contain;
  opacity: 0.85;
}

.pageTab[aria-current="page"] .tabIcon,
.pageTabs.isGliding .pageTab.isGlideTarget .tabIcon {
  opacity: 1;
  filter: drop-shadow(0 0 4px rgba(var(--GLOW_LIGHT_RGB), 0.8));
}

.pageTabs.isGliding .pageTab[aria-current="page"] .tabIcon {
  opacity: 0.85;
  filter: drop-shadow(0 0 4px rgba(var(--GLOW_LIGHT_RGB), 0));
}

/* The narrowest phones: the tabs two by two, over the page's buttons (side by side, the buttons wouldn't fit) */
@media (max-width: 359px) {
  .pageTop {
    grid-template-columns: minmax(0, 1fr);
  }

  .pageTabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
}

/* The page's buttons, on glass beside the tabs */
.controlsCard {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 0;
  padding: clamp(6px, 1.8vw, 20px);
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: var(--GLASS_RADIUS);
  box-shadow: var(--GLASS_SHADOW);
}

/* Recurring Entries, History, and Equity: the page's icon and title over its buttons, beside the tabs */
.controlsCard.pageControls {
  flex-direction: column;
  align-items: stretch;
  gap: clamp(8px, 1.6vmin, 16px);
}

.pageControls .cardHeader {
  margin: 0;
  padding: 0;
}

.controlsCard.pageControls .tableToolbar {
  justify-content: flex-start;
}

/* A page in a glass card: the calendar, or Recurring Entries', History's, and Equity accounts' tables. It never
   clips or layers what's in it: a zoomed day reaches past it, over the dimmed page (Process Budget.js). */
.budgetCard.calendarCard,
.budgetCard.pageCard {
  width: var(--PAGE_WIDTH);
  margin: 0 auto clamp(10px, 2.2vmin, 22px);
  padding: clamp(10px, 2vw, 22px) clamp(6px, 1.6vw, 20px) clamp(8px, 1.6vw, 18px);
}

.budgetCard.pageCard .dataScroll {
  width: 100%;
  margin-bottom: 1em;
}

.budgetCard.pageCard .elastic-table.historyGrid {
  margin-bottom: 0.5em;
}

/* A page's icon and title (and a line under it) */
.cardHeader {
  display: flex;
  align-items: center;
  gap: 0.8em;
  text-align: left;
  margin: 0 0 clamp(8px, 1.6vmin, 16px);
  padding: 0 clamp(2px, 0.6vw, 6px);
}

.cardHeading {
  min-width: 0;
}

.cardHeading .cardTitle {
  margin: 0;
  font-size: clamp(17px, 3.6vmin, 26px);
  font-weight: normal;
  line-height: 1.2;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.cardHeading .cardSubtitle {
  margin: 0.15em 0 0;
  font-size: clamp(12px, 2.4vmin, 16px);
  color: var(--TEXT_DIM);
}

/* An icon on its own little glowing tile */
.cardIcon {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: clamp(36px, 7vmin, 54px);
  height: clamp(36px, 7vmin, 54px);
  background: var(--TILE_FILL);
  border: 1px solid var(--GLASS_LINE);
  border-radius: 12px;
  box-shadow: 0 0 12px rgba(var(--GLOW_RGB), 0.25);
}

.cardIcon img {
  width: 62%;
  height: 62%;
  border-radius: 0;
  object-fit: contain;
  filter: drop-shadow(0 0 4px rgba(var(--GLOW_LIGHT_RGB), 0.6));
}

/* The calendar's dark blue icon, lifted to a bright neon blue */
.cardIcon img[src*="/Calendar."] {
  --ICON_LIFT: 2.8; /* (A theme's icon colors lift it the same way first: themes.css) */
  filter: brightness(2.8) drop-shadow(0 0 6px rgba(60, 120, 255, 0.95));
}

/*========================================*
 *  HOME: LOWEST IN BANK, BOB, AND UPCOMING
 *========================================*/

/* Lowest across the top; Bob and Upcoming side by side under it (one column on phones) */
.infoRow {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  grid-template-areas:
    "lowest lowest"
    "bob upcoming";
  gap: clamp(8px, 1.6vw, 18px);
  width: var(--PAGE_WIDTH);
  margin: 0 auto clamp(10px, 2.2vmin, 22px);
  text-align: left;
  font-size: clamp(12px, 2.3vmin, 17px);
}

.infoCard {
  padding: 0.9em 1em;
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: var(--GLASS_RADIUS);
  box-shadow: var(--GLASS_SHADOW);
}

.infoLabel {
  display: block;
  margin-bottom: 0.3em;
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

/* Lowest: the wallet, Lowest in bank after today, and at the right, the 28 days after the calendar (under it on
   phones), over a faint wave */
.lowestCard {
  grid-area: lowest;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.6em 1em;
  padding: 1em 1.2em 1.3em;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 60' preserveAspectRatio='none'><path d='M0 38 C 70 18, 130 56, 210 34 S 340 12, 400 30 L 400 60 L 0 60 Z' fill='rgba(90, 80, 230, 0.16)'/><path d='M0 48 C 90 30, 160 62, 240 44 S 350 30, 400 42 L 400 60 L 0 60 Z' fill='rgba(150, 70, 255, 0.14)'/></svg>") bottom / 100% 45% no-repeat,
    var(--GLASS);
}

/* Below $0 (today through the 28 days after the calendar): the card turns red, like a day below $0 */
.lowestCard.isNegative {
  border-color: var(--NEGATIVE_DAY_EDGE);
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 60' preserveAspectRatio='none'><path d='M0 38 C 70 18, 130 56, 210 34 S 340 12, 400 30 L 400 60 L 0 60 Z' fill='rgba(255, 70, 100, 0.16)'/><path d='M0 48 C 90 30, 160 62, 240 44 S 350 30, 400 42 L 400 60 L 0 60 Z' fill='rgba(200, 30, 80, 0.16)'/></svg>") bottom / 100% 45% no-repeat,
    var(--NEGATIVE_DAY_FILL);
  box-shadow: var(--GLASS_SHADOW), 0 0 16px rgba(255, 40, 60, 0.35);
}

.cardIcon.walletIcon {
  width: clamp(44px, 9vmin, 64px);
  height: clamp(44px, 9vmin, 64px);
  border-radius: 14px;
}

/* The card opens the 28 days after the calendar (Calendar Page.js openAheadDays): it lights up like Bob's, and says so
   at its bottom right */
.lowestCard {
  position: relative;
  cursor: pointer;
}

.lowestCard:hover,
.lowestCard:focus-visible {
  border-color: var(--GLASS_LINE_BRIGHT);
  box-shadow: var(--GLASS_SHADOW), var(--HOVER_SHADOW);
  outline: none;
}

.lowestMore {
  grid-column: 1 / -1;
  justify-self: end;
  margin-top: -0.2em;
  font-size: 0.8em;
  color: var(--TEXT_DIM);
}

/* The window: the lowest and the 28th day over four weeks of days, each a square with its date and In Bank (to the
   dollar); one below $0 is red, and the lowest is ringed */
.aheadSummary .negative {
  color: var(--NEGATIVE_TEXT);
}

.aheadGrid {
  width: 100%;
  table-layout: fixed;
  border-collapse: separate;
  border-spacing: clamp(2px, 0.8vw, 6px);
}

.aheadGrid th {
  padding: 0 0 0.3em;
  font-size: 0.7em;
  font-weight: normal;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--TEXT_DIM);
}

.aheadGrid td {
  padding: 0;
}

.budgetButton.aheadDay,
button.aheadDay {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2em;
  box-sizing: border-box;
  width: 100%;
  min-height: 3.4em;
  margin: 0;
  padding: 0.35em 0.1em;
  font: inherit;
  color: var(--TEXT_BRIGHT);
  background: var(--DAY_FILL);
  border: 0;
  border-radius: var(--DAY_RADIUS);
  box-shadow: inset 0 0 0 1px var(--DAY_EDGE);
  cursor: pointer;
}

button.aheadDay:hover,
button.aheadDay:focus-visible {
  background: var(--HOVER_GRADIENT);
  outline: none;
}

button.aheadDay.isNegative {
  background: var(--NEGATIVE_DAY_FILL);
  box-shadow: inset 0 0 0 1px var(--NEGATIVE_DAY_EDGE);
}

button.aheadDay.isLowest {
  box-shadow: inset 0 0 0 2px var(--PICK_EDGE), 0 0 10px rgba(var(--PICK_RGB), 0.45);
}

.aheadDate {
  font-size: clamp(11px, 0.85em, 15px);
  font-weight: bold;
  line-height: 1.1;
}

.aheadInBank {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: clamp(9px, 0.72em, 13px);
  font-variant-numeric: tabular-nums;
  color: var(--TEXT_DIM);
}

button.aheadDay.isNegative .aheadInBank {
  color: var(--NEGATIVE_ON_RED);
}

.lowestMain {
  min-width: 0;
}

.lowestAmount {
  display: block;
  font-size: 2.3em;
  line-height: 1.1;
  color: var(--TEXT_BRIGHT);
  text-shadow: 0 0 12px rgba(var(--HALO_RGB), 0.9);
}

.lowestAmount.negative,
.afterAmount.negative {
  color: var(--NEGATIVE_TEXT);
  text-shadow: 0 0 14px rgba(255, 60, 80, 0.45);
}

.afterCalendar {
  text-align: right;
}

.afterLine {
  margin: 0.2em 0 0;
  font-size: 1.05em;
  line-height: 1.35;
  color: var(--TEXT_BRIGHT);
}

.afterAmount {
  font-variant-numeric: tabular-nums;
}

@media (max-width: 560px) {
  .lowestCard {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .afterCalendar {
    grid-column: 1 / -1;
    padding-top: 0.6em;
    text-align: left;
    border-top: 1px solid var(--PANEL_LINE);
  }
}

/* Bob's card: his picture and message, which open his page (it lights up like the Menu's links), and under them, while
   he has any, his warnings and Okay */
.infoCard.bobCard {
  grid-area: bob;
  display: flex;
  flex-direction: column;
  gap: 0.8em;
  margin: 0;
  font-size: 1em;
  text-align: left;
  color: var(--BASE_COLOR);
  transition: transform var(--SLOW_TRANSFORM), box-shadow var(--SLOW_SHADOW), border-color var(--SLOW_BORDER);
}

.bobLink {
  display: flex;
  align-items: flex-start;
  gap: 0.9em;
  text-decoration: none;
  color: inherit;
  outline: none;
}

.infoCard.bobCard:has(.bobLink:hover),
.infoCard.bobCard:has(.bobLink:focus-visible) {
  transform: scale(1.02);
  text-shadow: none;
  outline: none;
  border-color: var(--GLOW_EDGE);
  background: var(--GLOW_FILL), var(--GLASS);
  box-shadow: var(--GLOW_SHADOW);
}

.upcomingCard {
  grid-area: upcoming;
}

/* Bob's picture, in a circle (it shows his name if it can't load), on Home and at the top of his page */
.bobImage {
  flex-shrink: 0;
  width: 12vmin;
  height: 12vmin;
  min-width: 52px;
  min-height: 52px;
  border-radius: 50%;
  background: var(--BOX_FILL);
  border: 2px solid var(--PANEL_BORDER);
  box-shadow: 0 0 12px rgba(var(--GLOW_RGB), 0.35);
  color: var(--BASE_COLOR);
  font-size: 0.8em;
  text-align: center;
  overflow: hidden;
}

.bobText {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.5em;
  min-width: 0;
}

.bobMessage {
  font-size: 1em;
  line-height: 1.4;
}

/* "More from Bob ›": the card opens his page */
.bobMore {
  align-self: flex-end;
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

.bobLink:hover .bobMore,
.bobLink:focus-visible .bobMore {
  color: var(--TEXT_BRIGHT);
}

/* His warnings (Bob's page, a card's Warnings switch): his card moves over the calendar (.bobAbove) with a red-orange
   edge, until Okay */
.bobAbove {
  width: var(--PAGE_WIDTH);
  margin: 0 auto clamp(10px, 2.2vmin, 22px);
  font-size: clamp(12px, 2.3vmin, 17px);
}

.bobAbove:empty {
  display: none;
}

.infoCard.bobCard.isWarning {
  border-color: #ff6a1a;
  box-shadow: var(--GLASS_SHADOW), 0 0 16px rgba(255, 106, 26, 0.35);
}

.bobWarnings {
  padding-top: 0.6em;
  border-top: 1px solid var(--PANEL_LINE);
}

.bobWarningsTitle {
  margin: 0;
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

.bobWarnings .panelButtons {
  margin-top: 0.7em;
}

.bobWarnings .panelHint {
  margin: 0.4em 0 0;
}

/* With his card over the calendar, Upcoming takes its place's room too */
.infoRow.bobAway {
  grid-template-areas:
    "lowest lowest"
    "upcoming upcoming";
}

/* Goals, on Bob's page (Bob Page.js renderGoalsCard): each one a button that opens it, with a thin bar for how
   far along it is and what Bob says reaching it takes */
.goalList {
  margin: 0.7em 0 0;
  padding: 0;
  list-style: none;
}

.goalItem + .goalItem {
  margin-top: 0.4em;
}

.goalButton {
  display: flex;
  flex-direction: column;
  gap: 0.2em;
  width: 100%;
  margin: 0;
  padding: 0.45em 0.6em;
  font: inherit;
  text-align: left;
  color: var(--BASE_COLOR);
  background: rgba(var(--WELL_RGB), 0.45);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
  cursor: pointer;
}

.goalButton:hover,
.goalButton:focus-visible {
  border-color: var(--PANEL_BORDER);
}

.goalTop {
  display: flex;
  justify-content: space-between;
  gap: 0.6em;
}

.goalTitle {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--TEXT_BRIGHT);
}

.goalStatus {
  flex-shrink: 0;
  font-size: 0.9em;
  color: var(--TEXT_DIM);
}

.goalItem.isReached .goalStatus {
  color: #7dffb0;
}

.goalDetails {
  font-size: 0.88em;
  line-height: 1.35;
  color: var(--TEXT_DIM);
}

.goalBar {
  display: block;
  height: 4px;
  overflow: hidden;
  background: rgba(var(--TINT_RGB), 0.08);
  border-radius: 2px;
}

.goalFill {
  display: block;
  height: 100%;
  background: var(--BAR_FILL);
  box-shadow: 0 0 6px rgba(var(--GLOW_RGB), 0.6);
}

.goalItem.isReached .goalFill {
  background: linear-gradient(90deg, #2fd88a, #7dffb0);
}

/* What Bob says about it; one in danger gets the red-orange edge */
.goalPlan {
  font-size: 0.88em;
  line-height: 1.4;
  color: var(--BASE_COLOR);
}

.goalItem.isDanger .goalButton {
  border-color: rgba(255, 110, 40, 0.75);
  box-shadow: 0 0 10px rgba(255, 69, 0, 0.3);
}

.goalItem.isDanger .goalStatus {
  color: #ff9a1a;
}

.upcomingList {
  max-height: 9.5em;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.upcomingItem {
  border-bottom: 1px solid var(--PANEL_LINE);
}

/* Each upcoming entry is a button that opens its options (Calendar Page.js renderInfoRow) */
.upcomingItem .upcomingButton {
  display: flex;
  gap: 0.6em;
  width: 100%;
  margin: 0;
  padding: 0.25em 0.3em;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: none;
  border-radius: 6px;
  box-shadow: none;
  cursor: pointer;
}

.upcomingItem .upcomingButton:hover,
.upcomingItem .upcomingButton:focus-visible {
  transform: none;
  text-shadow: none;
  outline: none;
  background: rgba(var(--TINT_RGB), 0.08);
  box-shadow: none;
}

/* New Entry: an entry with that title and type already on the day, and whether to add to it or set it */
.matchBox {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5em;
}

.matchNote .lineEntry {
  display: inline;
}

.upcomingDate {
  flex-shrink: 0;
  color: var(--TEXT_DIM);
}

.upcomingEmpty {
  opacity: 0.7;
}

/*========================================*
 *  HOME: THE CALENDAR'S BUTTONS
 *========================================*/

/* Undo over Redo at the left, New Entry (the prism) in the middle, and Search over Quick Entry at the right. Each
   side's buttons are as wide as each other. */
.controlsCard.homeControls {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-areas:
    "undo new search"
    "redo new quick";
  align-items: center;
  gap: clamp(6px, 1.4vmin, 14px) clamp(6px, 2vw, 28px);
  font-size: clamp(11px, 2.9vw, 16px);
}

.homeControls .budgetButton {
  font-size: 1em;
  padding: 0.5em clamp(0.5em, 1.6vw, 1.2em);
}

.homeUndo   { grid-area: undo;   justify-self: start; width: min(100%, 10em); }
.homeRedo   { grid-area: redo;   justify-self: start; width: min(100%, 10em); }
.homeSearch { grid-area: search; justify-self: end;   width: min(100%, 17em); }
.homeQuick  { grid-area: quick;  justify-self: end;   width: min(100%, 17em); }

/* Phones: Undo and Redo only as wide as they need, so Search and Quick Entry get the rest */
@media (max-width: 560px) {
  .controlsCard.homeControls {
    grid-template-columns: auto auto minmax(0, 1fr);
    column-gap: 6px;
  }

  .homeUndo,
  .homeRedo,
  .homeSearch,
  .homeQuick {
    justify-self: stretch;
    width: auto;
  }
}

/* Search reads like a search box: its glass and magnifying glass, and its word at the left */
.budgetButton.homeSearch {
  justify-content: flex-start;
  color: var(--TEXT_DIM);
}

.budgetButton.homeSearch:hover {
  color: var(--TEXT_HOT);
}

/* Quick Entry glows: a blue-violet radial gradient from its center and a bright edge (a recommended button, .primary,
   looks the same), and glows a little more under the pointer */
.budgetButton.homeQuick {
  color: var(--PRIMARY_TEXT);
  background: var(--GLOW_FILL), var(--RECOMMENDED_FILL);
  border-color: var(--GLOW_EDGE);
  box-shadow: var(--GLOW_SHADOW);
}

.budgetButton.homeQuick:not(:disabled):hover {
  box-shadow: var(--GLOW_SHADOW), 0 0 22px rgba(var(--GLOW_RGB), 0.6);
}

/* New Entry: the prism, with a + on it, and its name under it */
.newEntryButton {
  grid-area: new;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4em;
  margin: 0;
  padding: 0;
  font-size: 1em;
  color: var(--TEXT_BRIGHT);
  background: none;
  border: none;
  box-shadow: none;
}

.newEntryButton:hover {
  box-shadow: none;
}

/* The prism: a thin neon ring (NewEntryRing.webp, in Prismal's own colors) around a solid disk that glows like Quick
   Entry, with the + on it. Every other theme paints the ring in its own colors in the picture's shape (--RING_FILL,
   themes.css). */
.newEntryPrism {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: clamp(52px, 13vw, 84px);
  height: clamp(52px, 13vw, 84px);
  border-radius: 50%;
}

/* The disk: a blue-violet radial gradient from its center over Quick Entry's blue-to-violet, its edge under the ring.
   Its glow spreads from there, so it hugs the ring. */
.newEntryPrism::before {
  content: "";
  position: absolute;
  inset: 11%;
  border-radius: 50%;
  background: var(--GLOW_FILL), linear-gradient(90deg, rgb(30, 47, 139), rgb(80, 36, 145));
  box-shadow: 0 0 16px 2px rgba(var(--GLOW_RGB), 0.45), inset 0 0 12px rgba(var(--GLOW_RGB), 0.35);
  transition: box-shadow var(--SLOW_SHADOW);
}

.newEntryRing {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: url("/Resources/Icons/NewEntryRing.webp?v=9c8bd5e752") center / 100% 100% no-repeat;
}

/* Hovered or focused: the ring turns the chosen color (red to orange to gold), it glows that color, and so does the
   disk's edge */
.newEntryPrism::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 50%;
  background: var(--RING_HOVER_FILL);
  -webkit-mask: url("/Resources/Icons/NewEntryRing.webp?v=9c8bd5e752") center / 100% 100% no-repeat;
  mask: url("/Resources/Icons/NewEntryRing.webp?v=9c8bd5e752") center / 100% 100% no-repeat;
  opacity: 0;
  transition: opacity var(--SLOW_SHADOW);
}

.newEntryButton:hover .newEntryPrism::before,
.newEntryButton:focus-visible .newEntryPrism::before {
  box-shadow: 0 0 20px 4px rgba(var(--PICK_RGB), 0.6), inset 0 0 16px 2px rgba(var(--PICK_RGB), 0.6);
}

.newEntryButton:hover .newEntryPrism::after,
.newEntryButton:focus-visible .newEntryPrism::after {
  opacity: 1;
}

.newEntryPlus {
  position: relative;
  z-index: 2;
  font-size: 2.6em;
  line-height: 1;
  color: white; /* (On the prism, whatever the theme) */
  text-shadow: 0 0 6px rgba(0, 0, 0, 0.95), 0 0 2px #000;
}

/* Recurring Entries', History's, and Equity accounts' buttons fill their card's row (and wrap on phones) */
.controlsCard .tableToolbar {
  margin: 0;
  font-size: clamp(11px, 3.1vw, 16px);
}

.controlsCard .tableToolbar .budgetButton {
  font-size: 1em;
}

@media (max-width: 700px) {
  .infoRow {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "lowest"
      "bob"
      "upcoming";
  }

  .infoRow.bobAway {
    grid-template-areas:
      "lowest"
      "upcoming";
  }
}

/* Steps for each kind of phone (Layout.js wireDeviceGuide): a list picks the kind, and only its part shows. Without
   JavaScript, every part shows under its own name. */
.deviceGuide {
  margin: 0.6em 0 1em;
  padding: 0.7em 0.9em;
  text-align: left;
  background: rgba(var(--INSET_RGB), 0.22);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.deviceGuidePick {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5em;
  margin-bottom: 0.5em;
  font-size: 0.95em;
  color: var(--TEXT_DIM);
}

.deviceGuide .deviceSelect {
  width: auto;
  max-width: 100%;
  margin: 0;
  padding: 0.35em 0.7em;
  font-family: inherit;
  font-size: max(16px, 1em);
  color: var(--TEXT_BRIGHT);
  background: var(--BOX_FILL);
  border: 1.5px solid var(--PANEL_BORDER);
  border-radius: 10px;
}

.deviceGuide .deviceSelect option {
  background: var(--LIST_FILL);
}

.deviceGuide .deviceName {
  margin: 0.6em 0 0.2em;
  font-weight: bold;
  color: var(--TEXT_BRIGHT);
}

.deviceGuide.isPicking .deviceName {
  display: none;
}

.deviceGuide [data-device] > :first-child,
.deviceGuide [data-device] > .deviceName + * {
  margin-top: 0;
}

/* Quick Entry: In Bank today and the lowest it gets, side by side over the form (Quick Entry.js showQuickBalances) */
.quickBalances {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(8px, 1.6vw, 18px);
  width: min(94vw, 760px);
  margin: 0 auto 1em;
  font-size: clamp(13px, 2.6vmin, 18px);
}

.quickBalances[hidden] {
  display: none;
}

.quickBalance {
  padding: 0.7em 0.9em;
  text-align: center;
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: var(--GLASS_RADIUS);
  box-shadow: var(--GLASS_SHADOW);
}

.quickBalanceAmount {
  display: block;
  font-size: 1.7em;
  line-height: 1.15;
  color: var(--TEXT_BRIGHT);
  font-variant-numeric: tabular-nums;
}

.quickBalanceAmount.negative {
  color: var(--NEGATIVE_TEXT);
}

/* An Apple Watch (html.watchView, Quick Entry.js): In Bank today over the lowest it gets (with its day), big, and
   nothing else ("Loading..." until they're in) */
html.watchView #constellations,
html.watchView #transitionContainer > header,
html.watchView main > :not(.quickBalances):not(#dataStatus),
html.watchView .quickBalances:not([hidden]) ~ #dataStatus,
html.watchView footer[data-global-footer],
html.watchView #versionBadge {
  display: none;
}

html.watchView main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 90vh;
}

html.watchView .quickBalances {
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
  width: 100%;
  margin: 0;
}

html.watchView .quickBalance {
  padding: 0.45em 0.3em;
}

html.watchView .quickBalanceAmount {
  font-size: 1.8em;
}

/* Undo and Redo (the Quick Entry page's, above its form) */
.undoButtons {
  display: flex;
  gap: 1.2vmin;
  margin-right: auto;
}

/* The Quick Entry page's: just above its form, lined up with it (.budgetPanel.large's width), with Waiting at the right */
.undoButtons.quickUndo {
  justify-content: flex-start;
  width: min(94vw, 560px);
  margin: 0 auto -0.5vmin;
}

.undoButtons.quickUndo .waitingButton {
  margin-left: auto;
}

/* The card Waiting opens over the form: the entries this icon added that are still waiting, each with Change and ×
   (Quick Entry.js WAITING ENTRIES) */
.budgetCard.waitingSection {
  width: min(94vw, 560px);
  margin: 2.5vmin auto 0;
}

.waitingList {
  display: flex;
  flex-direction: column;
  gap: 0.45em;
  margin: 0;
  padding: 0;
  list-style: none;
}

.waitingItem {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.4em 0.45em 0.4em 0.75em;
  background: var(--BOX_FILL);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: 10px;
}

/* Its title (cut short with "..." when it's long) over its amount and day */
.waitingText {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
}

.waitingTitle {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--TEXT_BRIGHT);
}

.waitingDetails {
  font-size: 0.9em;
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
}

.waitingAmount.negative {
  color: var(--NEGATIVE_TEXT);
}

.waitingAmount.positive {
  color: var(--POSITIVE_TEXT);
}

.waitingItem .waitingChange {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.35em 0.9em;
  font-size: 0.9em;
}

.waitingItem .waitingDelete {
  flex: 0 0 auto;
}

/* Home's Quick Entries To Add (Calendar Page.js): the same rows, each with Add and Delete */
.budgetCard.quickWaiting {
  width: var(--PAGE_WIDTH);
  margin: 0 auto clamp(10px, 2vmin, 18px);
}

.quickWaiting h3 {
  margin: 0 0 0.3em;
}

.quickWaiting .panelHint {
  margin: 0 0 0.7em;
}

.waitingItem .waitingAdd,
.quickWaiting .waitingItem .waitingDelete {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.35em 0.9em;
  font-size: 0.9em;
}

/* One the budget has picked up: on its way in, so it can't be changed here */
.waitingItem.isJoining {
  opacity: 0.75;
}

.waitingJoining {
  flex: 0 0 auto;
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

.budgetCard.waitingSection #waitingNote {
  margin: 0.6em 0 0;
}

/* Change Entry (a waiting entry): the form glows blue-violet, so it's clear it's changing one, not adding one */
.budgetPanel.changeDraft {
  border-color: var(--GLOW_EDGE);
  box-shadow: var(--FLOAT_SHADOW), var(--GLOW_SHADOW);
}

/* Quick Entry's prisms: under its form, lined up with it. Add Prism, its ?, and Edit Prisms, then the
   prisms as buttons (or, in Edit Prisms, rows to drag and delete) */
.prismSection {
  box-sizing: border-box;
  width: min(94vw, 560px);
  margin: 0 auto 4vmin;
  font-size: var(--UI_TEXT);
  text-align: left;
}

.prismToolbar {
  display: flex;
  align-items: center;
  gap: 0.6em;
}

.prismToolbar .fieldHelpButton {
  margin: 0;
  font-size: 1em;
}

#editPrismsButton {
  margin-left: auto;
}

.prismHelp {
  margin-top: 0.7em;
}

.prismEmpty {
  margin: 0.8em 0 0;
}

.prismList {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em;
  margin: 0.8em 0 0;
  padding: 0;
  list-style: none;
}

.prismList:empty {
  display: none;
}

/* A long title ends in "..." instead of running off the screen */
.prismButton {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.prismList.isEditing {
  flex-direction: column;
  flex-wrap: nowrap;
}

.prismEditRow {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.35em 0.6em;
  background: var(--BOX_FILL);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: 10px;
}

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

/* The ≡ to hold and drag: the page doesn't scroll while it's held */
.prismHandle {
  padding: 0.1em 0.4em;
  font-size: 1.3em;
  line-height: 1;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.prismEditRow.dragging {
  border-color: var(--PICK_EDGE);
  box-shadow: 0 0 12px rgba(var(--PICK_RGB), 0.55);
  opacity: 0.85;
}

/* New Prism: the form glows, so it's clear it's making a prism, not adding an entry */
.budgetPanel.prismDraft {
  position: relative;
  box-shadow: var(--FLOAT_SHADOW), 0 0 22px rgba(var(--PICK_RGB), 0.7);
}

.prismDraftHint {
  margin: 0;
}

/* A short glow when a prism fills the form, or Add Prism turns it into New Prism */
.budgetPanel.prismFlash {
  animation: prismFlash 1.1s ease-out;
}

@keyframes prismFlash {
  0%   { box-shadow: 0 0 0 3px var(--LINK_LIGHT), 0 0 34px rgba(var(--PICK_RGB), 0.9); }
  100% { box-shadow: var(--FLOAT_SHADOW); }
}

@media (prefers-reduced-motion: reduce) {
  .budgetPanel.prismFlash {
    animation: none;
  }
}

html.lessMotion .budgetPanel.prismFlash {
  animation: none;
}

/* Recurring/Tracker toolbar */
.tableToolbar {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.2vmin;
  margin: 1vmin auto 2vmin;
}

.tableToolbar:empty {
  display: none;
}

/*========================================*
 *  RECURRING / TRACKER EDIT MODE
 *========================================*/

.dataTable tr.clickable {
  cursor: pointer;
}

.dataTable tr.clickable:hover td {
  filter: brightness(1.3);
}

.dataTable tr.selected td {
  background: rgba(var(--PICK_RGB), 0.22);
}

.dataTable .moveBar {
  width: 2.4em;
  text-align: center;
  font-size: 1.3em;
  cursor: grab;
  touch-action: none; /* Dragging the bar never scrolls the page */
  user-select: none;
  -webkit-user-select: none;
}

.dataTable .selectCell {
  width: 2.2em;
  text-align: center;
}

/* A row that can't be deleted (Savings on Equity) */
.dataTable .lockedRow {
  opacity: 0.7;
}

/* Equity: a narrower table, centered */
.dataTable.accountsTable {
  width: min(100%, 720px);
  margin: 0 auto;
}

/* An account's entries, in its panel: a box that scrolls up and down within it */
.accountEntries {
  max-height: min(18em, 45vh);
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
}

/* A balance with its max ("$500.00/$2000.00") can put the max under the balance, each staying whole, and a long account
   name takes more lines, so the table fits a narrow phone */
.accountsTable td.amountCell.withMax {
  white-space: normal;
}

.accountsTable td.amountCell.withMax > span {
  white-space: nowrap;
}

.accountsTable .titleCell {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* An account's entries (in its panel): every entry for it, newest first, each a button that opens its options. Its day,
   then the entry (red for a cost, green for a gain, darker grey for $0.00, yellow for a placeholder), then what the
   account got, at the right. A month's interest is laid out the same, but doesn't open. */
.accountEntryItem {
  border-bottom: 1px solid var(--PANEL_LINE);
}

.accountEntryItem .accountEntryButton {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15em 0.8em;
  width: 100%;
  margin: 0;
  padding: 0.4em 0.35em;
  font: inherit;
  font-variant-numeric: tabular-nums;
  text-align: left;
  color: var(--BASE_COLOR);
  background: none;
  border: none;
  border-radius: 6px;
  box-shadow: none;
  cursor: pointer;
}

.accountEntryItem.isInterest .accountEntryButton {
  cursor: default;
}

.accountEntryItem button.accountEntryButton:hover,
.accountEntryItem button.accountEntryButton:focus-visible {
  transform: none;
  outline: none;
  background: rgba(var(--TINT_RGB), 0.08);
  box-shadow: none;
}

.accountEntryButton .accountEntryDate {
  flex: 0 0 auto;
  color: var(--TEXT_DIM);
}

.accountEntryButton .accountEntryLine {
  flex: 1 1 12em;
  min-width: 0;
  overflow-wrap: anywhere;
}

.accountEntryButton .accountEntryAmount {
  flex: 0 0 auto;
  min-width: 0;
  margin-left: auto;
}

.sectionInsertRow td {
  padding: 0;
  text-align: center;
  background: none;
  border: none;
}

.sectionButton {
  margin: 0.15em auto;
  padding: 0.1em 0.9em;
  font-size: 0.8em;
  opacity: 0.55;
}

.sectionButton:hover {
  opacity: 1;
}

/* Hidden but still taking space, so rows don't jump when a drag starts */
.isDragging .sectionInsertRow {
  visibility: hidden;
}

.isDragging {
  user-select: none;
  -webkit-user-select: none;
}

.dataTable tr.dragRow td {
  background: rgba(var(--PICK_RGB), 0.3);
  box-shadow: 0 0 14px rgba(var(--PICK_RGB), 0.6);
}

.dataTable tr.dragRow .moveBar {
  cursor: grabbing;
}

/*========================================*
 *  CARDS (Paycheck Calculator, Settings)
 *========================================*/

/* Rounded content cards, same look as the home page's info row */
.budgetCard {
  box-sizing: border-box;
  width: min(94vw, 760px);
  margin: 0 auto 2.5vmin;
  padding: 1em 1.2em;
  text-align: left;
  font-size: var(--UI_TEXT);
  color: var(--BASE_COLOR);
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: var(--GLASS_RADIUS);
  box-shadow: var(--GLASS_SHADOW);
  user-select: text;
  -webkit-user-select: text;
}

.budgetCard h3 {
  margin: 0 0 0.6em;
  font-size: 1.3em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.budgetCard p {
  margin: 0 0 0.6em;
  font-size: 1em;
  line-height: 1.4;
}

/* Inputs inside cards (the global input style is a big centered pill) */
.budgetCard input[type="text"],
.budgetCard input[type="time"],
.budgetCard input[type="email"],
.budgetCard input[type="password"],
.budgetCard select {
  box-sizing: border-box;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0.5em 0.8em;
  font-family: var(--FONT);
  font-size: var(--UI_TEXT);
  text-align: left;
  color: var(--TEXT_BRIGHT);
  background: var(--BOX_FILL);
  border: 1.5px solid var(--PANEL_BORDER);
  border-radius: 10px;
  user-select: text;
  -webkit-user-select: text;
}

.budgetCard input[type="text"]:hover,
.budgetCard input[type="text"]:focus,
.budgetCard input[type="time"]:hover,
.budgetCard input[type="time"]:focus,
.budgetCard input[type="email"]:hover,
.budgetCard input[type="email"]:focus,
.budgetCard input[type="password"]:hover,
.budgetCard input[type="password"]:focus,
.budgetCard select:hover,
.budgetCard select:focus {
  transform: none;
  text-shadow: none;
  box-shadow: 0 0 10px rgba(var(--PICK_RGB), 0.55);
  outline: none;
}

.budgetCard .panelButtons {
  justify-content: flex-start;
}

/* Links that look like buttons (open calendar apps) */
a.budgetButton {
  margin: 0;
  padding: 0.45em 1.1em;
  color: var(--TEXT_BRIGHT);
  background: var(--GLASS_BUTTON);
  border: 1.5px solid var(--GLASS_LINE_BRIGHT);
  border-radius: 9999px;
  text-decoration: none;
  line-height: normal;
}

a.budgetButton:hover {
  transform: scale(1.05);
  color: var(--TEXT_HOT);
  text-shadow: 0 0 10px rgba(var(--PICK_RGB), 0.85);
  box-shadow: var(--PICK_SHADOW);
}

/* Budgets (Budgets.js): the picker's list, Share's list of people, and Settings' Budgets card. Each row is its name over
   a dimmer line (who it's shared with, or whose it is), with its buttons beside it; the open budget's row glows. */
.budgetLists {
  display: flex;
  flex-direction: column;
  gap: 0.2em;
}

.budgetListHeading {
  margin: 0.5em 0 0.3em;
  font-size: 0.85em;
  font-weight: normal;
  letter-spacing: 0.04em;
  color: var(--TEXT_DIM);
}

.budgetList {
  display: flex;
  flex-direction: column;
  gap: 0.4em;
  margin: 0;
  padding: 0;
  list-style: none;
}

.budgetList[hidden] {
  display: none;
}

.budgetPeople {
  margin-top: 0.4em;
}

.budgetManager {
  margin: 0.8em 0 1em;
}

.budgetItem {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45em;
  padding: 0.35em 0.45em 0.35em 0.4em;
  background: var(--BOX_FILL);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: 10px;
}

.budgetItem.isOpen {
  border-color: var(--GLOW_EDGE);
  background: var(--GLOW_FILL), var(--BOX_FILL);
  box-shadow: var(--GLOW_SHADOW);
}

/* The name and its line: a button that opens it in the picker's list, words in Settings and Share's list */
.budgetItem .budgetOpen {
  display: flex;
  flex: 1 1 10em;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1em;
  min-width: 0;
  margin: 0;
  padding: 0.25em 0.4em;
  font-size: 1em;
  line-height: 1.25;
  text-align: left;
  color: var(--TEXT_BRIGHT);
  background: none;
  border: none;
  border-radius: 8px;
  box-shadow: none;
}

.budgetItem button.budgetOpen:hover,
.budgetItem button.budgetOpen:focus-visible {
  transform: none;
  outline: none;
  background: rgba(var(--GLOW_RGB), 0.12);
  box-shadow: none;
}

.budgetName {
  max-width: 100%;
  overflow-wrap: anywhere;
}

.budgetDetail {
  font-size: 0.82em;
  color: var(--TEXT_DIM);
  overflow-wrap: anywhere;
}

.budgetItem .budgetShare,
.budgetInvitationButtons .budgetButton {
  flex: 0 0 auto;
  padding: 0.3em 0.85em;
  font-size: 0.85em;
}

.budgetInvitationButtons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4em;
}

/* Settings */
.settingsList {
  margin: 0 0 1em;
  padding: 0;
  list-style: none;
  line-height: 1.7;
}

/* Wrapped lines line up after the emoji */
.settingsList li {
  padding-left: 1.6em;
  text-indent: -1.6em;
}

/* Settings' Reminders: a switch for each kind, with what it's about under it */
.reminderKinds {
  display: flex;
  flex-direction: column;
  gap: 0.7em;
  margin: 0 0 1em;
}

.reminderKind {
  display: flex;
  flex-direction: column;
  gap: 0.2em;
}

/* Home's question right after a sign-in: turn notifications on here? (Notifications.js) */
.pushAsk h3 {
  margin: 0 0 0.4em;
}

.pushAsk .panelButtons {
  justify-content: flex-start;
}

/* A card's notes under its buttons (Push Notifications, Calendar Link): smaller, with plain bullets */
.settingsList.settingsNotes {
  margin: 1em 0 0;
  padding-left: 1.2em;
  list-style: disc;
  font-size: 0.85em;
  line-height: 1.5;
  opacity: 0.8;
}

.settingsList.settingsNotes li {
  padding-left: 0;
  text-indent: 0;
}

.settingsList.settingsNotes li + li {
  margin-top: 0.45em;
}

.settingsField {
  display: flex;
  flex-direction: column;
  gap: 0.3em;
  margin: 0 0 0.4em;
  font-size: 1em; /* The global label is much bigger */
}

.budgetCard .settingsField .timeInput {
  width: auto;
  min-width: 10em;
  align-self: flex-start;
}

.budgetCard .linkInput {
  margin-bottom: 0.8em;
  font-size: 0.85em;
}

/* Account forms (the global form centers everything) */
.settingsForm {
  align-items: stretch;
}

/* A pill switch in a Settings card (like Show balances on Quick Entry icons), and what it does under it */
.budgetCard .settingsSwitch {
  margin: 1em 0 0.3em;
}

/* The Spreadsheets & Calendars page's note that other emails are added in Settings */
.budgetCard .sheetsOtherEmails {
  margin: 1em 0 0;
}

.settingsForm .panelButtons {
  margin-top: 0.6em;
}

/* A second part of a Settings card (like "Forgot It?" under Change Password) */
.budgetCard .settingsSubheading {
  margin: 1.4em 0 0.4em;
  padding-top: 1em;
  font-size: 1.05em;
  font-weight: normal;
  border-top: 1px solid var(--PANEL_LINE);
}

/* Passkeys and Other Emails (Settings): each one's name and details, with its buttons beside it */
.passkeyList,
.sheetEmailList {
  margin: 0.8em 0 1em;
  padding: 0;
  list-style: none;
}

.passkeyItem,
.sheetEmailItem {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5em 1em;
  padding: 0.6em 0;
  border-top: 1px solid var(--PANEL_BORDER);
}

.passkeyItem:last-child,
.sheetEmailItem:last-child {
  border-bottom: 1px solid var(--PANEL_BORDER);
}

.passkeyAbout,
.sheetEmailAbout {
  display: flex;
  flex-direction: column;
  gap: 0.15em;
  min-width: 0;
  overflow-wrap: anywhere;
}

.sheetEmailButtons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em;
}

/* Connected spreadsheets (the Spreadsheets & Calendars page): each one's button, On/Off switch, and Delete, with a box
   under it when something needs a look */
.sheetList {
  margin: 0.8em 0 1em;
  padding: 0;
  list-style: none;
}

.sheetItem {
  padding: 0.6em 0;
  border-top: 1px solid var(--PANEL_BORDER);
}

.sheetItem:last-child {
  border-bottom: 1px solid var(--PANEL_BORDER);
}

.sheetEmpty {
  padding: 0.5em 0;
  border: none;
}

.sheetRow {
  display: flex;
  align-items: center;
  gap: 0.6em;
}

.budgetButton.sheetButton {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1em;
  min-width: 0;
  margin: 0;
  padding: 0.45em 1em;
  text-align: left;
  border-radius: 14px;
}

.sheetName {
  overflow-wrap: anywhere;
}

.sheetCount {
  font-size: 0.8em;
  opacity: 0.7;
}

.sheetItem.isOff .sheetButton {
  opacity: 0.6;
}

.sheetSwitch,
.budgetButton.sheetDelete {
  flex: 0 0 auto;
  margin: 0;
}

/* "Needs a look": a connected spreadsheet's problems (Spreadsheets), and recurring entries that match another one
   (Recurring Entries) */
.sheetProblems,
.recurringProblems {
  margin-top: 0.55em;
  padding: 0.5em 0.8em;
  font-size: 0.9em;
  line-height: 1.4;
  text-align: left;
  background: rgba(120, 0, 0, 0.25);
  border: 1px solid rgba(255, 90, 90, 0.55);
  border-radius: 10px;
}

.sheetProblems ul,
.recurringProblems ul {
  margin: 0.3em 0 0;
  padding-left: 1.1em;
}

.sheetProblems li + li,
.recurringProblems li + li {
  margin-top: 0.3em;
}

/* Over the Recurring Entries table (Budget Pages.js) */
.recurringProblems {
  margin: 0 auto 3vmin;
  font-size: var(--UI_TEXT);
}

/* Connecting a spreadsheet needs a verified email: until it is, this note says so (with Send Verification Email) */
.sheetsVerify {
  margin-top: 0.8em;
  padding: 0.5em 0.9em;
  text-align: left;
  background: rgba(var(--YELLOW_RGB), 0.1);
  border: 1px solid rgba(var(--YELLOW_RGB), 0.6);
  border-radius: 10px;
}

.sheetsVerify p {
  margin: 0.2em 0 0.5em;
}

/* Its panel: the link, then the entry form, which grows in once the spreadsheet opens */
.sheetOpened {
  margin: -0.3em 0 0;
}

.sheetForm {
  display: flex;
  flex-direction: column;
  gap: 0.75em;
}

.sheetForm.isOpening {
  animation: sheetFormIn 0.5s ease-out;
}

@keyframes sheetFormIn {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sheetForm.isOpening {
    animation: none;
  }
}

html.lessMotion .sheetForm.isOpening {
  animation: none;
}

/* A part of an entry: its yellow ➕, then what's typed, or the cells it comes from */
.sheetLine {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.sheetTyped {
  flex: 1 1 auto;
  min-width: 0;
}

.sheetPick {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2em;
  height: 2.2em;
  margin: 0;
  padding: 0;
  font-size: 1em;
  line-height: 1;
  background: rgba(var(--YELLOW_RGB), 0.12);
  border: 2px solid rgba(var(--YELLOW_RGB), 0.7);
  border-radius: 50%;
}

.sheetPick .sprite {
  width: 1.2em;
  height: 1.2em;
}

.sheetPick:hover,
.sheetPick:focus-visible {
  transform: scale(1.08);
  box-shadow: 0 0 10px rgba(var(--YELLOW_RGB), 0.65);
}

/* Picked: filled in */
.sheetPick.isLinked {
  background: rgba(var(--YELLOW_RGB), 0.38);
  border-color: rgb(var(--YELLOW_RGB));
  box-shadow: 0 0 8px rgba(var(--YELLOW_RGB), 0.5);
}

/* The cells it comes from (tap to change them) */
.sheetCells {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: 0.45em 0.9em;
  font-size: 1em;
  text-align: left;
  overflow-wrap: anywhere;
  color: var(--BASE_COLOR);
  background: rgba(var(--INSET_RGB), 0.35);
  border: 2px solid rgba(var(--YELLOW_RGB), 0.7);
  border-radius: 10px;
}

.sheetSign {
  margin-left: 2.7em;
}

/* What it finds: entries from today on, and problems */
.sheetPreview {
  font-size: 0.95em;
}

.sheetPreviewHeading {
  margin: 0 0 0.3em;
  font-size: 1em;
}

.sheetPreviewList {
  margin: 0;
  padding: 0.45em 0.7em;
  list-style: none;
  background: rgba(var(--INSET_RGB), 0.35);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.sheetPreviewList li {
  line-height: 1.6;
}

.sheetPreviewList li.positive {
  color: var(--POSITIVE_TEXT);
}

.sheetPreviewDate {
  display: inline-block;
  min-width: 3.2em;
  opacity: 0.75;
}

/* The ➕ panel: the spreadsheet's tabs, and Column / Row boxes */
.sheetTabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em;
}

.sheetTabs .budgetButton {
  margin: 0;
  padding: 0.3em 0.8em;
  font-size: 0.9em;
}

.rangeBoxes {
  display: flex;
  flex-direction: column;
  gap: 0.45em;
}

.rangeLine {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4em;
}

.rangeWord {
  font-size: 0.9em;
}

.rangeWord:first-child {
  min-width: 2.6em;
  opacity: 0.75;
}

.budgetPanel input.rangeInput {
  flex: 0 0 4.5em;
  width: 4.5em;
  text-align: center;
  text-transform: uppercase;
}

.budgetPanel input.rangeInput.rangeRow {
  flex-basis: 5.5em;
  width: 5.5em;
}

.sheetRangeFound {
  margin: 0;
  font-size: 0.9em;
  overflow-wrap: anywhere;
}

.sheetRangeFound.isProblem {
  color: var(--NEGATIVE_TEXT);
}

/* Connected calendars (Calendars Page.js): like spreadsheets, with Paychecks And Shifts and what the last read found
   under each one */
.calendarsVerify {
  margin: 0.6em 0 0;
}

/* (Its count names the next paycheck too, so it wraps instead of running under the switch) */
.calendarItem .budgetButton.sheetButton {
  white-space: normal;
}

.calendarMore {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3em 0.8em;
  margin-top: 0.45em;
}

.budgetButton.calendarPayButton {
  margin: 0;
  padding: 0.35em 0.9em;
  font-size: 0.9em;
}

.calendarStatus {
  overflow-wrap: anywhere;
}

/* Its panel: parts in boxes, the pay's versions as tabs over their boxes, and title rules as cards */
.calendarPart {
  display: flex;
  flex-direction: column;
  gap: 0.7em;
  margin: 0;
}

.calendarVersions,
.calendarCrystalButtons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4em;
}

.calendarVersions .budgetButton,
.calendarCrystalButtons .budgetButton,
.budgetButton.calendarAddRule {
  margin: 0;
  padding: 0.35em 0.9em;
  font-size: 0.9em;
}

/* Pay Change's "?" sits beside it, and the explanations of Pay Change and Pay By Event Title open under their row */
.calendarVersions .fieldHelpButton {
  align-self: center;
  margin: 0;
}

.calendarHelp {
  margin: 0.6em 0 0.2em;
}

.budgetButton.calendarVersionTab.isPicked {
  color: var(--TEXT_HOT);
  border-color: rgb(var(--YELLOW_RGB));
  box-shadow: 0 0 10px rgba(var(--YELLOW_RGB), 0.5);
}

.budgetButton.calendarVersionAdd {
  border-style: dashed;
}

.calendarCrystals {
  display: flex;
  flex-direction: column;
  gap: 0.35em;
}

.calendarCrystals:empty {
  display: none;
}

.calendarVersion {
  display: flex;
  flex-direction: column;
  gap: 0.7em;
}

/* A section of the pay's boxes (like the Paycheck Calculator's), and a title rule: each opens and closes by its name */
.calendarGroup,
.calendarRule {
  margin: 0;
  padding: 0.35em 0.8em;
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.calendarRule {
  border-color: var(--PANEL_BORDER);
}

.calendarGroup > summary,
.calendarRule > summary {
  padding: 0.3em 0;
  font-size: 0.95em;
  color: var(--TEXT_BRIGHT);
  overflow-wrap: anywhere;
  cursor: pointer;
}

.calendarGroup[open] > summary,
.calendarRule[open] > summary {
  margin-bottom: 0.45em;
}

.calendarGroup[open],
.calendarRule[open] {
  padding-bottom: 0.8em;
}

.calendarGroupNote {
  font-size: 0.85em;
  color: rgb(var(--YELLOW_RGB));
}

.calendarGroupBoxes,
.calendarRuleGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15em), 1fr));
  gap: 0.6em 1em;
  align-items: start;
}

.budgetPanel input.calendarNumber {
  font-variant-numeric: tabular-nums;
}

.budgetPanel .unitInput input.calendarNumber {
  padding-right: 3.6em;
}

/* A box that can't be read (it isn't a number or a day) */
.budgetPanel input.isWrong {
  border-color: var(--NEGATIVE_TEXT);
  box-shadow: 0 0 8px rgba(255, 60, 60, 0.45);
}

/* Two boxes on a line, with words between them (night hours, an unpaid break, paydays) */
.calendarPair {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4em;
}

.calendarPair > select,
.calendarPair > .unitInput {
  flex: 1 1 6em;
  min-width: 0;
}

.budgetPanel input[type="time"] {
  box-sizing: border-box;
  flex: 1 1 7em;
  min-width: 0;
  margin: 0;
  padding: 0.45em 0.6em;
  font-family: var(--FONT);
  font-size: var(--UI_TEXT);
  color: var(--TEXT_BRIGHT);
  color-scheme: dark;
  background: var(--BOX_FILL);
  border: 1.5px solid var(--PANEL_BORDER);
  border-radius: 10px;
}

@media (pointer: coarse) {
  .budgetPanel input[type="time"] {
    font-size: max(16px, var(--UI_TEXT));
  }
}

.calendarRules {
  display: flex;
  flex-direction: column;
  gap: 0.7em;
}

.calendarRule .panelButtons {
  justify-content: flex-start;
  margin-top: 0.6em;
}

/* Paychecks And Shifts: this year's totals, the schedule, and every paycheck */
.calendarPayView {
  display: flex;
  flex-direction: column;
  gap: 0.8em;
  text-align: left;
}

.paycheckResults.calendarTotals {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5em), 1fr));
  width: 100%;
  margin: 0;
  font-size: 0.9em;
}

.calendarTotals .paycheckAmount {
  font-size: 1.35em;
}

.calendarTotals .takeHome .paycheckAmount {
  font-size: 1.6em;
}

/* (Sized here: the site's own p and h4 are the front page's big ones) */
.calendarNext {
  margin: 0;
  font-size: 1em;
  line-height: 1.4;
}

.calendarSchedule h4,
.calendarPaychecks h4,
.calendarPaycheckShifts h4 {
  margin: 0 0 0.4em;
  font-size: 1.05em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
}

.calendarScheduleNav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6em;
  margin-bottom: 0.4em;
}

.budgetButton.calendarScheduleMove {
  margin: 0;
  padding: 0.15em 0.8em;
  font-size: 1.2em;
}

.calendarScheduleRange {
  font-size: 0.9em;
  opacity: 0.8;
}

.calendarScheduleGrid {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.78em;
}

.calendarScheduleRow {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr)) 3.2em;
  gap: 2px;
}

.calendarScheduleHead {
  padding: 0.2em;
  text-align: center;
  opacity: 0.75;
}

.calendarScheduleDay {
  display: flex;
  flex-direction: column;
  gap: 0.25em;
  min-height: 3.6em;
  min-width: 0;
  padding: 0.25em;
  background: rgba(var(--WELL_RGB), 0.55);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 6px;
}

.calendarScheduleDay.isToday {
  border-color: rgb(0, 230, 255);
  box-shadow: 0 0 8px rgba(0, 230, 255, 0.45);
}

.calendarScheduleDate {
  opacity: 0.75;
}

.calendarScheduleWeekday {
  display: none;
}

.calendarShift {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow-wrap: anywhere;
}

.calendarShift.isLong {
  padding-left: 0.3em;
  border-left: 2px solid rgba(0, 220, 120, 0.8);
}

.calendarShift.isPremium .calendarShiftTime {
  color: rgb(var(--YELLOW_RGB));
}

.calendarShiftTitle {
  opacity: 0.8;
}

.calendarPayday {
  color: var(--POSITIVE_TEXT);
  overflow-wrap: anywhere;
}

.calendarScheduleHours {
  align-self: center;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Phones: each week is a list of its days, each day's shifts beside it */
@media (max-width: 560px) {
  .calendarScheduleRow {
    display: flex;
    flex-direction: column;
    margin-bottom: 0.5em;
  }

  .calendarScheduleRow.isHead {
    display: none;
  }

  .calendarScheduleDay {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.2em 0.7em;
    min-height: 0;
  }

  .calendarScheduleWeekday {
    display: inline;
    opacity: 0.75;
  }

  .calendarScheduleHours::before {
    content: "Week's hours: ";
    opacity: 0.75;
  }

  .calendarScheduleHours {
    text-align: right;
  }
}

.calendarPaycheckList,
.calendarShiftList {
  display: flex;
  flex-direction: column;
  gap: 0.45em;
  margin: 0;
  padding: 0;
  list-style: none;
}

.budgetButton.calendarPaycheck {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.2em;
  width: 100%;
  margin: 0;
  padding: 0.5em 0.9em;
  text-align: left;
  border-radius: 12px;
}

.calendarPaycheckTop {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2em 0.8em;
}

.calendarPaycheckStatus {
  margin-left: auto;
  font-size: 0.85em;
  opacity: 0.75;
}

.calendarPaycheckStatus.isUpcoming {
  color: rgb(0, 230, 255);
  opacity: 1;
}

.calendarPaycheckHours,
.calendarPaycheckMoney,
.calendarShiftKind {
  font-size: 0.85em;
  opacity: 0.8;
}

.calendarPaycheckTake {
  font-variant-numeric: tabular-nums;
}

.calendarShiftList li {
  padding: 0.35em 0.6em;
  overflow-wrap: anywhere;
  background: rgba(var(--WELL_RGB), 0.45);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 8px;
}

/* A panel opened over another one: the one under it waits, dimmed */
.budgetPanel.isUnder {
  filter: brightness(0.55);
}

.budgetPanel.large.floating.stacked {
  z-index: 1310;
  top: calc(max(2vh, env(safe-area-inset-top, 0px)) + 1.2em);
}

/* Settings' birth date: its box and calendar button, as wide as a date needs */
.budgetCard .settingsField .ageRow {
  width: min(100%, 15em);
}

/* Help: the Help button at the bottom of a page, just under the footer's line (Layout.js moves it there), opens the
   page's help, floating over a dimmed page. The word in a small pill (its padding follows the panels' text size, the
   word a little bigger on big screens). */
.helpButton {
  display: flex;
  width: fit-content;
  align-items: center;
  justify-content: center;
  margin: 0 auto 0.5vmin;
  padding: calc(var(--UI_TEXT) * 0.35) calc(var(--UI_TEXT) * 1.1);
  font-size: max(12px, 2.4vmin);
  line-height: 1.1;
}

/* (A footer with the Help button keeps it close under its line) */
footer.hasHelp > hr {
  margin-bottom: max(8px, 1.5vmin);
}

/* Help floats over the page like a large panel: a long one runs past the screen's bottom, and the page scrolls to the
   rest of it */
.budgetCard.helpView {
  position: fixed;
  z-index: 1500;
  top: max(3vh, env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  margin: 0 auto;
  line-height: 1.45;
  background: var(--HOVER_GRADIENT);
  border-color: var(--PANEL_BORDER);
  box-shadow: var(--FLOAT_SHADOW);
}

/* Stays at the top right while the help scrolls */
.helpClose {
  position: sticky;
  top: 0;
  float: right;
  margin: -0.3em -0.4em 0 0.5em;
}

/* Help's dimmed backdrop: in <body>, fixed over the whole window (just under the screen layer, where the help is), so it
   covers the page however it's scrolled while the help is open (Layout.js) */
.overlayBackdrop {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: rgba(var(--SHADE_RGB), 0.6);
}

.helpView h4 {
  margin: 1.2em 0 0.4em;
  font-size: 1.1em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.helpView ul,
.helpView ol {
  margin: 0 0 0.8em;
  padding-left: 1.4em;
}

.helpView li {
  margin-bottom: 0.4em;
}

.helpView li > ol {
  margin: 0.4em 0 0;
}

/* Paycheck Calculator */
.paycheckResults {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5vmin;
  width: min(94vw, 760px);
  margin: 1vmin auto 2.5vmin;
  text-align: left;
  font-size: clamp(12px, 2.3vmin, 17px);
}

.paycheckAmount {
  font-size: 1.8em;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 12px rgba(var(--HALO_RGB), 0.9);
}

.takeHome .paycheckAmount {
  font-size: 2.3em;
}

.breakdownList {
  margin: 0;
}

.breakdownRow {
  display: flex;
  justify-content: space-between;
  gap: 1em;
  padding: 0.25em 0;
  border-bottom: 1px solid var(--PANEL_LINE);
}

.breakdownRow dt,
.breakdownRow dd {
  margin: 0;
}

.breakdownRow dd {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.breakdownRow.total {
  font-weight: bold;
  border-bottom-color: var(--PANEL_BORDER);
}

.calculatorForm {
  align-items: stretch; /* The global form centers everything */
}

.calculatorSection {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 14em), 1fr));
  gap: 0.7em 1em;
  margin: 0 0 0.8em;
  padding: 0.6em 0.9em 0.9em;
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.calculatorSection legend {
  padding: 0 0.4em;
  font-size: 1.05em;
}

.unitInput {
  position: relative;
  display: flex;
  align-items: center;
}

.budgetCard .unitInput input[type="text"] {
  padding-right: 3.6em;
  font-variant-numeric: tabular-nums;
}

.inputUnit {
  position: absolute;
  right: 0.8em;
  font-size: 0.85em;
  opacity: 0.6;
  pointer-events: none;
}

@media (max-width: 700px) {
  .paycheckResults {
    grid-template-columns: 1fr;
  }
}

/* The calculators' crystals and gems (Budget Pages.js presetShelf): like Quick Entry's prisms, in a card over the form.
   Add, its ?, and Edit, then the presets as buttons (or, in Edit, rows to drag and delete) */
.presetShelf {
  text-align: left;
}

.presetShelf h3 {
  margin: 0 0 0.6em;
}

.presetShelf .presetEdit {
  margin-left: auto;
}

/* Making one: its name, what to do, and Save or Cancel, while the calculator under it glows */
.presetDraftBox {
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  margin-top: 0.8em;
  padding: 0.7em 0.8em;
  background: rgba(var(--INSET_RGB), 0.3);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.presetDraftBox .panelHint,
.presetDraftBox .panelError {
  margin: 0;
}

.calculatorForm.presetDraft {
  position: relative;
  box-shadow: var(--GLASS_SHADOW), 0 0 22px rgba(var(--PICK_RGB), 0.7);
}

/* A short glow when a crystal or gem fills it */
.calculatorForm.prismFlash {
  animation: prismFlash 1.1s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .calculatorForm.prismFlash {
    animation: none;
  }
}

html.lessMotion .calculatorForm.prismFlash {
  animation: none;
}

/* Debt Calculator (menu/payments.html): its gems, the form, its results, and an Equity account's own pace with its
   entries, one card over another */
.paymentsPage {
  display: flex;
  flex-direction: column;
  gap: 2vmin;
}

.paymentsResults,
.paymentsAccount {
  text-align: left;
}

.paymentsLine {
  margin: 0 0 0.6em;
  line-height: 1.45;
}

/* Each payment, in a box that scrolls */
.paymentsSchedule {
  max-height: min(22em, 55vh);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.scheduleTable {
  width: 100%;
  font-variant-numeric: tabular-nums;
}

/* "Coming up" and "Today and before" in an account's entries */
.accountEntriesHeading {
  padding: 0.6em 0.35em 0.25em;
  font-size: 0.9em;
  color: var(--TEXT_DIM);
  border-bottom: 1px solid var(--PANEL_LINE);
}

/*========================================*
 *  BOB'S PAGE (menu/bob.html, Bob Page.js)
 *========================================*
 *  A column of glass cards: his highlights (with his picture) at the top, then each card with its title, a ? after it,
 *  and its switch at the right. A card that's off is only its title row, dimmed.
 */

.budgetCard.bobTop {
  display: flex;
  align-items: flex-start;
  gap: 1em;
}

.bobTop .bobImage {
  width: 16vmin;
  height: 16vmin;
  min-width: 64px;
  min-height: 64px;
}

.bobTopText {
  flex: 1 1 auto;
  min-width: 0;
}

/* One line from each card that's on; a line that needs a look has the red-orange edge, and the note about the cards
   that are off is quieter */
.bobHighlights {
  margin: 0;
  padding: 0;
  list-style: none;
}

.bobHighlight {
  margin: 0.45em 0 0;
  padding: 0.1em 0 0.1em 0.7em;
  line-height: 1.4;
  border-left: 2px solid var(--PANEL_BORDER);
}

.bobHighlight strong {
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
}

.bobHighlight.isWarning {
  border-left-color: #ff6a1a;
}

.bobHighlight.isQuiet {
  color: var(--TEXT_DIM);
  border-left-color: transparent;
}

/* A card's title row: its title, the ? right after it, and its switch at the right */
.sectionHead {
  display: flex;
  align-items: center;
  gap: 0.2em;
  min-width: 0;
}

.sectionTitle {
  margin: 0;
  font-size: 1.3em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.sectionHelpButton {
  flex-shrink: 0;
  font-size: 0.95em;
}

.sectionSwitch {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.5em;
  margin: 0 0 0 auto;
  padding-left: 0.6em;
  font-size: 1em; /* The global label is much bigger */
  cursor: pointer;
}

.sectionState {
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

/* A card's Warnings switch comes just before its On/Off one (and the two go under the title when they don't fit) */
.sectionHead {
  flex-wrap: wrap;
  row-gap: 0.4em;
}

.sectionSwitch + .sectionSwitch {
  margin-left: 0;
}

.sectionHelp {
  margin: 0.6em 0 0;
  padding: 0.55em 0.8em;
  font-size: 0.9em;
  line-height: 1.45;
  background: rgba(var(--INSET_RGB), 0.35);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.sectionBody {
  margin-top: 0.8em;
}

.budgetCard.bobSection.isOff {
  background: var(--PANEL_DARK);
  box-shadow: none;
}

.bobSection.isOff .sectionTitle {
  color: var(--BASE_COLOR);
  text-shadow: none;
}

.bobSection .panelButtons.sectionButtons {
  margin: 0 0 0.7em;
}

.bobTip {
  line-height: 1.45;
}

/* A tip's button for what's behind it ("See paydays ›") */
.budgetButton.tipMore {
  margin: 0.2em 0 0;
  padding: 0.35em 1em;
  font-size: 0.9em;
}

.bobList {
  margin: 0.2em 0 0;
  padding-left: 1.2em;
  line-height: 1.45;
}

/* Data: a row each, what it is (with a note under it) at the left and its figure at the right; a row with more behind it
   is a button with a › */
.bobData {
  margin: 0;
  padding: 0;
  list-style: none;
}

.bobDataItem + .bobDataItem {
  border-top: 1px solid var(--PANEL_LINE);
}

.bobDataRow {
  display: flex;
  align-items: center;
  gap: 0.8em;
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  padding: 0.55em 0.3em;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: none;
  border-radius: 8px;
}

button.bobDataRow {
  cursor: pointer;
}

button.bobDataRow:hover,
button.bobDataRow:focus-visible {
  transform: none;
  outline: none;
  background: rgba(var(--GLOW_RGB), 0.14);
  box-shadow: inset 0 0 0 1px var(--PANEL_BORDER);
}

.bobDataText {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.15em;
  min-width: 0;
}

.bobDataLabel {
  color: var(--TEXT_BRIGHT);
}

.bobDataNote {
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

.bobDataValue {
  flex-shrink: 0;
  max-width: 45%;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--TEXT_BRIGHT);
}

.bobDataValue.negative {
  color: var(--NEGATIVE_TEXT);
}

.bobDataMore {
  flex-shrink: 0;
  font-size: 1.2em;
  color: var(--TEXT_DIM);
}

/* Accounts: the table, with the day's box at the top of its third column; the Total row stands out, and the Interest
   column only shows when an account has interest */
.bobAccountsBox {
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--GLOW_LIGHT_RGB), 0.45) transparent;
}

.dataTable.bobAccounts {
  font-size: 1em;
}

.bobAccounts th {
  font-size: 1em;
}

.bobAccounts th.dayHead {
  min-width: 9.5em;
  padding: 0.5vmin 1vmin;
}

.bobAccounts .dayHead .dateRow {
  justify-content: center;
  gap: 0.3em;
}

/* Just wide enough for its date */
.bobAccounts .dayHead .dateRow input.dateInput {
  flex: none;
  width: 6.6em;
  padding: 0.3em 0.25em;
  font-size: 0.95em;
  text-align: center;
}

.bobAccounts.noInterest .interestHead,
.bobAccounts.noInterest .interestCell {
  display: none;
}

.bobAccounts .accountMax,
.bobAccounts .interestRate {
  display: block;
  font-size: 0.8em;
  color: var(--TEXT_DIM);
}

.bobAccounts tr.totalRow td {
  color: var(--TEXT_BRIGHT);
  background: var(--PANEL_DEEP);
}

.bobAccounts tr.totalRow td.negative {
  color: var(--NEGATIVE_TEXT);
}

.bobAccountsNote {
  margin: 0.5em 0 0;
}

.bobAccountsNote.isError {
  color: var(--NEGATIVE_TEXT);
  opacity: 1;
}

/* A window's table or list, in a box that scrolls up and down within it (the window stays on the screen) */
.bobScroll {
  max-height: min(55vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--GLOW_LIGHT_RGB), 0.45) transparent;
}

.dataTable.bobTable {
  font-size: 0.95em;
}

.bobTable td,
.bobTable th {
  white-space: normal;
}

.bobTable td.amountCell {
  white-space: nowrap;
}

/* Wavelength Planning: the days and the Wavelengths button, then the spectrum, what it says, and its legend under it */
.wavelengthControls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6em 1em;
  margin: 0 0 0.8em;
}

.wavelengthControls .purposeDates {
  flex: 1 1 26em;
  margin: 0;
}

.budgetButton.wavelengthsButton {
  margin: 0;
  padding: 0.4em 1em;
  font-size: 0.9em;
}

.wavelengthsHint {
  flex: 1 1 100%;
  margin: 0;
}

.purposeDates {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6em 1em;
  margin: 0 0 0.8em;
}

.purposeDate {
  display: flex;
  flex: 1 1 13em;
  flex-direction: column;
  gap: 0.3em;
  min-width: 0;
}

/* The spectrum: a glowing bar with each wavelength's stretch of the wave in its color (wavelengthSpectrum in
   Bob Page.js) */
.spectrumBox {
  display: flex;
  flex-direction: column;
  gap: 0.5em;
}

.spectrum {
  display: block;
  width: 100%;
  height: clamp(72px, 16vmin, 120px);
  overflow: visible;
}

.spectrumBand {
  opacity: 0.16;
}

.spectrumStretch {
  cursor: pointer;
  outline: none;
  transition: opacity 0.15s ease-out;
}

.spectrumHit {
  opacity: 0.1;
  transition: opacity 0.15s ease-out;
}

.spectrumWave {
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 4px currentColor);
}

/* The stretch pointed at (or tabbed to) lights up, and the others step back */
.spectrum:hover .spectrumStretch:not(:hover),
.spectrum:focus-within .spectrumStretch:not(:focus) {
  opacity: 0.45;
}

.spectrumStretch:hover .spectrumHit,
.spectrumStretch:focus-visible .spectrumHit {
  opacity: 0.28;
}

.spectrumCaption {
  margin: 0;
  font-size: 0.9em;
  text-align: center;
  color: var(--TEXT_DIM);
}

.purposeLegend {
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Wavelengths' window: each one's color, its name, up, down, and × */
.wavelengthEditor {
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  margin: 0.4em 0 0.8em;
  padding: 0;
  list-style: none;
}

.wavelengthRow {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.wavelengthRow .purposeSwatch {
  width: 1em;
  height: 1em;
}

.wavelengthRow input.wavelengthName {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
}

.budgetButton.wavelengthMove {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.3em 0.7em;
}

.budgetButton.wavelengthAdd {
  align-self: flex-start;
  margin: 0 0 0.8em;
  padding: 0.35em 1em;
  font-size: 0.9em;
}

.purposeLegendButton {
  display: flex;
  align-items: center;
  gap: 0.6em;
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  padding: 0.5em 0.4em;
  font: inherit;
  text-align: left;
  color: var(--BASE_COLOR);
  background: none;
  border: none;
  border-bottom: 1px solid var(--PANEL_LINE);
  border-radius: 0;
  cursor: pointer;
}

.purposeLegendButton:hover,
.purposeLegendButton:focus-visible {
  transform: none;
  outline: none;
  background: rgba(var(--GLOW_RGB), 0.14);
}

.purposeLegendButton:disabled {
  cursor: default;
  opacity: 0.55;
  background: none;
}

.purposeSwatch {
  flex-shrink: 0;
  width: 0.8em;
  height: 0.8em;
  border-radius: 3px;
}

.purposeName {
  flex: 1 1 auto;
  color: var(--TEXT_BRIGHT);
}

.purposeAmount,
.purposeShare {
  font-variant-numeric: tabular-nums;
}

.purposeShare {
  min-width: 3em;
  text-align: right;
  color: var(--TEXT_DIM);
}

.budgetButton.purposeUnsorted {
  margin: 0.9em 0 0;
  padding: 0.35em 1em;
  font-size: 0.9em;
}

/* A purpose's titles (and the ones with no purpose yet), each with what it cost and its share, or its buttons */
.purposeTitles {
  margin: 0;
  padding: 0;
  list-style: none;
}

.purposeTitle {
  display: flex;
  align-items: center;
  gap: 0.8em;
  padding: 0.5em 0.2em;
  border-bottom: 1px solid var(--PANEL_LINE);
}

/* Line graphs (Line Graph.js): hairline grid, 2px lines, days ahead dashed, and a box with each line's value on the day read.
   Colors: a graph with one line uses the theme's glow (--GRAPH_ONE); with more, the eight in --SERIES_n, stepped for dark or
   light cards */
:root {
  --GRAPH_ONE: rgb(var(--GLOW_RGB));
  --SERIES_1: #3987e5;
  --SERIES_2: #d95926;
  --SERIES_3: #199e70;
  --SERIES_4: #c98500;
  --SERIES_5: #d55181;
  --SERIES_6: #008300;
  --SERIES_7: #9085e9;
  --SERIES_8: #e66767;
}

html.lightCards {
  --GRAPH_ONE: var(--LINK_LIGHT);
  --SERIES_1: #2a78d6;
  --SERIES_2: #eb6834;
  --SERIES_3: #1baf7a;
  --SERIES_4: #eda100;
  --SERIES_5: #e87ba4;
  --SERIES_6: #008300;
  --SERIES_7: #6250d6;
  --SERIES_8: #e34948;
}

.srOnly {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.lineGraph {
  margin: 0.9em 0 0.4em;
  padding-top: 0.8em;
  border-top: 1px solid var(--PANEL_LINE);
}

.paymentsGraph .lineGraph {
  margin: 0;
  padding-top: 0;
  border-top: none;
}

.lineGraphTitle {
  margin: 0 0 0.4em;
  font-weight: 600;
  color: var(--TEXT_BRIGHT);
}

.lineGraphPlot {
  position: relative;
  border-radius: 8px;
  touch-action: pan-y;
  cursor: crosshair;
}

.lineGraphPlot:focus-visible {
  outline: 2px solid var(--GLOW_EDGE);
  outline-offset: 2px;
}

.lineGraphSvg {
  display: block;
  width: 100%;
}

.lineGraphGrid {
  stroke: rgba(var(--TINT_RGB, 255, 255, 255), 0.1);
  stroke-width: 1;
}

.lineGraphZero {
  stroke: rgba(var(--TINT_RGB, 255, 255, 255), 0.32);
  stroke-width: 1;
}

.lineGraphToday,
.lineGraphCrosshair {
  stroke: rgba(var(--TINT_RGB, 255, 255, 255), 0.45);
  stroke-width: 1;
}

.lineGraphAxis {
  font-size: 11px;
  fill: var(--TEXT_DIM);
}

.lineGraphLabel {
  font-size: 11px;
  fill: var(--BASE_COLOR);
}

.lineGraphLine {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lineGraphLine.isAhead {
  stroke-dasharray: 5 5;
}

.lineGraphTip {
  position: absolute;
  top: 6px;
  z-index: 2;
  box-sizing: border-box;
  max-width: min(15em, 80%);
  padding: 0.35em 0.55em;
  font-size: 0.82em;
  color: var(--BASE_COLOR);
  background: var(--LIST_FILL);
  border: 1px solid var(--PANEL_BORDER);
  border-radius: 8px;
  box-shadow: var(--GLASS_SHADOW);
  pointer-events: none;
}

.lineGraphTipDay {
  color: var(--TEXT_BRIGHT);
  font-weight: 600;
  white-space: nowrap;
}

.lineGraphTipRow {
  display: flex;
  align-items: center;
  gap: 0.4em;
}

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

.lineGraphTipValue {
  font-variant-numeric: tabular-nums;
  color: var(--TEXT_BRIGHT);
}

.lineGraphKey {
  flex: 0 0 auto;
  display: inline-block;
  width: 14px;
  height: 3px;
  border-radius: 2px;
}

.lineGraphLegend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3em 0.5em;
  margin: 0.5em 0 0;
  padding: 0;
  list-style: none;
}

.lineGraphLegendButton {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.2em 0.55em;
  font: inherit;
  font-size: 0.85em;
  color: var(--BASE_COLOR);
  background: none;
  border: 1px solid var(--PANEL_LINE);
  border-radius: 999px;
  cursor: pointer;
}

.lineGraphLegendButton[aria-pressed="false"] {
  color: var(--TEXT_DIM);
  text-decoration: line-through;
}

.lineGraphLegendButton[aria-pressed="false"] .lineGraphKey {
  opacity: 0.35;
}

.lineGraphEmpty {
  margin: 0.4em 0;
}

.lineGraphTable {
  margin-top: 0.5em;
}

.lineGraphTable summary {
  width: fit-content;
  font-size: 0.9em;
  color: var(--BASE_COLOR);
  cursor: pointer;
}

.lineGraphTable .bobScroll {
  margin-top: 0.4em;
}

/* Equity's window: how an account's interest is worked out, on its own line under the account */
.bobAccounts tr.interestAbout td {
  padding-top: 0;
  font-size: 0.82em;
  text-align: left;
  white-space: normal;
  color: var(--TEXT_DIM);
}

/* An account's kind: its tips, showing under the kind's buttons */
.accountKindTips {
  margin-top: 0.5em;
}

/* A title with no wavelength yet: its words, with a button for each wavelength under them */
.purposeTitle.hasChoices {
  flex-direction: column;
  align-items: stretch;
  gap: 0.45em;
}

.purposeTitle.hasChoices .purposeTitleText {
  flex: none;
}

.purposeTitleText {
  display: flex;
  flex: 1 1 10em;
  flex-direction: column;
  gap: 0.1em;
  min-width: 0;
}

.purposeTitleName {
  overflow-wrap: anywhere;
  color: var(--TEXT_BRIGHT);
}

.purposeTitleCount {
  font-size: 0.85em;
  color: var(--TEXT_DIM);
}

.purposeTitleAmount {
  font-variant-numeric: tabular-nums;
}

.purposeTitleAmount.negative {
  color: var(--NEGATIVE_TEXT);
}

.purposeTitleShare {
  min-width: 3em;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--TEXT_DIM);
}

.purposeTitleChoices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4em;
}

.purposeTitleChoices .budgetButton {
  margin: 0;
  padding: 0.3em 0.8em;
  font-size: 0.9em;
}

/* Needs, Wants, Or Future in an entry's form: four buttons that wrap on a narrow phone */
.purposeChoices {
  flex-wrap: wrap;
}

/* An entry's note (BudgetUI.noteField): the last thing in its form, under its buttons, with its button over the note so
   the button stays put as it opens and closes. A long note scrolls in its box, which can be pulled taller. */
.noteField {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55em;
  margin-top: 0.9em;
}

.budgetButton.noteToggle {
  padding: 0.35em 1em;
  font-size: 0.9em;
}

.budgetPanel textarea.noteBox {
  min-height: 7em;
  max-height: 60vh;
  line-height: 1.45;
  overflow-y: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Settings' Upload A Backup window (Settings Page.js): what each choice does, then each part of the budget the backup
   has, in a box of its own with its three choices */
.backupHelp {
  margin: 0.2em 0 0.9em;
  padding-left: 1.2em;
  line-height: 1.45;
}

.backupParts {
  display: flex;
  flex-direction: column;
  gap: 0.7em;
  margin: 0.5em 0 0.9em;
}

.backupPart {
  padding: 0.6em 0.75em;
  background: rgba(var(--INSET_RGB), 0.22);
  border: 1px solid var(--PANEL_LINE);
  border-radius: 10px;
}

.backupPartName {
  margin: 0 0 0.2em;
  font-size: 1em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
}

.backupPart .panelHint {
  margin: 0 0 0.45em;
}

@media (max-width: 560px) {
  .budgetCard.bobTop {
    flex-direction: column;
    align-items: center;
  }

  .bobDataValue {
    max-width: 55%;
  }

  /* Accounts packs closer on a phone, so all four columns fit */
  .dataTable.bobAccounts {
    font-size: 0.86em;
    border-spacing: 2px;
  }

  .bobAccounts th,
  .bobAccounts td {
    padding-left: 0.35em;
    padding-right: 0.35em;
  }

  .bobAccounts th.dayHead {
    min-width: 0;
    padding: 0.3em 0.2em;
  }

  .bobAccounts td.titleCell {
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

/* The narrowest phones: smaller still, with the day's calendar button under its box */
@media (max-width: 380px) {
  .dataTable.bobAccounts {
    font-size: 0.8em;
  }

  .bobAccounts .dayHead .dateRow {
    flex-wrap: wrap;
  }
}

/*========================================*
 *  HOW IT WORKS (how-it-works.html): a long reference page, readable without JavaScript
 *========================================*/

.guide {
  display: block; /* The global article is a centered flex column, which would shrink the Contents box */
  box-sizing: border-box;
  width: min(94vw, 920px);
  margin: 0 auto 4vmin;
  text-align: left;
  font-size: var(--UI_TEXT);
  line-height: 1.55;
  color: var(--BASE_COLOR);
  user-select: text;
  -webkit-user-select: text;
}

.guide > section,
.guide > nav {
  margin: 0 0 2.5vmin;
  padding: 1em 1.3em;
  background: var(--GLASS);
  border: 1px solid var(--GLASS_LINE);
  border-radius: var(--GLASS_RADIUS);
  box-shadow: var(--GLASS_SHADOW);
}

.guide h2 {
  margin: 0 0 0.6em;
  font-size: 1.45em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.guide h3 {
  margin: 1.2em 0 0.4em;
  font-size: 1.15em;
  font-weight: normal;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.guide p {
  margin: 0 0 0.75em;
  font-size: 1em;
}

.guide ul,
.guide ol {
  margin: 0 0 0.9em;
  padding-left: 1.4em;
}

.guide li {
  margin-bottom: 0.35em;
}

.guide a {
  display: inline;
  padding: 0;
  text-decoration: underline;
}

.guide code {
  padding: 0.05em 0.3em;
  font-family: Consolas, "Courier New", monospace;
  font-size: 0.92em;
  background: rgba(var(--INSET_RGB), 0.4);
  border-radius: 4px;
}

.guide pre {
  overflow-x: auto;
  overflow-y: hidden;
  margin: 0 0 0.9em;
  padding: 0.7em 0.9em;
  font-size: 0.9em;
  line-height: 1.4;
  background: rgba(var(--INSET_RGB), 0.45);
  border-radius: 8px;
}

.guide pre code {
  padding: 0;
  background: none;
}

/* A key on the keyboard (the starfield's controls) */
.guide kbd {
  display: inline-block;
  min-width: 1.4em;
  padding: 0.05em 0.35em;
  font-family: inherit;
  font-size: 0.9em;
  line-height: 1.3;
  text-align: center;
  background: rgba(var(--INSET_RGB), 0.4);
  border: 1px solid var(--PANEL_BORDER);
  border-bottom-width: 2px;
  border-radius: 5px;
}

.guide .tableScroll {
  overflow-x: auto;
  overflow-y: hidden;
  margin: 0 0 1em;
}

.guide table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95em;
}

.guide th,
.guide td {
  padding: 0.4em 0.6em;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--PANEL_LINE);
}

.guide th {
  font-weight: normal;
  white-space: nowrap;
  opacity: 0.85;
}

.guide dt {
  margin-top: 0.7em;
  font-weight: bold;
}

.guide dd {
  margin: 0.15em 0 0 1.2em;
}

.guideUpdated {
  opacity: 0.75;
}

@media (min-width: 760px) {
  .guide .toc ol {
    columns: 2;
    column-gap: 2.5em;
  }
}

/*========================================*
 *  FRONT PAGE (index.html for anyone signed out): what Prismal Planning is, readable without JavaScript.
 *  html.frontPage (Boot.js) shows it, and Sign In and Create Account fixed to the window, instead of the
 *  budget.
 *========================================*/

html:not(.frontPage) .frontView,
html:not(.frontPage) .frontSignIn,
.frontPage #transitionContainer > main > :not(.frontView),
.frontPage header .navButtons {
  display: none;
}

.frontView {
  font-size: clamp(15px, 3vmin, 19px);
}

/* The note at the very top: Prismal Planning isn't any other company with a similar name */
.frontView .frontDisclaimer {
  max-width: 46em;
  margin: 0 auto 0.4em;
  padding: 0 1em;
  font-size: 0.8em;
  line-height: 1.4;
  text-align: center;
  color: var(--TEXT_DIM);
}

.frontHero {
  padding: 1.6em 1.3em;
  text-align: center;
}

.frontHero h1 {
  margin: 0 0 0.6em;
  font-size: clamp(26px, 5.5vmin, 44px);
  font-weight: normal;
  line-height: 1.25;
  color: var(--TEXT_BRIGHT);
  text-shadow: var(--TITLE_GLOW);
}

.frontHero p {
  max-width: 40em;
  margin: 0 auto 1em;
}

.frontButtons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.8em;
  margin-top: 1.2em;
}

/* (Buttons, not .guide's plain links) */
.frontButtons .budgetButton,
.frontSignIn .budgetButton {
  display: inline-flex;
  padding: 0.45em 1.1em;
  font-size: 1em;
  text-decoration: none;
}

.frontFeatures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.8em;
  padding: 0;
  list-style: none;
}

.frontFeatures li {
  margin: 0;
  padding: 0.8em 1em;
  background: var(--PANEL_DARK);
  border: 1px solid var(--GLASS_LINE);
  border-radius: 12px;
}

.frontFeatures strong {
  display: block;
  margin-bottom: 0.3em;
}

.frontSteps li {
  margin-bottom: 0.6em;
}

/* Sign In and Create Account: top right, over everything, on a dark pill so they read over the page */
.frontSignIn {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  right: calc(env(safe-area-inset-right, 0px) + 16px);
  z-index: 100;
  display: flex;
  gap: 0.6em;
  padding: 0.45em;
  font-size: clamp(14px, 2.6vmin, 18px);
  background: rgba(12, 12, 40, 0.8);
  border: 1px solid var(--GLASS_LINE);
  border-radius: 9999px;
  box-shadow: var(--GLASS_SHADOW);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  transition: opacity 0.4s ease;
}

/* They come and go with the page as it slides in and out */
.homeJs #transitionContainer:not(.ready) ~ .frontSignIn,
.homeJs #transitionContainer.slide-out ~ .frontSignIn {
  opacity: 0;
  pointer-events: none;
}

/* Phones: top center, with room for them above the page */
@media (max-width: 700px) {
  .frontSignIn {
    right: auto;
    left: 50%;
    transform: translateX(-50%);
  }

  .frontPage #transitionContainer {
    padding-top: calc(2vh + 64px);
  }
}

/* A placeholder (Process Budget.js) is yellow, a cost or a gain, wherever it shows: on a day, in Upcoming, Search, the
   Recurring Entries table, an account's entries, Quick Entry's prisms and waiting entries, and a spreadsheet's count and
   preview. It comes last, and is as specific as each place's own colors, so it wins over them. */
.isPlaceholder,
.isPlaceholder .positive,
.isPlaceholder .negative,
.lineEntry.isPlaceholder,
.upcomingEntry.isPlaceholder,
.accountEntryLine.isPlaceholder,
.dataTable td.isPlaceholder,
.dataTable td.amountCell.isPlaceholder,
.recurringTable tr.isPlaceholder td,
.recurringTable tr.isPlaceholder td.amountCell,
.waitingItem.isPlaceholder .waitingTitle,
.waitingItem.isPlaceholder .waitingAmount,
.sheetPreviewList.isPlaceholder li {
  color: var(--PLACEHOLDER_TEXT);
}
