@charset "UTF-8";
#profileFullName,
#profileEmail,
#securityAddPhoneNumber,
#securityAddPhoneCode,
#upgradeCodeInput,
#adminEmailInput, .search_bar input,
.cm-prompt-dialog input, .share-panel-email-input, .editLink-form input, #vaultSetupArea input,
#vaultUnlockArea input, .pennyForm input:not([type=checkbox]), .pennySummaryTable input, .pennyBalanceInput, .project-name-input, .project-invite-email, .hoursForm input:not([type=checkbox]), .hoursForm input, .hoursBreakdownTable input, .hoursForm textarea, .duesForm input:not([type=checkbox]), .duesForm input, .duesForm textarea, .duesBreakdownTable input, .pennyEstimatorSection select,
.pennyForm select, .project-role-select,
.hoursForm select,
.duesForm select, #apiKeyCreateForm input:not([type=checkbox]),
#addPasswordForm input,
#linkRequestFormArea input, #mergeConfirmInput, .pennyEstimatorSection input, .projectAuthorInput input {
  color: var(--color-ink);
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 6px 15px;
  box-sizing: border-box;
}
#profileFullName:focus,
#profileEmail:focus,
#securityAddPhoneNumber:focus,
#securityAddPhoneCode:focus,
#upgradeCodeInput:focus,
#adminEmailInput:focus, .search_bar input:focus,
.cm-prompt-dialog input:focus, .share-panel-email-input:focus, .editLink-form input:focus, #vaultSetupArea input:focus,
#vaultUnlockArea input:focus, .pennyForm input:focus:not([type=checkbox]), .pennySummaryTable input:focus, .pennyBalanceInput:focus, .project-name-input:focus, .project-invite-email:focus, .hoursForm input:focus, .hoursBreakdownTable input:focus, .hoursForm textarea:focus, .duesForm input:focus, .duesForm textarea:focus, .duesBreakdownTable input:focus, .pennyEstimatorSection select:focus,
.pennyForm select:focus, .project-role-select:focus,
.hoursForm select:focus,
.duesForm select:focus, #apiKeyCreateForm input:focus:not([type=checkbox]),
#addPasswordForm input:focus,
#linkRequestFormArea input:focus, #mergeConfirmInput:focus, .pennyEstimatorSection input:focus, .projectAuthorInput input:focus {
  outline: none;
  border-color: var(--color-green);
}
#profileFullName:-moz-ui-valid,
#profileEmail:-moz-ui-valid,
#securityAddPhoneNumber:-moz-ui-valid,
#securityAddPhoneCode:-moz-ui-valid,
#upgradeCodeInput:-moz-ui-valid,
#adminEmailInput:-moz-ui-valid, .search_bar input:-moz-ui-valid,
.cm-prompt-dialog input:-moz-ui-valid, .share-panel-email-input:-moz-ui-valid, .editLink-form input:-moz-ui-valid, #vaultSetupArea input:-moz-ui-valid,
#vaultUnlockArea input:-moz-ui-valid, .pennyForm input:-moz-ui-valid:not([type=checkbox]), .pennySummaryTable input:-moz-ui-valid, .pennyBalanceInput:-moz-ui-valid, .project-name-input:-moz-ui-valid, .project-invite-email:-moz-ui-valid, .hoursForm input:-moz-ui-valid, .hoursBreakdownTable input:-moz-ui-valid, .hoursForm textarea:-moz-ui-valid, .duesForm input:-moz-ui-valid, .duesForm textarea:-moz-ui-valid, .duesBreakdownTable input:-moz-ui-valid, .pennyEstimatorSection select:-moz-ui-valid,
.pennyForm select:-moz-ui-valid, .project-role-select:-moz-ui-valid,
.hoursForm select:-moz-ui-valid,
.duesForm select:-moz-ui-valid, #apiKeyCreateForm input:-moz-ui-valid:not([type=checkbox]),
#addPasswordForm input:-moz-ui-valid,
#linkRequestFormArea input:-moz-ui-valid, #mergeConfirmInput:-moz-ui-valid, .pennyEstimatorSection input:-moz-ui-valid, .projectAuthorInput input:-moz-ui-valid, #profileFullName:-moz-ui-invalid,
#profileEmail:-moz-ui-invalid,
#securityAddPhoneNumber:-moz-ui-invalid,
#securityAddPhoneCode:-moz-ui-invalid,
#upgradeCodeInput:-moz-ui-invalid,
#adminEmailInput:-moz-ui-invalid, .search_bar input:-moz-ui-invalid,
.cm-prompt-dialog input:-moz-ui-invalid, .share-panel-email-input:-moz-ui-invalid, .editLink-form input:-moz-ui-invalid, #vaultSetupArea input:-moz-ui-invalid,
#vaultUnlockArea input:-moz-ui-invalid, .pennyForm input:-moz-ui-invalid:not([type=checkbox]), .pennySummaryTable input:-moz-ui-invalid, .pennyBalanceInput:-moz-ui-invalid, .project-name-input:-moz-ui-invalid, .project-invite-email:-moz-ui-invalid, .hoursForm input:-moz-ui-invalid, .hoursBreakdownTable input:-moz-ui-invalid, .hoursForm textarea:-moz-ui-invalid, .duesForm input:-moz-ui-invalid, .duesForm textarea:-moz-ui-invalid, .duesBreakdownTable input:-moz-ui-invalid, .pennyEstimatorSection select:-moz-ui-invalid,
.pennyForm select:-moz-ui-invalid, .project-role-select:-moz-ui-invalid,
.hoursForm select:-moz-ui-invalid,
.duesForm select:-moz-ui-invalid, #apiKeyCreateForm input:-moz-ui-invalid:not([type=checkbox]),
#addPasswordForm input:-moz-ui-invalid,
#linkRequestFormArea input:-moz-ui-invalid, #mergeConfirmInput:-moz-ui-invalid, .pennyEstimatorSection input:-moz-ui-invalid, .projectAuthorInput input:-moz-ui-invalid {
  box-shadow: none;
}

#apiKeyCreateForm input:not([type=checkbox]),
#addPasswordForm input,
#linkRequestFormArea input, #mergeConfirmInput, .pennyEstimatorSection input, .projectAuthorInput input {
  background-color: var(--color-input-fitting);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}
#apiKeyCreateForm input:-moz-ui-valid:not([type=checkbox]),
#addPasswordForm input:-moz-ui-valid,
#linkRequestFormArea input:-moz-ui-valid, #mergeConfirmInput:-moz-ui-valid, .pennyEstimatorSection input:-moz-ui-valid, .projectAuthorInput input:-moz-ui-valid, #apiKeyCreateForm input:-moz-ui-invalid:not([type=checkbox]),
#addPasswordForm input:-moz-ui-invalid,
#linkRequestFormArea input:-moz-ui-invalid, #mergeConfirmInput:-moz-ui-invalid, .pennyEstimatorSection input:-moz-ui-invalid, .projectAuthorInput input:-moz-ui-invalid {
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}

.pennyEstimatorSection select,
.pennyForm select, .project-role-select,
.hoursForm select,
.duesForm select {
  background-color: var(--color-dark-b);
  color: var(--color-white-h);
  color-scheme: var(--color-scheme);
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23cacaca' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 10px 6px;
  padding-right: 32px;
  cursor: pointer;
}
[data-theme=midnight-dark] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=midnight-dark] select,
[data-theme=midnight-dark] .pennyForm select,
.pennyForm [data-theme=midnight-dark] select, [data-theme=midnight-dark] .project-role-select,
[data-theme=midnight-dark] .hoursForm select,
.hoursForm [data-theme=midnight-dark] select,
[data-theme=midnight-dark] .duesForm select,
.duesForm [data-theme=midnight-dark] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23bdbdbd' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=twilight-dark] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=twilight-dark] select,
[data-theme=twilight-dark] .pennyForm select,
.pennyForm [data-theme=twilight-dark] select, [data-theme=twilight-dark] .project-role-select,
[data-theme=twilight-dark] .hoursForm select,
.hoursForm [data-theme=twilight-dark] select,
[data-theme=twilight-dark] .duesForm select,
.duesForm [data-theme=twilight-dark] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23c4c4c4' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=halloween] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=halloween] select,
[data-theme=halloween] .pennyForm select,
.pennyForm [data-theme=halloween] select, [data-theme=halloween] .project-role-select,
[data-theme=halloween] .hoursForm select,
.hoursForm [data-theme=halloween] select,
[data-theme=halloween] .duesForm select,
.duesForm [data-theme=halloween] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23e6dccb' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=valentines] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=valentines] select,
[data-theme=valentines] .pennyForm select,
.pennyForm [data-theme=valentines] select, [data-theme=valentines] .project-role-select,
[data-theme=valentines] .hoursForm select,
.hoursForm [data-theme=valentines] select,
[data-theme=valentines] .duesForm select,
.duesForm [data-theme=valentines] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23ecd5dc' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=st-patricks] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=st-patricks] select,
[data-theme=st-patricks] .pennyForm select,
.pennyForm [data-theme=st-patricks] select, [data-theme=st-patricks] .project-role-select,
[data-theme=st-patricks] .hoursForm select,
.hoursForm [data-theme=st-patricks] select,
[data-theme=st-patricks] .duesForm select,
.duesForm [data-theme=st-patricks] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23d8e6d2' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=christmas] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=christmas] select,
[data-theme=christmas] .pennyForm select,
.pennyForm [data-theme=christmas] select, [data-theme=christmas] .project-role-select,
[data-theme=christmas] .hoursForm select,
.hoursForm [data-theme=christmas] select,
[data-theme=christmas] .duesForm select,
.duesForm [data-theme=christmas] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23e8e4d8' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=new-year] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=new-year] select,
[data-theme=new-year] .pennyForm select,
.pennyForm [data-theme=new-year] select, [data-theme=new-year] .project-role-select,
[data-theme=new-year] .hoursForm select,
.hoursForm [data-theme=new-year] select,
[data-theme=new-year] .duesForm select,
.duesForm [data-theme=new-year] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23e3dfd2' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=dracula] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=dracula] select,
[data-theme=dracula] .pennyForm select,
.pennyForm [data-theme=dracula] select, [data-theme=dracula] .project-role-select,
[data-theme=dracula] .hoursForm select,
.hoursForm [data-theme=dracula] select,
[data-theme=dracula] .duesForm select,
.duesForm [data-theme=dracula] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23d8d8d2' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=nord] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=nord] select,
[data-theme=nord] .pennyForm select,
.pennyForm [data-theme=nord] select, [data-theme=nord] .project-role-select,
[data-theme=nord] .hoursForm select,
.hoursForm [data-theme=nord] select,
[data-theme=nord] .duesForm select,
.duesForm [data-theme=nord] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23d8dee9' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=solarized] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=solarized] select,
[data-theme=solarized] .pennyForm select,
.pennyForm [data-theme=solarized] select, [data-theme=solarized] .project-role-select,
[data-theme=solarized] .hoursForm select,
.hoursForm [data-theme=solarized] select,
[data-theme=solarized] .duesForm select,
.duesForm [data-theme=solarized] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%2393a1a1' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=gruvbox] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=gruvbox] select,
[data-theme=gruvbox] .pennyForm select,
.pennyForm [data-theme=gruvbox] select, [data-theme=gruvbox] .project-role-select,
[data-theme=gruvbox] .hoursForm select,
.hoursForm [data-theme=gruvbox] select,
[data-theme=gruvbox] .duesForm select,
.duesForm [data-theme=gruvbox] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23d5c4a1' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=one-dark] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=one-dark] select,
[data-theme=one-dark] .pennyForm select,
.pennyForm [data-theme=one-dark] select, [data-theme=one-dark] .project-role-select,
[data-theme=one-dark] .hoursForm select,
.hoursForm [data-theme=one-dark] select,
[data-theme=one-dark] .duesForm select,
.duesForm [data-theme=one-dark] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23abb2bf' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=tokyo-night] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=tokyo-night] select,
[data-theme=tokyo-night] .pennyForm select,
.pennyForm [data-theme=tokyo-night] select, [data-theme=tokyo-night] .project-role-select,
[data-theme=tokyo-night] .hoursForm select,
.hoursForm [data-theme=tokyo-night] select,
[data-theme=tokyo-night] .duesForm select,
.duesForm [data-theme=tokyo-night] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23a9b1d6' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=catppuccin] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=catppuccin] select,
[data-theme=catppuccin] .pennyForm select,
.pennyForm [data-theme=catppuccin] select, [data-theme=catppuccin] .project-role-select,
[data-theme=catppuccin] .hoursForm select,
.hoursForm [data-theme=catppuccin] select,
[data-theme=catppuccin] .duesForm select,
.duesForm [data-theme=catppuccin] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23bac2de' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=blossom] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=blossom] select,
[data-theme=blossom] .pennyForm select,
.pennyForm [data-theme=blossom] select, [data-theme=blossom] .project-role-select,
[data-theme=blossom] .hoursForm select,
.hoursForm [data-theme=blossom] select,
[data-theme=blossom] .duesForm select,
.duesForm [data-theme=blossom] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23f0dce8' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=dim] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=dim] select,
[data-theme=dim] .pennyForm select,
.pennyForm [data-theme=dim] select, [data-theme=dim] .project-role-select,
[data-theme=dim] .hoursForm select,
.hoursForm [data-theme=dim] select,
[data-theme=dim] .duesForm select,
.duesForm [data-theme=dim] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23d9e1e8' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=lounge] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=lounge] select,
[data-theme=lounge] .pennyForm select,
.pennyForm [data-theme=lounge] select, [data-theme=lounge] .project-role-select,
[data-theme=lounge] .hoursForm select,
.hoursForm [data-theme=lounge] select,
[data-theme=lounge] .duesForm select,
.duesForm [data-theme=lounge] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23dbdee1' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=daylight] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=daylight] select,
[data-theme=daylight] .pennyForm select,
.pennyForm [data-theme=daylight] select, [data-theme=daylight] .project-role-select,
[data-theme=daylight] .hoursForm select,
.hoursForm [data-theme=daylight] select,
[data-theme=daylight] .duesForm select,
.duesForm [data-theme=daylight] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%231f2328' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=petal] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=petal] select,
[data-theme=petal] .pennyForm select,
.pennyForm [data-theme=petal] select, [data-theme=petal] .project-role-select,
[data-theme=petal] .hoursForm select,
.hoursForm [data-theme=petal] select,
[data-theme=petal] .duesForm select,
.duesForm [data-theme=petal] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%233d2a35' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[data-theme=barbie] .pennyEstimatorSection select, .pennyEstimatorSection [data-theme=barbie] select,
[data-theme=barbie] .pennyForm select,
.pennyForm [data-theme=barbie] select, [data-theme=barbie] .project-role-select,
[data-theme=barbie] .hoursForm select,
.hoursForm [data-theme=barbie] select,
[data-theme=barbie] .duesForm select,
.duesForm [data-theme=barbie] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%234a0d2e' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.pennyEstimatorSection select option,
.pennyForm select option, .project-role-select option,
.hoursForm select option,
.duesForm select option,
.pennyEstimatorSection select optgroup,
.pennyForm select optgroup,
.project-role-select optgroup,
.hoursForm select optgroup,
.duesForm select optgroup {
  background-color: var(--color-dark-b);
  color: var(--color-white-h);
}

.pageSection, .skeleton-tally, .skeleton-table, .skeleton-form-panel, .pennyTotalsPanel, .pennyEstimatorSection, .hoursTallyPanel, .duesTallyPanel, .duesTemplatePanel, .hoursExportPanel {
  background-color: var(--color-dark);
  border-radius: 10px;
  padding: 16px 20px;
}

.pageSectionList {
  margin: 0;
  padding: 0;
  list-style: none;
}

.pageSectionList li {
  margin-bottom: 8px;
}
.pageSectionList li:last-child {
  margin-bottom: 0;
}

.apiKeyRow,
.securityFactorRow,
.trustedDeviceRow,
.signInMethodRow,
.linkedAccountRow,
.linkRequestRow, .themeOption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  background-color: var(--color-dark-b);
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 8px;
}
.apiKeyRow:last-child,
.securityFactorRow:last-child,
.trustedDeviceRow:last-child,
.signInMethodRow:last-child,
.linkedAccountRow:last-child,
.linkRequestRow:last-child, .themeOption:last-child {
  margin-bottom: 0;
}

.cheat-type, .revisions-cheat, .revision-notice-link, .makePrivate,
.makePublic, .taskDuration,
.taskCategory.editable, .pennies-tab, .pennyImportPanel button, .penny-market-btn, .penny-filter-pill, .pennyEstCalcBtn, .project-tab, .projectName.editable,
.projectStatus.editable, .projectType.editable, .hours-tab, .hours-filter-pill, .dues-tab, .dues-filter-pill, .duesManageMethodsLink, .duesCycle,
.duesSchedule, .billingPeriodToggle {
  color: var(--color-white) !important;
  cursor: pointer;
}
.cheat-type:hover, .revisions-cheat:hover, .revision-notice-link:hover, .makePrivate:hover,
.makePublic:hover, .taskDuration:hover,
.taskCategory.editable:hover, .pennies-tab:hover, .pennyImportPanel button:hover, .penny-market-btn:hover, .penny-filter-pill:hover, .pennyEstCalcBtn:hover, .project-tab:hover, .projectName.editable:hover,
.projectStatus.editable:hover, .projectType.editable:hover, .hours-tab:hover, .hours-filter-pill:hover, .dues-tab:hover, .dues-filter-pill:hover, .duesManageMethodsLink:hover, .duesCycle:hover,
.duesSchedule:hover, .billingPeriodToggle:hover {
  color: var(--color-white-h) !important;
}

.side-nav-groups, .cm-scroller, .pennyDetails,
.pennyForm, #penniesSummary, .pennyLedger, .pennyBalanceCheck, .project-board, .hoursDetails,
.hoursForm, .hoursBreakdown, .duesDetails,
.duesForm, .duesTemplatePreview, .duesBreakdown {
  scrollbar-width: thin;
  scrollbar-color: var(--color-white) var(--color-dark-h);
}
.side-nav-groups::-webkit-scrollbar, .cm-scroller::-webkit-scrollbar, .pennyDetails::-webkit-scrollbar,
.pennyForm::-webkit-scrollbar, #penniesSummary::-webkit-scrollbar, .pennyLedger::-webkit-scrollbar, .pennyBalanceCheck::-webkit-scrollbar, .project-board::-webkit-scrollbar, .hoursDetails::-webkit-scrollbar,
.hoursForm::-webkit-scrollbar, .hoursBreakdown::-webkit-scrollbar, .duesDetails::-webkit-scrollbar,
.duesForm::-webkit-scrollbar, .duesTemplatePreview::-webkit-scrollbar, .duesBreakdown::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
.side-nav-groups::-webkit-scrollbar-track, .cm-scroller::-webkit-scrollbar-track, .pennyDetails::-webkit-scrollbar-track,
.pennyForm::-webkit-scrollbar-track, #penniesSummary::-webkit-scrollbar-track, .pennyLedger::-webkit-scrollbar-track, .pennyBalanceCheck::-webkit-scrollbar-track, .project-board::-webkit-scrollbar-track, .hoursDetails::-webkit-scrollbar-track,
.hoursForm::-webkit-scrollbar-track, .hoursBreakdown::-webkit-scrollbar-track, .duesDetails::-webkit-scrollbar-track,
.duesForm::-webkit-scrollbar-track, .duesTemplatePreview::-webkit-scrollbar-track, .duesBreakdown::-webkit-scrollbar-track {
  background: var(--color-dark-h);
}
.side-nav-groups::-webkit-scrollbar-thumb, .cm-scroller::-webkit-scrollbar-thumb, .pennyDetails::-webkit-scrollbar-thumb,
.pennyForm::-webkit-scrollbar-thumb, #penniesSummary::-webkit-scrollbar-thumb, .pennyLedger::-webkit-scrollbar-thumb, .pennyBalanceCheck::-webkit-scrollbar-thumb, .project-board::-webkit-scrollbar-thumb, .hoursDetails::-webkit-scrollbar-thumb,
.hoursForm::-webkit-scrollbar-thumb, .hoursBreakdown::-webkit-scrollbar-thumb, .duesDetails::-webkit-scrollbar-thumb,
.duesForm::-webkit-scrollbar-thumb, .duesTemplatePreview::-webkit-scrollbar-thumb, .duesBreakdown::-webkit-scrollbar-thumb {
  background-color: var(--color-white);
  border-radius: 4px;
  border: 2px solid var(--color-dark-h);
}
.side-nav-groups::-webkit-scrollbar-thumb:hover, .cm-scroller::-webkit-scrollbar-thumb:hover, .pennyDetails::-webkit-scrollbar-thumb:hover,
.pennyForm::-webkit-scrollbar-thumb:hover, #penniesSummary::-webkit-scrollbar-thumb:hover, .pennyLedger::-webkit-scrollbar-thumb:hover, .pennyBalanceCheck::-webkit-scrollbar-thumb:hover, .project-board::-webkit-scrollbar-thumb:hover, .hoursDetails::-webkit-scrollbar-thumb:hover,
.hoursForm::-webkit-scrollbar-thumb:hover, .hoursBreakdown::-webkit-scrollbar-thumb:hover, .duesDetails::-webkit-scrollbar-thumb:hover,
.duesForm::-webkit-scrollbar-thumb:hover, .duesTemplatePreview::-webkit-scrollbar-thumb:hover, .duesBreakdown::-webkit-scrollbar-thumb:hover {
  background-color: var(--color-white-h);
}

input[type=checkbox], .cm-checklist-box {
  position: relative;
  display: inline-block;
  width: 14px;
  height: 14px;
  box-sizing: border-box;
  background-color: var(--color-dark-h);
  border: 1px solid var(--color-white-l);
  border-radius: 4px;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

input[type=checkbox]:checked, .cm-checklist-box.checked {
  background-color: var(--color-green);
  border-color: var(--color-green);
}

input[type=checkbox]:checked::after, .cm-checklist-box.checked::after {
  content: "";
  position: absolute;
  top: 1px;
  left: 4px;
  width: 3px;
  height: 7px;
  border: solid var(--color-on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

:root, [data-theme=monokai] {
  --color-white: #cacaca;
  --color-white-l: #7c7c7c;
  --color-white-h: #ffffff;
  --color-green: #74aa04;
  --color-green-h: #8dd006;
  --color-blue: #1a83a6;
  --color-blue-h: #2095bd;
  --color-red: #a70334;
  --color-red-h: #f3044b;
  --color-gold: #cccc81;
  --color-gold-h: #c7c74a;
  --color-gold-highlight: rgba(204, 204, 129, 0.6352941176);
  --color-dark: #1d1e19;
  --color-dark-b: #32332c;
  --color-dark-l: #272822;
  --color-dark-m: #20211b;
  --color-dark-h: #171714;
  --color-dark-t: rgba(30, 30, 25, 0.7490196078);
  --color-input-fitting: #dcdcd8;
  --color-paper: #ffffff;
  --color-ink: #1d1e19;
  --color-on-accent: #ffffff;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=midnight-dark] {
  --color-white: #bdbdbd;
  --color-white-l: #7a7a7a;
  --color-white-h: #ececec;
  --color-green: #0d8a6a;
  --color-green-h: #10a37f;
  --color-blue: #2f6fb5;
  --color-blue-h: #4f93e8;
  --color-red: #b94545;
  --color-red-h: #e05d5d;
  --color-gold: #b9852b;
  --color-gold-h: #d9a13b;
  --color-gold-highlight: rgba(185, 133, 43, 0.6352941176);
  --color-dark: #0f0f0f;
  --color-dark-b: #2b2b2b;
  --color-dark-l: #181818;
  --color-dark-m: #111111;
  --color-dark-h: #080808;
  --color-dark-t: rgba(15, 15, 15, 0.7490196078);
  --color-input-fitting: #ececec;
  --color-paper: #ffffff;
  --color-ink: #141414;
  --color-on-accent: #ffffff;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=twilight-dark] {
  --color-white: #c4c4c4;
  --color-white-l: #82828a;
  --color-white-h: #f0f0f0;
  --color-green: #0d8a6a;
  --color-green-h: #10a37f;
  --color-blue: #2f6fb5;
  --color-blue-h: #4f93e8;
  --color-red: #b94545;
  --color-red-h: #e05d5d;
  --color-gold: #b9852b;
  --color-gold-h: #d9a13b;
  --color-gold-highlight: rgba(185, 133, 43, 0.6352941176);
  --color-dark: #181818;
  --color-dark-b: #383838;
  --color-dark-l: #232323;
  --color-dark-m: #1c1c1c;
  --color-dark-h: #0f0f0f;
  --color-dark-t: rgba(24, 24, 24, 0.7490196078);
  --color-input-fitting: #ececec;
  --color-paper: #ffffff;
  --color-ink: #141414;
  --color-on-accent: #ffffff;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=halloween] {
  --color-white: #e6dccb;
  --color-white-l: #9a8aa8;
  --color-white-h: #fff4e0;
  --color-green: #5f8f2f;
  --color-green-h: #8bc34a;
  --color-blue: #7a4fb5;
  --color-blue-h: #b388eb;
  --color-red: #b3261e;
  --color-red-h: #e5493d;
  --color-gold: #d9651a;
  --color-gold-h: #ff9a3d;
  --color-gold-highlight: rgba(217, 101, 26, 0.6352941176);
  --color-dark: #160f1f;
  --color-dark-b: #3a2a4d;
  --color-dark-l: #1d1527;
  --color-dark-m: #1a1223;
  --color-dark-h: #100a17;
  --color-dark-t: rgba(29, 21, 39, 0.7490196078);
  --color-input-fitting: #f3ecf8;
  --color-paper: #fbf6ff;
  --color-ink: #1d1527;
  --color-on-accent: #fff4e0;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=valentines] {
  --color-white: #ecd5dc;
  --color-white-l: #a8808c;
  --color-white-h: #fff0f4;
  --color-green: #4f8f6a;
  --color-green-h: #7fc79b;
  --color-blue: #8a5aa8;
  --color-blue-h: #c08ee0;
  --color-red: #c2294f;
  --color-red-h: #ff5a85;
  --color-gold: #d9899a;
  --color-gold-h: #ffb3c1;
  --color-gold-highlight: rgba(217, 137, 154, 0.6352941176);
  --color-dark: #200f18;
  --color-dark-b: #4a2636;
  --color-dark-l: #2a1520;
  --color-dark-m: #25121c;
  --color-dark-h: #170a11;
  --color-dark-t: rgba(42, 21, 32, 0.7490196078);
  --color-input-fitting: #fbeef2;
  --color-paper: #fff7f9;
  --color-ink: #2a1520;
  --color-on-accent: #fff7f9;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=st-patricks] {
  --color-white: #d8e6d2;
  --color-white-l: #8aa684;
  --color-white-h: #f2fff0;
  --color-green: #2f9e44;
  --color-green-h: #5fd36f;
  --color-blue: #3a7ca5;
  --color-blue-h: #6cb0dc;
  --color-red: #b5473a;
  --color-red-h: #e5705f;
  --color-gold: #d4a72c;
  --color-gold-h: #f5cf4d;
  --color-gold-highlight: rgba(212, 167, 44, 0.6352941176);
  --color-dark: #101e14;
  --color-dark-b: #2a4430;
  --color-dark-l: #15261a;
  --color-dark-m: #122017;
  --color-dark-h: #0b150e;
  --color-dark-t: rgba(21, 38, 26, 0.7490196078);
  --color-input-fitting: #eef7ec;
  --color-paper: #f8fff6;
  --color-ink: #15261a;
  --color-on-accent: #f8fff6;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=christmas] {
  --color-white: #e8e4d8;
  --color-white-l: #98a39a;
  --color-white-h: #ffffff;
  --color-green: #2f8f4e;
  --color-green-h: #54c276;
  --color-blue: #3b7fb5;
  --color-blue-h: #6fb2e6;
  --color-red: #b3262e;
  --color-red-h: #ec4a52;
  --color-gold: #c9a23a;
  --color-gold-h: #f1cc5c;
  --color-gold-highlight: rgba(201, 162, 58, 0.6352941176);
  --color-dark: #0e1c15;
  --color-dark-b: #2d4a3a;
  --color-dark-l: #13251c;
  --color-dark-m: #11211a;
  --color-dark-h: #0a140f;
  --color-dark-t: rgba(19, 37, 28, 0.7490196078);
  --color-input-fitting: #f1f6f1;
  --color-paper: #fbfffb;
  --color-ink: #13251c;
  --color-on-accent: #ffffff;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=new-year] {
  --color-white: #e3dfd2;
  --color-white-l: #8e8a9c;
  --color-white-h: #fffaf0;
  --color-green: #3f9b7a;
  --color-green-h: #68d1a8;
  --color-blue: #4a64c4;
  --color-blue-h: #8197f0;
  --color-red: #b8435e;
  --color-red-h: #ef6f8a;
  --color-gold: #c9a43c;
  --color-gold-h: #ffd75e;
  --color-gold-highlight: rgba(201, 164, 60, 0.6352941176);
  --color-dark: #0e1022;
  --color-dark-b: #2d3256;
  --color-dark-l: #14172b;
  --color-dark-m: #111426;
  --color-dark-h: #090b19;
  --color-dark-t: rgba(20, 23, 43, 0.7490196078);
  --color-input-fitting: #f1f1f8;
  --color-paper: #fbfbff;
  --color-ink: #14172b;
  --color-on-accent: #fffaf0;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=dracula] {
  --color-white: #d8d8d2;
  --color-white-l: #6272a4;
  --color-white-h: #f8f8f2;
  --color-green: #2f9e4f;
  --color-green-h: #50fa7b;
  --color-blue: #7a5cc4;
  --color-blue-h: #bd93f9;
  --color-red: #c4344a;
  --color-red-h: #ff5555;
  --color-gold: #e2ea85;
  --color-gold-h: #f1fa8c;
  --color-gold-highlight: rgba(226, 234, 133, 0.6352941176);
  --color-dark: #1e1f29;
  --color-dark-b: #343746;
  --color-dark-l: #282a36;
  --color-dark-m: #21222c;
  --color-dark-h: #191a21;
  --color-dark-t: rgba(30, 31, 41, 0.7490196078);
  --color-input-fitting: #e2e2dc;
  --color-paper: #f8f8f2;
  --color-ink: #1e1f29;
  --color-on-accent: #f8f8f2;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=nord] {
  --color-white: #d8dee9;
  --color-white-l: #7b88a1;
  --color-white-h: #eceff4;
  --color-green: #6f8f5a;
  --color-green-h: #a3be8c;
  --color-blue: #5e81ac;
  --color-blue-h: #81a1c1;
  --color-red: #a9505a;
  --color-red-h: #d57780;
  --color-gold: #ebcb8b;
  --color-gold-h: #e5b85c;
  --color-gold-highlight: rgba(235, 203, 139, 0.6352941176);
  --color-dark: #272c36;
  --color-dark-b: #3b4252;
  --color-dark-l: #2e3440;
  --color-dark-m: #2a2f3a;
  --color-dark-h: #222730;
  --color-dark-t: rgba(39, 44, 54, 0.7490196078);
  --color-input-fitting: #e5e9f0;
  --color-paper: #eceff4;
  --color-ink: #272c36;
  --color-on-accent: #eceff4;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=solarized] {
  --color-white: #93a1a1;
  --color-white-l: #586e75;
  --color-white-h: #fdf6e3;
  --color-green: #718200;
  --color-green-h: #9cb300;
  --color-blue: #1f74b0;
  --color-blue-h: #268bd2;
  --color-red: #b8282a;
  --color-red-h: #f04a47;
  --color-gold: #b58900;
  --color-gold-h: #d4a20a;
  --color-gold-highlight: rgba(181, 137, 0, 0.6352941176);
  --color-dark: #002129;
  --color-dark-b: #073642;
  --color-dark-l: #002b36;
  --color-dark-m: #00252e;
  --color-dark-h: #001b22;
  --color-dark-t: rgba(0, 33, 41, 0.7490196078);
  --color-input-fitting: #eee8d5;
  --color-paper: #fdf6e3;
  --color-ink: #002129;
  --color-on-accent: #fdf6e3;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=gruvbox] {
  --color-white: #d5c4a1;
  --color-white-l: #928374;
  --color-white-h: #fbf1c7;
  --color-green: #79740e;
  --color-green-h: #b8bb26;
  --color-blue: #3c7477;
  --color-blue-h: #83a598;
  --color-red: #cc241d;
  --color-red-h: #fb4934;
  --color-gold: #d79921;
  --color-gold-h: #fabd2f;
  --color-gold-highlight: rgba(215, 153, 33, 0.6352941176);
  --color-dark: #1d2021;
  --color-dark-b: #3c3836;
  --color-dark-l: #282828;
  --color-dark-m: #242424;
  --color-dark-h: #181a1b;
  --color-dark-t: rgba(29, 32, 33, 0.7490196078);
  --color-input-fitting: #ebdbb2;
  --color-paper: #fbf1c7;
  --color-ink: #1d2021;
  --color-on-accent: #fbf1c7;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=one-dark] {
  --color-white: #abb2bf;
  --color-white-l: #5c6370;
  --color-white-h: #dcdfe4;
  --color-green: #5f8a41;
  --color-green-h: #98c379;
  --color-blue: #3a7fc0;
  --color-blue-h: #61afef;
  --color-red: #be5046;
  --color-red-h: #e06c75;
  --color-gold: #e5c07b;
  --color-gold-h: #d19a66;
  --color-gold-highlight: rgba(229, 192, 123, 0.6352941176);
  --color-dark: #21252b;
  --color-dark-b: #353b45;
  --color-dark-l: #282c34;
  --color-dark-m: #23272e;
  --color-dark-h: #1b1e23;
  --color-dark-t: rgba(33, 37, 43, 0.7490196078);
  --color-input-fitting: #dcdfe4;
  --color-paper: #dcdfe4;
  --color-ink: #21252b;
  --color-on-accent: #dcdfe4;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=tokyo-night] {
  --color-white: #a9b1d6;
  --color-white-l: #565f89;
  --color-white-h: #c0caf5;
  --color-green: #5c8a3a;
  --color-green-h: #9ece6a;
  --color-blue: #3d59a1;
  --color-blue-h: #7aa2f7;
  --color-red: #c0394f;
  --color-red-h: #f7768e;
  --color-gold: #e0af68;
  --color-gold-h: #ff9e64;
  --color-gold-highlight: rgba(224, 175, 104, 0.6352941176);
  --color-dark: #16161e;
  --color-dark-b: #24283b;
  --color-dark-l: #1a1b26;
  --color-dark-m: #171821;
  --color-dark-h: #121218;
  --color-dark-t: rgba(22, 22, 30, 0.7490196078);
  --color-input-fitting: #cfd6f2;
  --color-paper: #c0caf5;
  --color-ink: #16161e;
  --color-on-accent: #c0caf5;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=catppuccin] {
  --color-white: #bac2de;
  --color-white-l: #6c7086;
  --color-white-h: #cdd6f4;
  --color-green: #4f9a5a;
  --color-green-h: #a6e3a1;
  --color-blue: #4f78c4;
  --color-blue-h: #89b4fa;
  --color-red: #b8456b;
  --color-red-h: #f38ba8;
  --color-gold: #f9e2af;
  --color-gold-h: #fab387;
  --color-gold-highlight: rgba(249, 226, 175, 0.6352941176);
  --color-dark: #181825;
  --color-dark-b: #313244;
  --color-dark-l: #1e1e2e;
  --color-dark-m: #1a1a28;
  --color-dark-h: #11111b;
  --color-dark-t: rgba(24, 24, 37, 0.7490196078);
  --color-input-fitting: #d9e0ee;
  --color-paper: #cdd6f4;
  --color-ink: #181825;
  --color-on-accent: #cdd6f4;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=blossom] {
  --color-white: #f0dce8;
  --color-white-l: #a5859b;
  --color-white-h: #fff5fa;
  --color-green: #c94f86;
  --color-green-h: #f48fb8;
  --color-blue: #9161c9;
  --color-blue-h: #c9a2f5;
  --color-red: #c43a2f;
  --color-red-h: #ff6f61;
  --color-gold: #f5c0a8;
  --color-gold-h: #ffb38a;
  --color-gold-highlight: rgba(245, 192, 168, 0.6352941176);
  --color-dark: #241924;
  --color-dark-b: #3d2b3c;
  --color-dark-l: #2b1f2b;
  --color-dark-m: #271b27;
  --color-dark-h: #1d141d;
  --color-dark-t: rgba(36, 25, 36, 0.7490196078);
  --color-input-fitting: #f5e6ef;
  --color-paper: #fff5fa;
  --color-ink: #241924;
  --color-on-accent: #fff5fa;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=dim] {
  --color-white: #d9e1e8;
  --color-white-l: #8b98a5;
  --color-white-h: #f7f9f9;
  --color-green: #1d9bf0;
  --color-green-h: #4cb3f5;
  --color-blue: #7856ff;
  --color-blue-h: #9a80ff;
  --color-red: #e0245e;
  --color-red-h: #f4467e;
  --color-gold: #ffd400;
  --color-gold-h: #ffe14d;
  --color-gold-highlight: rgba(255, 212, 0, 0.5019607843);
  --color-dark: #10171e;
  --color-dark-b: #22303c;
  --color-dark-l: #15202b;
  --color-dark-m: #121c25;
  --color-dark-h: #0b1117;
  --color-dark-t: rgba(16, 23, 30, 0.7490196078);
  --color-input-fitting: #e1e8ed;
  --color-paper: #f7f9f9;
  --color-ink: #10171e;
  --color-on-accent: #f7f9f9;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=lounge] {
  --color-white: #dbdee1;
  --color-white-l: #949ba4;
  --color-white-h: #f2f3f5;
  --color-green: #5865f2;
  --color-green-h: #7984f5;
  --color-blue: #0a84c6;
  --color-blue-h: #00a8fc;
  --color-red: #da373c;
  --color-red-h: #f23f43;
  --color-gold: #f0b232;
  --color-gold-h: #f5c45e;
  --color-gold-highlight: rgba(240, 178, 50, 0.6352941176);
  --color-dark: #2b2d31;
  --color-dark-b: #3a3c42;
  --color-dark-l: #313338;
  --color-dark-m: #2e3035;
  --color-dark-h: #1e1f22;
  --color-dark-t: rgba(43, 45, 49, 0.7490196078);
  --color-input-fitting: #ebedef;
  --color-paper: #f2f3f5;
  --color-ink: #2b2d31;
  --color-on-accent: #f2f3f5;
  --color-scheme: dark;
  --syntax-literal: #ce4949;
  --syntax-keyword: #7474ff;
  --syntax-function: #d1b270;
  --syntax-variable: #7179b5;
  --syntax-annotation: #c7c74a;
  --syntax-type: #52b8d5;
}

[data-theme=daylight] {
  --color-white: #1f2328;
  --color-white-l: #656d76;
  --color-white-h: #0d1117;
  --color-green: #1a7f37;
  --color-green-h: #2da44e;
  --color-blue: #0969da;
  --color-blue-h: #218bff;
  --color-red: #cf222e;
  --color-red-h: #fa4549;
  --color-gold: #9a6700;
  --color-gold-h: #bf8700;
  --color-gold-highlight: rgba(212, 167, 44, 0.4);
  --color-dark: #ffffff;
  --color-dark-b: #e6e6e1;
  --color-dark-l: #f6f6f3;
  --color-dark-m: #eeeeea;
  --color-dark-h: #e3e3de;
  --color-dark-t: rgba(214, 214, 207, 0.7490196078);
  --color-input-fitting: #f6f6f3;
  --color-paper: #ffffff;
  --color-ink: #1f2328;
  --color-on-accent: #ffffff;
  --color-scheme: light;
  --syntax-literal: #a31515;
  --syntax-keyword: #0000ff;
  --syntax-function: #795e26;
  --syntax-variable: #001080;
  --syntax-annotation: #808000;
  --syntax-type: #267f99;
}

[data-theme=petal] {
  --color-white: #3d2a35;
  --color-white-l: #8a6f7e;
  --color-white-h: #24151e;
  --color-green: #c2417a;
  --color-green-h: #d9609a;
  --color-blue: #8a4fb8;
  --color-blue-h: #a46bd1;
  --color-red: #c0392b;
  --color-red-h: #e0533f;
  --color-gold: #a8613a;
  --color-gold-h: #c27448;
  --color-gold-highlight: rgba(244, 166, 198, 0.4);
  --color-dark: #fffafc;
  --color-dark-b: #f8e1eb;
  --color-dark-l: #fdf1f6;
  --color-dark-m: #fae9f0;
  --color-dark-h: #f6dbe7;
  --color-dark-t: rgba(243, 211, 225, 0.7490196078);
  --color-input-fitting: #fdf1f6;
  --color-paper: #ffffff;
  --color-ink: #3d2a35;
  --color-on-accent: #ffffff;
  --color-scheme: light;
  --syntax-literal: #a31515;
  --syntax-keyword: #0000ff;
  --syntax-function: #795e26;
  --syntax-variable: #001080;
  --syntax-annotation: #808000;
  --syntax-type: #267f99;
}

[data-theme=barbie] {
  --color-white: #4a0d2e;
  --color-white-l: #9c4f78;
  --color-white-h: #2b0519;
  --color-green: #d6197f;
  --color-green-h: #f03c9a;
  --color-blue: #7b2fbe;
  --color-blue-h: #9b4fe0;
  --color-red: #c2410c;
  --color-red-h: #ea580c;
  --color-gold: #9c5a00;
  --color-gold-h: #b86e00;
  --color-gold-highlight: rgba(255, 143, 207, 0.4);
  --color-dark: #fff5fa;
  --color-dark-b: #ffc6e3;
  --color-dark-l: #ffe0f0;
  --color-dark-m: #ffd3ea;
  --color-dark-h: #ffd6ea;
  --color-dark-t: rgba(255, 179, 217, 0.7490196078);
  --color-input-fitting: #fff0f7;
  --color-paper: #ffffff;
  --color-ink: #4a0d2e;
  --color-on-accent: #ffffff;
  --color-scheme: light;
  --syntax-literal: #a31515;
  --syntax-keyword: #0000ff;
  --syntax-function: #795e26;
  --syntax-variable: #001080;
  --syntax-annotation: #808000;
  --syntax-type: #267f99;
}

:root {
  --syntax-paper-literal: #a31515;
  --syntax-paper-keyword: #0000ff;
  --syntax-paper-function: #795e26;
  --syntax-paper-variable: #001080;
  --syntax-paper-annotation: #808000;
  --syntax-paper-type: #267f99;
}

html {
  font-family: "Consolas", "Fira Code", monospace;
  background-color: var(--color-dark-b);
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0px;
}

/* Hide scroll when a class is active on body */
body.no-scroll {
  overflow: hidden; /* Prevent scroll on desktop */
  height: 100%; /* Ensure full height */
  touch-action: none; /* Disable touch scrolling on mobile */
}

input[type=checkbox] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  margin: 0 6px 0 0;
  vertical-align: -2px;
  cursor: pointer;
}

input[type=checkbox]:hover {
  border-color: var(--color-green);
}

input[type=checkbox]:focus-visible {
  outline: none;
  border-color: var(--color-green-h);
}

#globalTooltip {
  position: fixed;
  z-index: 2147483647;
  background-color: var(--color-dark-h);
  color: var(--color-white-h);
  font-family: "Consolas", "Fira Code", monospace;
  font-size: 12px;
  line-height: 1.4;
  text-align: center;
  width: max-content;
  max-width: min(220px, 100vw - 16px);
  white-space: normal;
  padding: 5px 10px;
  border-radius: 6px;
  box-shadow: 0 2px 8px var(--color-dark);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
  transform: translateY(-4px);
}

/* Opt-in roomier variant for tooltips holding a sentence or two rather than a short label — see
   data-tooltip-wide in commonScripts.js's showGlobalTooltip. */
#globalTooltip.wide {
  max-width: min(340px, 100vw - 16px);
  text-align: left;
}

#globalTooltip::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
}

#globalTooltip.placement-below::after {
  top: -10px;
  border-bottom-color: var(--color-dark-h);
}

#globalTooltip.placement-above::after {
  bottom: -10px;
  border-top-color: var(--color-dark-h);
}

#globalTooltip.visible {
  opacity: 1;
  transform: translateY(0);
}

#ContainerMain {
  padding: 40px;
  background-color: var(--color-dark-l);
  clear: both;
}

/* Workbench shell: collapsible left rail + main column. Padding moves onto #MainColumn so the
   side nav can sit edge-to-edge against the viewport while content keeps the same inset. */
#ContainerMain.workbench-shell {
  display: flex;
  align-items: stretch;
  gap: 0;
  padding: 0;
  min-height: calc(100vh - 80px);
}

#ContainerMain.workbench-shell #MainColumn {
  flex: 1;
  min-width: 0;
  padding: 40px;
  display: flex;
  flex-direction: column;
}

#ContainerMain.workbench-shell #SideNav.side-nav {
  flex: 0 0 220px;
  width: 220px;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 40;
  height: auto;
  max-height: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 10px 12px;
  box-sizing: border-box;
  /* Raised band against #MainColumn. Fixed to the viewport so it runs to the bottom of the
     screen and paints over the footer rather than stopping where the column ends. */
  background-color: var(--color-dark-b);
  border-right: 1px solid var(--color-dark-h);
  overflow: hidden;
  transition: width 0.2s ease, flex-basis 0.2s ease;
}

/* The rail is out of flow (fixed), so the column keeps the width it used to occupy. */
body.has-side-nav #ContainerMain.workbench-shell #MainColumn {
  margin-left: 220px;
  transition: margin-left 0.2s ease;
}

#ContainerMain.workbench-shell #SideNav.side-nav[hidden] {
  display: none;
}

#container {
  width: 100%;
  position: relative;
  margin: 0 auto;
  overflow: auto;
  overflow-y: hidden;
  overflow-x: hidden;
  min-width: 320px;
}

footer {
  clear: both;
  margin-bottom: 8px;
  bottom: 0;
  /* Same band as the header (#TitleArea). */
  background-color: var(--color-dark-m);
  padding: 40px;
  text-align: center;
}

/* The rail covers the footer's left edge. Inset the columns so the links stay beside it. */
body.has-side-nav footer {
  padding-left: 260px;
  transition: padding-left 0.2s ease;
}

/* Midnight Dark and Twilight Dark's page-behind colour (dark-b) is a pale grey, which would
   show as a light band in the margin under the footer. The footer matches the header (dark-m);
   the html background follows it so that strip does too. The rail stays on the darkest shade. */
html[data-theme=midnight-dark],
html[data-theme=twilight-dark] {
  background-color: var(--color-dark-m);
}

html[data-theme=midnight-dark] #ContainerMain.workbench-shell #SideNav.side-nav,
html[data-theme=twilight-dark] #ContainerMain.workbench-shell #SideNav.side-nav {
  background-color: var(--color-dark-h);
}

#footerTagline {
  color: var(--color-white-l);
  font-style: italic;
  margin-top: 16px;
  margin-bottom: 0;
}

#FooterColumns {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 24px 60px;
  margin-bottom: 20px;
}

.footerColumn {
  text-align: left;
  min-width: 140px;
}

.footerColumnTitle {
  color: var(--color-white-l);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin: 0 0 8px;
}

.footerColumn .userButton {
  margin-bottom: 4px;
}

.footerColumn .userButton:last-child {
  margin-bottom: 0;
}

iframe[seamless] {
  border: none;
}

* {
  font-size: 12px;
  color: var(--color-white);
  font-family: "Consolas", "Fira Code", monospace;
}

hr {
  clear: both;
  margin-bottom: 15px;
}

#FilterArea,
#TitleArea {
  display: flex;
  align-items: center; /* vertically center content */
  justify-content: space-between; /* push items to edges */
  gap: 8px;
}

.title {
  float: left;
  color: var(--color-white-h);
  font-size: 24px;
}

.page-title {
  float: left;
  color: var(--color-white-h);
  font-size: 16px;
  padding-left: 15px;
  margin-top: -3px;
}

/* Utility bar in the main column: Workbench crumb, search, and (when signed out) Sign in.
   Negative margins pull it over #MainColumn's padding to the column edges. Still inside
   #ContainerMain so each view's click-off-to-collapse handler keeps seeing header clicks. */
#TitleArea {
  flex-wrap: wrap;
  align-items: center;
  column-gap: 16px;
  row-gap: 10px;
  margin: -40px -40px 28px;
  padding: 10px 40px;
  min-height: 44px;
  box-sizing: border-box;
  background-color: var(--color-dark-m);
  border-bottom: 1px solid var(--color-dark-b);
}

/* Flush the header into the workbench toolbar on every section that has one (Cheats,
   Tasks, Brain, Vault, …) — otherwise TitleArea's bottom margin leaves a band. */
body:has(.cheats-toolbar) #TitleArea {
  margin-bottom: 0;
  border-bottom: 0;
}

/* Forced Mobile view uses the narrow-layout rules at full main-column width — no phone-sized
   centered column on a widescreen (that just looked like a skinny strip in the middle). */
/* Workbench utility crumb: cheatsheet/{section} — muted root, strong current section. */
.main-crumb {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0;
  margin: 0;
  font-size: 12px;
  line-height: 1.3;
  color: var(--color-white-l);
  text-transform: none;
}

.main-crumb-root,
.main-crumb-sep {
  color: var(--color-white-l);
  text-decoration: none;
  text-transform: none;
  font-weight: 400;
}

.main-crumb-root:hover,
.main-crumb-root:focus-visible {
  color: var(--color-white);
  outline: none;
}

.main-crumb-section {
  color: var(--color-white-h);
  text-decoration: none;
  text-transform: none;
  font-weight: 500;
}

.main-crumb-section:hover,
.main-crumb-section:focus-visible {
  color: var(--color-white);
  outline: none;
}

/* For a heading that has to stay in the page for screen readers and search engines but would only
   repeat what's already on screen: a view's <h1>, now that its link in the header is the visible
   title. */
.visuallyHidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

#TitleLeft {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 20px;
  min-width: 0;
}

/* Search docks to the right of the crumb, Workbench utility-bar style. */
#TitleArea .search_bar {
  flex: 0 1 320px;
  max-width: 320px;
  margin: 0 0 0 auto;
}

/* The box inside it fills the bar rather than keeping its own width, so the bar's growth shows. */
#TitleArea .search_form {
  display: block;
}

#TitleArea .search_form,
#TitleArea .search_bar input {
  width: 100%;
  box-sizing: border-box;
}

/* %input-base uses $color-ink for light fields; this bar sits on the dark utility band, so
   text/caret have to be the light roles or they vanish against $color-dark-h. */
#TitleArea .search_bar input,
#scrollChrome .search_bar input {
  background-color: var(--color-dark-h);
  border: 1px solid var(--color-dark-b);
  border-radius: 4px;
  color: var(--color-white-h);
  caret-color: var(--color-white-h);
}

#TitleArea .search_bar input::placeholder,
#scrollChrome .search_bar input::placeholder {
  color: var(--color-white-l);
  opacity: 1;
}

/* ——— Workbench side rail ——— */
.side-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 8px;
  min-height: 32px;
  flex-shrink: 0;
}

.side-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 0 4px;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--color-green);
}

.side-brand-mark {
  display: none;
  width: 28px;
  height: 28px;
  border-radius: 4px;
  place-items: center;
  background-color: var(--color-dark-l);
  color: var(--color-green);
  font-size: 11px;
  font-weight: 600;
  text-transform: lowercase;
  text-decoration: none;
}

.side-brand-label {
  display: inline-flex;
  align-items: baseline;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Workbench B side brand: green "cheatsheet/" (section crumb lives in the main utility bar). */
.side-crumb,
.side-crumb-sep {
  text-transform: none;
  text-decoration: none;
}

.side-crumb-brand,
.side-crumb-sep {
  color: var(--color-green);
}

.side-crumb-brand:hover,
.side-crumb-brand:focus-visible,
a.side-brand-mark:hover,
a.side-brand-mark:focus-visible {
  color: var(--color-green-h);
  outline: none;
}

.side-nav-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 4px 8px;
  border: 1px solid var(--color-dark-b);
  border-radius: 4px;
  background: transparent;
  color: var(--color-white-l);
  font: inherit;
  font-size: 11px;
  text-transform: none;
  cursor: pointer;
}

.side-nav-toggle:hover,
.side-nav-toggle:focus-visible {
  color: var(--color-white-h);
  border-color: color-mix(in srgb, var(--color-white) 22%, transparent);
  outline: none;
}

.side-nav-groups {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
}

.navGroup {
  display: none;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}

.navGroup.hasItems {
  display: flex;
}

.navGroupLabel {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-white-l);
  margin: 12px 8px 4px;
  min-height: 14px;
}

.navGroup:first-child .navGroupLabel {
  margin-top: 4px;
}

.navLink {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: 4px;
  color: var(--color-white);
  font-size: 13px;
  text-transform: none;
  min-height: 32px;
  text-decoration: none;
}

.navLink:hover,
.navLink:focus-visible {
  color: var(--color-white-h);
  background-color: var(--color-dark-l);
  outline: none;
}

.navLink.active {
  background-color: var(--color-dark-l);
  color: var(--color-white-h);
}

.navIco {
  width: 22px;
  flex: 0 0 22px;
  text-align: center;
  color: var(--color-white-l);
  font-size: 11px;
  text-transform: lowercase;
}

.navLink.active .navIco {
  color: var(--color-green);
}

.navLabel {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* View / Cheats layout overrides (DisplayPrefs in public/js/displayPrefs.js). */
.side-display {
  flex-shrink: 0;
  margin-top: auto;
  padding: 10px 8px 0;
  border-top: 1px solid var(--color-dark-h);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.side-display-label {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-white-l);
}

.side-display-seg {
  display: inline-flex;
  flex-wrap: wrap;
  border: 1px solid var(--color-dark-h);
  border-radius: 4px;
  overflow: hidden;
  width: 100%;
}

.side-display-btn {
  flex: 1 1 auto;
  margin: 0;
  padding: 5px 6px;
  border: 0;
  border-left: 1px solid var(--color-dark-h);
  border-radius: 0;
  background: transparent;
  color: var(--color-white-l);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}

.side-display-btn:first-child {
  border-left: 0;
}

.side-display-btn:hover:not(:disabled),
.side-display-btn:focus-visible:not(:disabled) {
  background-color: var(--color-dark-l);
  color: var(--color-white-h);
  outline: none;
}

.side-display-btn.on {
  background-color: var(--color-dark-l);
  color: var(--color-green);
}

.side-display-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.side-display-layout[hidden],
.side-display-btn-three[hidden] {
  display: none;
}

body.side-nav-collapsed .side-display {
  padding: 8px 4px 0;
}

body.side-nav-collapsed .side-display-label {
  display: none;
}

body.side-nav-collapsed .side-display-seg {
  flex-direction: column;
}

body.side-nav-collapsed .side-display-btn {
  border-left: 0;
  border-top: 1px solid var(--color-dark-h);
  padding: 6px 0;
  font-size: 0;
  line-height: 0;
}

body.side-nav-collapsed .side-display-btn:first-child {
  border-top: 0;
}

body.side-nav-collapsed .side-display-btn::before {
  font-size: 10px;
  line-height: 1.2;
}

body.side-nav-collapsed .side-display-btn[data-viewport=auto]::before {
  content: "A";
}

body.side-nav-collapsed .side-display-btn[data-viewport=desktop]::before {
  content: "D";
}

body.side-nav-collapsed .side-display-btn[data-viewport=mobile]::before {
  content: "M";
}

body.side-nav-collapsed .side-display-btn[data-list-layout=rows]::before {
  content: "1";
}

body.side-nav-collapsed .side-display-btn[data-list-layout=two]::before {
  content: "2";
}

body.side-nav-collapsed .side-display-btn[data-list-layout=three]::before {
  content: "3";
}

.side-foot {
  flex-shrink: 0;
  padding-top: 10px;
  border-top: 1px solid var(--color-dark-h);
}

/* Tagline + copyright live in the rail when signed in; the page footer keeps the link columns. */
.side-meta {
  margin-top: 10px;
  padding: 0 8px 2px;
}

.side-tagline,
.side-copyright {
  margin: 0;
  font-size: 10px;
  line-height: 1.35;
  color: var(--color-white-l);
}

.side-tagline {
  font-style: italic;
  margin-bottom: 6px;
}

.side-copyright a {
  color: var(--color-white-l);
  text-decoration: none;
}

.side-copyright a:hover,
.side-copyright a:focus-visible {
  color: var(--color-white);
  outline: none;
}

body.has-side-nav footer #copyright,
body.has-side-nav footer #footerTagline {
  display: none;
}

/* Stronger than `.pill-group .userButton` so the rail foot doesn't inherit the header chip's
   12px side padding and spill past the drawer edge. */
.side-account.pill-group {
  display: block;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  gap: 0;
  box-sizing: border-box;
}

.side-account.pill-group .userButton {
  display: block;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  background: transparent;
  border: 0;
  border-radius: 4px;
}

.side-account .accountToggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  padding: 8px;
  border-radius: 4px;
  color: var(--color-white-h);
  font-size: 13px;
  text-transform: none;
  text-decoration: none;
}

.side-account .accountToggle:hover,
.side-account .accountMenuWrap.open .accountToggle {
  background-color: var(--color-dark-l);
}

.side-account .accountIco {
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background-color: var(--color-dark-l);
  border: 1px solid var(--color-dark-h);
  font-size: 10px;
  font-weight: 600;
  color: var(--color-white-h);
}

.side-account .accountName {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.side-account .accountInitials {
  display: grid;
}

/* Collapsed rail: icons only */
body.side-nav-collapsed #ContainerMain.workbench-shell #SideNav.side-nav {
  width: 56px;
  flex-basis: 56px;
  padding: 10px 6px 12px;
}

body.has-side-nav.side-nav-collapsed #ContainerMain.workbench-shell #MainColumn {
  margin-left: 56px;
}

body.has-side-nav.side-nav-collapsed footer {
  padding-left: 96px;
}

body.side-nav-collapsed .side-brand-label,
body.side-nav-collapsed .navGroupLabel,
body.side-nav-collapsed .navLabel,
body.side-nav-collapsed .sideNavToggleLabel,
body.side-nav-collapsed .side-account .accountName,
body.side-nav-collapsed .side-meta {
  display: none;
}

body.side-nav-collapsed .side-brand-mark {
  display: grid;
}

body.side-nav-collapsed .side-top {
  justify-content: center;
  flex-direction: column;
  gap: 8px;
}

body.side-nav-collapsed .side-nav-toggle {
  width: 100%;
  justify-content: center;
  padding: 6px 0;
}

body.side-nav-collapsed .navLink {
  justify-content: center;
  padding: 8px 0;
}

body.side-nav-collapsed .navIco {
  width: 100%;
}

body.side-nav-collapsed .side-account .accountToggle {
  justify-content: center;
  padding: 6px 0;
}

body.side-nav-collapsed .side-account .accountIco {
  margin: 0 auto;
}

@media (prefers-reduced-motion: reduce) {
  #ContainerMain.workbench-shell #SideNav.side-nav,
  body.has-side-nav #ContainerMain.workbench-shell #MainColumn,
  body.has-side-nav footer {
    transition: none;
  }
}
/* Phone/tablet: rail becomes a slide-over drawer; Menu button opens it. */
.navMenuToggle {
  display: none;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 6px 12px;
  border: 1px solid var(--color-dark-l);
  border-radius: 8px;
  background-color: var(--color-dark-h);
  color: var(--color-white-h);
  font: inherit;
  font-size: 13px;
  text-transform: none;
  cursor: pointer;
}

.navMenuToggle:hover,
.navMenuToggle:focus-visible {
  border-color: var(--color-white-l);
  outline: none;
}

.navDrawerScrim {
  display: none;
}

@media screen and (max-width: 1100px) {
  html:not([data-viewport-mode=desktop]) .navMenuToggle {
    display: inline-flex;
  }
  html:not([data-viewport-mode=desktop]) body.has-side-nav #ContainerMain.workbench-shell #MainColumn,
  html:not([data-viewport-mode=desktop]) body.has-side-nav.side-nav-collapsed #ContainerMain.workbench-shell #MainColumn {
    margin-left: 0;
  }
  html:not([data-viewport-mode=desktop]) body.has-side-nav footer,
  html:not([data-viewport-mode=desktop]) body.has-side-nav.side-nav-collapsed footer {
    padding-left: 40px;
  }
  html:not([data-viewport-mode=desktop]) body.has-side-nav #ContainerMain.workbench-shell #SideNav.side-nav,
  html:not([data-viewport-mode=desktop]) #ContainerMain.workbench-shell #SideNav.side-nav:not([hidden]) {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 450;
    flex: none;
    width: min(320px, 86vw) !important;
    max-width: 320px;
    height: 100%;
    height: 100dvh;
    max-height: none;
    margin: 0;
    /* Keep the account foot fully on-screen: groups scroll, foot stays pinned. */
    padding: 16px;
    padding-bottom: max(20px, env(safe-area-inset-bottom, 0px));
    border: 0;
    border-radius: 0;
    background-color: var(--color-dark-b);
    overflow: hidden;
    transform: translateX(-105%);
    transition: transform 0.2s ease;
    visibility: hidden;
    pointer-events: none;
  }
  html:not([data-viewport-mode=desktop]) body.nav-drawer-open #ContainerMain.workbench-shell #SideNav.side-nav {
    transform: translateX(0);
    visibility: visible;
    pointer-events: auto;
  }
  html:not([data-viewport-mode=desktop]) body.nav-drawer-open {
    overflow: hidden;
  }
  html:not([data-viewport-mode=desktop]) body.nav-drawer-open .navDrawerScrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 440;
    background-color: var(--color-dark-t);
  }
  html:not([data-viewport-mode=desktop]) {
    /* Slides down from the top once #TitleArea has scrolled away, and stays there. Menu and
       the page's search field are moved into it (see updateScrollChrome in auth.js). */
  }
  html:not([data-viewport-mode=desktop]) #scrollChrome {
    display: flex;
    align-items: center;
    gap: 10px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 430;
    box-sizing: border-box;
    padding: 8px 12px;
    padding-top: max(8px, env(safe-area-inset-top, 0px));
    background-color: var(--color-dark-m);
    border-bottom: 1px solid var(--color-dark-h);
    transform: translateY(-100%);
    transition: transform 0.2s ease;
  }
  html:not([data-viewport-mode=desktop]) #scrollChrome.is-in {
    transform: translateY(0);
  }
  html:not([data-viewport-mode=desktop]) #scrollChrome[hidden] {
    display: none;
  }
  html:not([data-viewport-mode=desktop]) #scrollChrome .navMenuToggle {
    flex: 0 0 auto;
  }
  html:not([data-viewport-mode=desktop]) #scrollChrome .search_bar {
    flex: 1 1 auto;
    min-width: 0;
    float: none;
    margin: 0;
  }
  html:not([data-viewport-mode=desktop]) #scrollChrome .search_form,
  html:not([data-viewport-mode=desktop]) #scrollChrome .search_bar input {
    width: 100%;
    box-sizing: border-box;
  }
  html:not([data-viewport-mode=desktop]) {
    /* On a phone the rail is a drawer, so this control closes it instead of collapsing. */
  }
  html:not([data-viewport-mode=desktop]) .side-nav-toggle {
    display: inline-flex;
  }
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .side-nav-toggle {
    width: auto;
    padding: 4px 8px;
  }
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .side-brand-label,
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .navGroupLabel,
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .navLabel,
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .side-account .accountName,
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .side-meta {
    display: revert;
  }
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .side-brand-mark {
    display: none;
  }
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .navLink {
    justify-content: flex-start;
    padding: 7px 8px;
  }
  html:not([data-viewport-mode=desktop]) body.side-nav-collapsed .navIco {
    width: 22px;
  }
}
@media screen and (max-width: 1100px) and (prefers-reduced-motion: reduce) {
  html:not([data-viewport-mode=desktop]) #ContainerMain.workbench-shell #SideNav.side-nav,
  html:not([data-viewport-mode=desktop]) #scrollChrome {
    transition: none;
  }
}
html[data-viewport-mode=mobile] .navMenuToggle {
  display: inline-flex;
}
html[data-viewport-mode=mobile] body.has-side-nav #ContainerMain.workbench-shell #MainColumn,
html[data-viewport-mode=mobile] body.has-side-nav.side-nav-collapsed #ContainerMain.workbench-shell #MainColumn {
  margin-left: 0;
}
html[data-viewport-mode=mobile] body.has-side-nav footer,
html[data-viewport-mode=mobile] body.has-side-nav.side-nav-collapsed footer {
  padding-left: 40px;
}
html[data-viewport-mode=mobile] body.has-side-nav #ContainerMain.workbench-shell #SideNav.side-nav,
html[data-viewport-mode=mobile] #ContainerMain.workbench-shell #SideNav.side-nav:not([hidden]) {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 450;
  flex: none;
  width: min(320px, 86vw) !important;
  max-width: 320px;
  height: 100%;
  height: 100dvh;
  max-height: none;
  margin: 0;
  /* Keep the account foot fully on-screen: groups scroll, foot stays pinned. */
  padding: 16px;
  padding-bottom: max(20px, env(safe-area-inset-bottom, 0px));
  border: 0;
  border-radius: 0;
  background-color: var(--color-dark-b);
  overflow: hidden;
  transform: translateX(-105%);
  transition: transform 0.2s ease;
  visibility: hidden;
  pointer-events: none;
}
html[data-viewport-mode=mobile] body.nav-drawer-open #ContainerMain.workbench-shell #SideNav.side-nav {
  transform: translateX(0);
  visibility: visible;
  pointer-events: auto;
}
html[data-viewport-mode=mobile] body.nav-drawer-open {
  overflow: hidden;
}
html[data-viewport-mode=mobile] body.nav-drawer-open .navDrawerScrim {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 440;
  background-color: var(--color-dark-t);
}
html[data-viewport-mode=mobile] {
  /* Slides down from the top once #TitleArea has scrolled away, and stays there. Menu and
     the page's search field are moved into it (see updateScrollChrome in auth.js). */
}
html[data-viewport-mode=mobile] #scrollChrome {
  display: flex;
  align-items: center;
  gap: 10px;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 430;
  box-sizing: border-box;
  padding: 8px 12px;
  padding-top: max(8px, env(safe-area-inset-top, 0px));
  background-color: var(--color-dark-m);
  border-bottom: 1px solid var(--color-dark-h);
  transform: translateY(-100%);
  transition: transform 0.2s ease;
}
html[data-viewport-mode=mobile] #scrollChrome.is-in {
  transform: translateY(0);
}
html[data-viewport-mode=mobile] #scrollChrome[hidden] {
  display: none;
}
html[data-viewport-mode=mobile] #scrollChrome .navMenuToggle {
  flex: 0 0 auto;
}
html[data-viewport-mode=mobile] #scrollChrome .search_bar {
  flex: 1 1 auto;
  min-width: 0;
  float: none;
  margin: 0;
}
html[data-viewport-mode=mobile] #scrollChrome .search_form,
html[data-viewport-mode=mobile] #scrollChrome .search_bar input {
  width: 100%;
  box-sizing: border-box;
}
html[data-viewport-mode=mobile] {
  /* On a phone the rail is a drawer, so this control closes it instead of collapsing. */
}
html[data-viewport-mode=mobile] .side-nav-toggle {
  display: inline-flex;
}
html[data-viewport-mode=mobile] body.side-nav-collapsed .side-nav-toggle {
  width: auto;
  padding: 4px 8px;
}
html[data-viewport-mode=mobile] body.side-nav-collapsed .side-brand-label,
html[data-viewport-mode=mobile] body.side-nav-collapsed .navGroupLabel,
html[data-viewport-mode=mobile] body.side-nav-collapsed .navLabel,
html[data-viewport-mode=mobile] body.side-nav-collapsed .side-account .accountName,
html[data-viewport-mode=mobile] body.side-nav-collapsed .side-meta {
  display: revert;
}
html[data-viewport-mode=mobile] body.side-nav-collapsed .side-brand-mark {
  display: none;
}
html[data-viewport-mode=mobile] body.side-nav-collapsed .navLink {
  justify-content: flex-start;
  padding: 7px 8px;
}
html[data-viewport-mode=mobile] body.side-nav-collapsed .navIco {
  width: 22px;
}
@media (prefers-reduced-motion: reduce) {
  html[data-viewport-mode=mobile] #ContainerMain.workbench-shell #SideNav.side-nav,
  html[data-viewport-mode=mobile] #scrollChrome {
    transition: none;
  }
}

/* ——— Workbench Cheats toolbar + feed (concept B) ———
   Sibling of #TitleArea (not inside #container) so overflow-x:hidden there cannot clip the bleed.
   Negative margins match #TitleArea and cancel #MainColumn's 40px padding.
   Filter + Sort stack in .toolbar-controls; Type takes the remaining width beside them. */
.cheats-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  align-items: flex-start;
  width: auto;
  padding: 10px 40px;
  margin: 0 -40px 16px;
  background-color: var(--color-dark);
  border: 0;
  border-bottom: 1px solid var(--color-dark-b);
  border-radius: 0;
  box-sizing: border-box;
}

.cheats-toolbar .toolbar-controls {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 0 0 auto;
}

.cheats-toolbar .toolbar-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.cheats-toolbar .toolbar-label {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-white-l);
}

.cheats-toolbar .toolbar-sort .toolbar-label {
  color: var(--color-gold);
}

.cheats-toolbar .toolbar-types {
  flex: 1 1 280px;
  min-width: min(100%, 280px);
}

/* Per-tab filters for Dues / Hours / Pennies — same band as Cheats Type, filled by JS. */
.toolbar-filters {
  flex: 1 1 280px;
  min-width: min(100%, 280px);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.toolbar-filters[hidden] {
  display: none !important;
}

.cheats-toolbar .pennyFilters,
.cheats-toolbar .duesFilters,
.cheats-toolbar .hoursFilters {
  margin-bottom: 0;
}

.cheats-toolbar .pennyFilterRow,
.cheats-toolbar .duesFilterRow,
.cheats-toolbar .hoursFilterRow {
  margin-bottom: 0;
}

.cheats-toolbar .pennyImportOpen {
  align-self: flex-start;
  margin: 4px 0 0;
}

.toolbar-filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.toolbar-type-row .type-cheat {
  margin: 0;
}

.filter-seg {
  display: inline-flex;
  flex-wrap: wrap;
  border: 1px solid var(--color-dark-b);
  border-radius: 4px;
  overflow: hidden;
}

.filter-seg .userButton {
  margin: 0;
  padding: 0;
  border-radius: 0;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--color-dark-b);
}

.filter-seg .userButton:first-child {
  border-left: 0;
}

.filter-seg .userButton a,
.filter-seg .userButton:not(:has(a)) {
  display: block;
  padding: 5px 10px;
  text-transform: none;
  color: var(--color-white-l);
}

.filter-seg .userButton:hover {
  background-color: var(--color-dark-l);
  border-color: var(--color-dark-b);
}

.filter-seg .userButton.active {
  background-color: var(--color-dark-l);
  border-color: var(--color-dark-b);
}

.filter-seg .userButton.active,
.filter-seg .userButton.active a {
  color: var(--color-green);
}

.sort-select {
  appearance: none;
  -webkit-appearance: none;
  background-color: var(--color-dark-h);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath fill='%237c7c7c' d='M0 0l5 6 5-6z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  border: 1px solid color-mix(in srgb, var(--color-gold) 35%, var(--color-dark-b));
  border-radius: 4px;
  color: var(--color-white-h);
  font: inherit;
  font-size: 12px;
  padding: 5px 26px 5px 10px;
  min-width: 110px;
  cursor: pointer;
}

.sort-select:hover,
.sort-select:focus-visible {
  border-color: color-mix(in srgb, var(--color-gold) 55%, var(--color-dark-b));
  outline: none;
}

.toolbar-type-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: baseline;
}

/* Browse feed: full-width rows with type beside title (Cheats, Tasks, Brain, Vault, …). */
.cheat-feed {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 10px;
  margin-bottom: 12px;
  clear: both;
}

/* Desktop multi-column: side-by-side cards; expanded/edit/empty-state still span the full row.
   Applied to every .cheat-feed (Cheats, Vault, Tasks, Brain, Hours, Pennies, Dues). */
.cheat-feed.cheat-feed--two,
.cheat-feed.cheat-feed--three {
  display: grid;
  align-items: start;
}

.cheat-feed.cheat-feed--two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.cheat-feed.cheat-feed--three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.cheat-feed.cheat-feed--two .cheat.large,
.cheat-feed.cheat-feed--two .cheat.revise,
.cheat-feed.cheat-feed--two .cheat.max,
.cheat-feed.cheat-feed--two .cheat.editing,
.cheat-feed.cheat-feed--two > p,
.cheat-feed.cheat-feed--three .cheat.large,
.cheat-feed.cheat-feed--three .cheat.revise,
.cheat-feed.cheat-feed--three .cheat.max,
.cheat-feed.cheat-feed--three .cheat.editing,
.cheat-feed.cheat-feed--three > p {
  grid-column: 1/-1;
}

@media screen and (max-width: 1000px) {
  html:not([data-viewport-mode=desktop]) .cheat-feed.cheat-feed--two,
  html:not([data-viewport-mode=desktop]) .cheat-feed.cheat-feed--three {
    display: flex;
    flex-direction: column;
  }
}
html[data-viewport-mode=mobile] .cheat-feed.cheat-feed--two,
html[data-viewport-mode=mobile] .cheat-feed.cheat-feed--three {
  display: flex;
  flex-direction: column;
}

.cheat-feed .cheat {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  height: auto;
  margin: 0;
}

.cheat-feed .cheat.large,
.cheat-feed .cheat.revise,
.cheat-feed .cheat.max {
  width: 100% !important;
}

.cheat-feed .cheat-main {
  padding: 10px 12px 12px;
  min-height: 0;
  height: auto;
  max-height: none;
}

.cheat-feed .cheat-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 10px;
  margin-bottom: 8px;
}

.cheat-feed .cheat-type {
  float: none;
  margin: 0;
  flex: 0 0 auto;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-green);
  background-color: color-mix(in srgb, var(--color-green) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-green) 35%, transparent);
}

.cheat-feed .cheat-title {
  float: none;
  clear: none;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  /* Beat the mobile `h1 { font-size: 1.5em !important }` so feed titles stay compact. */
  font-size: 14px !important;
  font-weight: 600;
  text-transform: none;
}

.cheat-feed .cheat-stats {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  font-size: 11px;
  color: var(--color-white-l);
}

.cheat-feed .cheat-stats .cheat-details, .cheat-feed .cheat-stats .billingPeriodToggle, .cheat-feed .cheat-stats .duesArchivedPill, .cheat-feed .cheat-stats .duesFrozenPill, .cheat-feed .cheat-stats .duesStatus, .cheat-feed .cheat-stats .duesCycle,
.cheat-feed .cheat-stats .duesSchedule, .cheat-feed .cheat-stats .hoursArchivedPill, .cheat-feed .cheat-stats .hoursOverride, .cheat-feed .cheat-stats .projectAuthorInput, .cheat-feed .cheat-stats .projectType, .cheat-feed .cheat-stats .projectName,
.cheat-feed .cheat-stats .projectStatus, .cheat-feed .cheat-stats .pennyStatus, .cheat-feed .cheat-stats .pennySide,
.cheat-feed .cheat-stats .taskDuration, .cheat-feed .cheat-stats .cheat-type,
.cheat-feed .cheat-stats .cheat-stars,
.cheat-feed .cheat-stats .cheat-point-total,
.cheat-feed .cheat-stats .star-cheat,
.cheat-feed .cheat-stats .cheat-star-total,
.cheat-feed .cheat-stats .score-star-cheat,
.cheat-feed .cheat-stats .score-up-cheat,
.cheat-feed .cheat-stats .score-down-cheat,
.cheat-feed .cheat-stats .revisions-cheat,
.cheat-feed .cheat-stats .taskExpiry,
.cheat-feed .cheat-stats .taskCategory,
.cheat-feed .cheat-stats .vault-meta {
  float: none;
  margin: 0;
  color: inherit;
}

.cheat-feed .min-max-cheat {
  float: none;
  margin: 0;
  margin-left: 4px;
}

.cheat-feed .cheat-owner {
  float: none;
  clear: none;
  margin: 0 0 8px;
  font-size: 11px;
  color: var(--color-white-l);
}

.cheat-feed .cheat-body-container {
  clear: none;
  padding-top: 0;
}

/* New/empty cheat: type field keeps the badge shape while editable. */
.cheat-feed .cheat-type[contenteditable=true] {
  min-width: 3em;
  outline: none;
}

/* Collapsed browse preview: clip the snippet — no inner scrollbar (concept B). */
.cheat-feed .cheat:not(.large):not(.revise):not(.max) .cheat-body .cm-editor {
  max-height: 4.5em;
  min-height: 0;
}

.cheat-feed .cheat:not(.large):not(.revise):not(.max) .cheat-body .cm-scroller {
  overflow: hidden !important;
}

.cheat-feed .cheat.large .cheat-body .cm-editor,
.cheat-feed .cheat.revise .cheat-body .cm-editor {
  max-height: min(60vh, 480px);
}

/* Feed actions sit in the head stats row; still only visible once the card is expanded. */
.cheat-feed .vault-cheat-actions,
.cheat-feed .task-actions,
.cheat-feed .dues-actions {
  float: none;
  margin: 0;
  display: none;
}

.cheat-feed .cheat.large .vault-cheat-actions,
.cheat-feed .cheat.large .task-actions,
.cheat-feed .cheat.large .dues-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cheat-feed .vault-cheat-actions a,
.cheat-feed .task-actions a,
.cheat-feed .dues-actions a,
.cheat-feed .penny-actions a,
.cheat-feed .hours-actions a {
  margin-left: 0;
}

.cheat-feed .penny-actions, .cheat-feed .dues-actions,
.cheat-feed .hours-actions {
  float: none;
  margin: 0;
  display: none;
}

.cheat-feed .cheat.large .penny-actions, .cheat-feed .cheat.large .dues-actions,
.cheat-feed .cheat.large .hours-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cheats-toolbar .project-tabs.filter-seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0;
}

.cheats-toolbar .project-tabs.filter-seg .project-tab {
  margin: 0;
  padding: 5px 10px;
  border-radius: 0;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--color-dark-b);
  text-transform: none;
  color: var(--color-white-l);
  cursor: pointer;
}

.cheats-toolbar .project-tabs.filter-seg .project-tab:first-child {
  border-left: 0;
}

.cheats-toolbar .project-tabs.filter-seg .project-tab:hover {
  background-color: var(--color-dark-l);
}

.cheats-toolbar .project-tabs.filter-seg .project-tab.active {
  background-color: var(--color-dark-l);
  color: var(--color-green);
}

/* Status badge in the feed head keeps paid/unpaid/overdue colours (not the green type badge). */
.cheat-feed .duesStatus.cheat-type {
  background-color: transparent;
  border-color: color-mix(in srgb, currentColor 35%, transparent);
}

.cheat-feed .duesStatus.duesPaid {
  color: var(--color-green-h);
  background-color: color-mix(in srgb, var(--color-green) 12%, transparent);
  border-color: color-mix(in srgb, var(--color-green) 35%, transparent);
}

.cheat-feed .duesStatus.duesUnpaid {
  color: var(--color-gold-h);
  background-color: color-mix(in srgb, var(--color-gold) 12%, transparent);
  border-color: color-mix(in srgb, var(--color-gold) 35%, transparent);
}

.cheat-feed .duesStatus.duesOverdue {
  color: var(--color-red-h);
  background-color: color-mix(in srgb, var(--color-red) 12%, transparent);
  border-color: color-mix(in srgb, var(--color-red) 35%, transparent);
}

/* View tabs sitting in a workbench toolbar use the filter-seg shell. */
.cheats-toolbar .dues-tabs.filter-seg .dues-tab,
.cheats-toolbar .pennies-tabs.filter-seg .pennies-tab,
.cheats-toolbar .pennies-tabs.filter-seg .dues-tab,
.cheats-toolbar .filter-seg.dues-tabs .pennies-tab,
.cheats-toolbar .pennies-tabs.filter-seg .hours-tab,
.cheats-toolbar .filter-seg.dues-tabs .hours-tab,
.cheats-toolbar .filter-seg.hours-tabs .pennies-tab,
.cheats-toolbar .filter-seg.hours-tabs .dues-tab,
.cheats-toolbar .pennies-tabs.filter-seg .project-tab,
.cheats-toolbar .filter-seg.dues-tabs .project-tab,
.cheats-toolbar .filter-seg.hours-tabs .project-tab,
.cheats-toolbar .pennies-tabs.filter-seg .penny-filter-pill,
.cheats-toolbar .pennies-tabs.filter-seg .dues-filter-pill,
.cheats-toolbar .filter-seg.dues-tabs .penny-filter-pill,
.cheats-toolbar .filter-seg.dues-tabs .dues-filter-pill,
.cheats-toolbar .pennies-tabs.filter-seg .hours-filter-pill,
.cheats-toolbar .filter-seg.dues-tabs .hours-filter-pill,
.cheats-toolbar .filter-seg.hours-tabs .penny-filter-pill,
.cheats-toolbar .filter-seg.hours-tabs .dues-filter-pill,
.cheats-toolbar .filter-seg.hours-tabs .hours-filter-pill,
.cheats-toolbar .hours-tabs.filter-seg .hours-tab {
  margin: 0;
  padding: 5px 10px;
  border-radius: 0;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--color-dark-b);
  text-transform: none;
  color: var(--color-white-l);
  cursor: pointer;
}

.cheats-toolbar .dues-tabs.filter-seg .dues-tab:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .pennies-tab:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .dues-tab:first-child,
.cheats-toolbar .filter-seg.dues-tabs .pennies-tab:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .hours-tab:first-child,
.cheats-toolbar .filter-seg.dues-tabs .hours-tab:first-child,
.cheats-toolbar .filter-seg.hours-tabs .pennies-tab:first-child,
.cheats-toolbar .filter-seg.hours-tabs .dues-tab:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .project-tab:first-child,
.cheats-toolbar .filter-seg.dues-tabs .project-tab:first-child,
.cheats-toolbar .filter-seg.hours-tabs .project-tab:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .penny-filter-pill:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .dues-filter-pill:first-child,
.cheats-toolbar .filter-seg.dues-tabs .penny-filter-pill:first-child,
.cheats-toolbar .filter-seg.dues-tabs .dues-filter-pill:first-child,
.cheats-toolbar .pennies-tabs.filter-seg .hours-filter-pill:first-child,
.cheats-toolbar .filter-seg.dues-tabs .hours-filter-pill:first-child,
.cheats-toolbar .filter-seg.hours-tabs .penny-filter-pill:first-child,
.cheats-toolbar .filter-seg.hours-tabs .dues-filter-pill:first-child,
.cheats-toolbar .filter-seg.hours-tabs .hours-filter-pill:first-child,
.cheats-toolbar .hours-tabs.filter-seg .hours-tab:first-child {
  border-left: 0;
}

.cheats-toolbar .dues-tabs.filter-seg .dues-tab:hover,
.cheats-toolbar .pennies-tabs.filter-seg .pennies-tab:hover,
.cheats-toolbar .pennies-tabs.filter-seg .dues-tab:hover,
.cheats-toolbar .filter-seg.dues-tabs .pennies-tab:hover,
.cheats-toolbar .pennies-tabs.filter-seg .hours-tab:hover,
.cheats-toolbar .filter-seg.dues-tabs .hours-tab:hover,
.cheats-toolbar .filter-seg.hours-tabs .pennies-tab:hover,
.cheats-toolbar .filter-seg.hours-tabs .dues-tab:hover,
.cheats-toolbar .pennies-tabs.filter-seg .project-tab:hover,
.cheats-toolbar .filter-seg.dues-tabs .project-tab:hover,
.cheats-toolbar .filter-seg.hours-tabs .project-tab:hover,
.cheats-toolbar .pennies-tabs.filter-seg .penny-filter-pill:hover,
.cheats-toolbar .pennies-tabs.filter-seg .dues-filter-pill:hover,
.cheats-toolbar .filter-seg.dues-tabs .penny-filter-pill:hover,
.cheats-toolbar .filter-seg.dues-tabs .dues-filter-pill:hover,
.cheats-toolbar .pennies-tabs.filter-seg .hours-filter-pill:hover,
.cheats-toolbar .filter-seg.dues-tabs .hours-filter-pill:hover,
.cheats-toolbar .filter-seg.hours-tabs .penny-filter-pill:hover,
.cheats-toolbar .filter-seg.hours-tabs .dues-filter-pill:hover,
.cheats-toolbar .filter-seg.hours-tabs .hours-filter-pill:hover,
.cheats-toolbar .hours-tabs.filter-seg .hours-tab:hover {
  background-color: var(--color-dark-l);
}

.cheats-toolbar .dues-tabs.filter-seg .dues-tab.active,
.cheats-toolbar .pennies-tabs.filter-seg .pennies-tab.active,
.cheats-toolbar .pennies-tabs.filter-seg .active.dues-tab,
.cheats-toolbar .filter-seg.dues-tabs .pennies-tab.active,
.cheats-toolbar .pennies-tabs.filter-seg .active.hours-tab,
.cheats-toolbar .filter-seg.dues-tabs .active.hours-tab,
.cheats-toolbar .filter-seg.hours-tabs .pennies-tab.active,
.cheats-toolbar .filter-seg.hours-tabs .active.dues-tab,
.cheats-toolbar .pennies-tabs.filter-seg .active.project-tab,
.cheats-toolbar .filter-seg.dues-tabs .active.project-tab,
.cheats-toolbar .filter-seg.hours-tabs .active.project-tab,
.cheats-toolbar .pennies-tabs.filter-seg .active.penny-filter-pill,
.cheats-toolbar .pennies-tabs.filter-seg .active.dues-filter-pill,
.cheats-toolbar .filter-seg.dues-tabs .active.penny-filter-pill,
.cheats-toolbar .filter-seg.dues-tabs .active.dues-filter-pill,
.cheats-toolbar .pennies-tabs.filter-seg .active.hours-filter-pill,
.cheats-toolbar .filter-seg.dues-tabs .active.hours-filter-pill,
.cheats-toolbar .filter-seg.hours-tabs .active.penny-filter-pill,
.cheats-toolbar .filter-seg.hours-tabs .active.dues-filter-pill,
.cheats-toolbar .filter-seg.hours-tabs .active.hours-filter-pill,
.cheats-toolbar .hours-tabs.filter-seg .hours-tab.active {
  background-color: var(--color-dark-l);
  color: var(--color-green);
}

/* Legal / API docs pages still use the old wordmark; workbench pages use .main-crumb. */
.header-title {
  cursor: pointer;
}

.header-title:hover {
  color: var(--color-white-l);
}

#TitleArea .search_bar {
  float: none;
}

/* No padding-left: #FilterButtonsArea sits below the title, and its "Filter:" label belongs on
   the same left rail as the title, the "Tags:" label and the cheat cards. #SortArea is unaffected
   either way, since #FilterArea is justify-content: space-between and pushes it to the right edge
   regardless. */
#SortArea,
#FilterButtonsArea,
#UserArea {
  display: flex;
  align-items: center; /* vertically aligns text and buttons */
  flex-wrap: wrap; /* allow wrapping if it gets too long */
  gap: 4px;
}

/* #UserLoginInfo holds the account pill when signed in, #signInOutButton the Sign in pill when
   not, so one of the two is always empty. An empty flex item is still an item, and would leave a
   gap hanging beside the other. */
#UserArea > div:empty {
  display: none;
}

#SortButtons,
#UserLoginInfo {
  display: flex;
  align-items: center; /* vertically aligns text and buttons */
  flex-wrap: wrap; /* allow wrapping if it gets too long */
  gap: 5px;
}

.userButton a {
  cursor: pointer;
}

.userButton:last-child {
  margin-right: 0;
}

/* Pill-button rows: account / Sign in (#UserArea) and in-page filters (#FilterButtons —
   All/Yours/Starred/Liked, plus filter rows on Hours/Pennies/Dues). Scoped to .pill-group
   (rather than restyling .userButton itself) since that class is reused everywhere else as a
   plain text-link wrapper — forms, the footer, Vault's "Purge Vault", OAuth Allow/Deny.
   Default is a quiet ghost chip; the account / Sign-in pills stay filled below. */
.pill-group {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

.pill-group .userButton {
  padding: 5px 10px;
  border-radius: 4px;
  background-color: transparent;
  border: 1px solid color-mix(in srgb, var(--color-white) 12%, var(--color-dark-b));
  text-transform: none;
}

.pill-group .userButton a {
  color: var(--color-white);
}

.pill-group .userButton:hover {
  background-color: color-mix(in srgb, var(--color-dark-h) 55%, transparent);
  border-color: color-mix(in srgb, var(--color-white) 20%, var(--color-dark-b));
}

.pill-group .userButton a:hover {
  color: var(--color-white-h);
}

.pill-group .userButton.active {
  background-color: color-mix(in srgb, var(--color-green) 12%, var(--color-dark-h));
  border-color: color-mix(in srgb, var(--color-green) 40%, var(--color-dark-b));
}

.pill-group .userButton.active a {
  color: var(--color-green);
}

/* Filled pills on the dark header band (account / Sign in), so they still read against dark-m. */
#TitleArea .pill-group .userButton {
  background-color: var(--color-dark-h);
  border-color: transparent;
}

#TitleArea .pill-group .userButton:hover {
  background-color: var(--color-dark);
  border-color: transparent;
}

/* The account pill keeps the name as typed rather than shouting it in capitals. */
.accountToggle {
  text-transform: none;
}

/* The full name on a wide screen, initials on a phone (swapped in the max-width: 600px block). */
.accountInitials {
  display: none;
}

/* Account dropdown (updateUserText in public/js/auth.js). Fixed and placed by placeMenu, which
   keeps it inside the screen and opens it upward when the toggle is at the bottom of the rail. */
.headerMenu {
  position: fixed;
  z-index: 500;
  overflow-y: auto;
  padding: 8px;
  box-sizing: border-box;
  max-width: calc(100vw - 32px);
  /* Darker than the band and the page it opens over. No shadow: a hairline a shade lighter than
     either is just enough to keep its edge from getting lost against the content below. */
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-b);
  border-radius: 6px;
  text-transform: none;
}

.headerMenu[hidden] {
  display: none;
}

/* `a.` and the order in the file are what let these beat `.pill-group .userButton a` above, since
   both menus sit inside a pill. The text-transform also opts out of the global
   `a { text-transform: capitalize }`, which would turn every label into Title Case. */
.headerMenu a.headerMenuItem {
  display: block;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--color-white);
  text-align: left;
  text-transform: none;
}

.headerMenu a.headerMenuItem:hover,
.headerMenu a.headerMenuItem:focus-visible {
  /* Hover goes darker, never lighter: an item lifts by sinking a shade below the menu. */
  background-color: var(--color-dark-h);
  color: var(--color-white-h);
  outline: none;
}

.headerMenu a.headerMenuItem.active {
  color: var(--color-green);
}

.headerMenuDivider {
  border-top: 1px solid var(--color-dark-l);
  margin: 4px 0;
}

.accountMenuWrap.open .accountToggle {
  color: var(--color-white-h);
}

.accountMenu {
  width: 260px;
}

.accountEmail {
  padding: 6px 10px 8px;
  font-size: 11px;
  color: var(--color-white-l);
  overflow-wrap: anywhere;
}

/* Billing carries the plan badge on its right. */
.accountMenu a.headerMenuItem {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* The one red item, and set apart below a divider, so the rarely wanted action is the easy one to
   find without being the loudest thing in the header the way the old red Sign Out was. */
.headerMenu a#signOut,
.headerMenu a#signOut:hover {
  color: var(--color-red);
}

.apiKeyRevealBox {
  background: var(--color-dark-l);
  border-radius: 8px;
  padding: 10px;
  margin: 10px 0;
}
.apiKeyRevealBox code {
  font-family: "Consolas", "Fira Code", monospace;
  word-break: break-all;
  color: var(--color-green-h);
}

/* Text fields only: the API-key form also holds checkboxes, and the fitting look (pale fill,
   inset shadow, 10px radius) would fight the themed square they get at the top of this file. */
#apiKeyCreateForm input:not([type=checkbox]),
#addPasswordForm input,
#linkRequestFormArea input {
  margin-right: 10px;
  margin-bottom: 10px;
}

/* The same form's tick lists (the write-scope toggle and the per-section ticks), plus the two
   other places a key's sections are picked: editing an existing key on /user, and the OAuth
   consent screen. Inline-flex labels keep a box from wrapping away from the word it belongs to,
   which plain inline labels separated by a space are free to do. */
#apiKeyCreateForm label,
.apiKeySectionsEditor label,
#oauthSectionsArea label {
  display: inline-flex;
  align-items: center;
  margin: 0 12px 10px 0;
  cursor: pointer;
}

/* Opens under its key's row, so it is indented to read as belonging to that row rather than as
   the next key in the list. */
.apiKeySectionsEditor {
  margin: 0 0 10px 12px;
}

/* Every other bare text input across the account-facing pages (/user, /billing, /admin) —
   previously unstyled, unlike the search bar, Vault, and editLink-form inputs above.
   #profileCountry is a <select>, not a text input — it's styled in authDesktop.scss instead,
   alongside #profileGateCountry, since #userProfile select there already covers it with more
   specific (and select-appropriate) rules. */
#profileFullName,
#profileEmail,
#securityAddPhoneNumber,
#securityAddPhoneCode,
#upgradeCodeInput,
#adminEmailInput {
  margin-bottom: 10px;
}

#mergeConfirmInput {
  margin-bottom: 10px;
}

/* Explainer under a Profile field that needs one (currently the base-currency picker) — same
   muted, italic aside treatment as .pennyProjectedDisclaimer and friends over on Pennies. */
.profileFieldHint {
  font-size: 0.8em;
  font-style: italic;
  color: var(--color-white-l);
  margin: 0 0 10px;
}

/* The Theme picker on /user. Each option carries its own data-theme attribute, which re-scopes
   every --color-* variable inside it (see theme-properties in _variables.scss), so a card is drawn
   in the palette it offers whatever theme the page itself is in, with no colours passed from JS.
   It reuses the %dark-card-row surface the other /user rows sit on, and the green ticked-state
   border the checkboxes use for the one that is active. */
/* The "Seasonal themes" group under the picker: the same cards as the ordinary themes, dimmed and
   unclickable while their dates are not open. */
.themeGroupHeading {
  margin-top: 24px;
}

.themeOption.locked {
  opacity: 0.5;
  cursor: not-allowed;
}
.themeOption.locked:hover {
  border-color: var(--color-dark-h);
}

.themeOptionDates {
  font-size: 0.8em;
  color: var(--color-white-l);
}

/* Seasonal decoration (functions/themes.js names each theme's effect, public/js/theme.js sets
   html[data-effect] from the theme in use). Most seasons are quiet speck fields; Halloween gets
   its own atmosphere (fog, bats, candle flicker) so it feels like a scene rather than confetti.
   Never takes a click, draws only in the theme's own colours, and is switched off for anyone who
   asks their system for reduced motion. */
html[data-effect]::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  opacity: 0.7;
  background-size: 340px 520px, 410px 520px, 500px 520px, 270px 520px, 620px 520px;
  background-position: 40px 60px, 190px 280px, 330px 140px, 120px 430px, 450px 360px;
}

/* Valentine's: soft petals rising. */
html[data-effect=petals]::after {
  background-image: radial-gradient(ellipse 4px 3px, var(--color-red-h) 0 100%, transparent 100%), radial-gradient(ellipse 3px 2px, color-mix(in srgb, var(--color-gold-h) 80%, transparent) 0 100%, transparent 100%), radial-gradient(ellipse 4px 3px, color-mix(in srgb, var(--color-red-h) 70%, transparent) 0 100%, transparent 100%), radial-gradient(ellipse 3px 2px, var(--color-gold-h) 0 100%, transparent 100%), radial-gradient(ellipse 4px 3px, color-mix(in srgb, var(--color-white-h) 60%, transparent) 0 100%, transparent 100%);
  animation: speck-rise 44s linear infinite;
}

/* Snow: flakes falling. */
html[data-effect=snow]::after {
  background-image: radial-gradient(circle, var(--color-white-h) 0 2px, transparent 3px), radial-gradient(circle, color-mix(in srgb, var(--color-white-h) 70%, transparent) 0 1.5px, transparent 2.5px), radial-gradient(circle, var(--color-white-h) 0 1.5px, transparent 2.5px), radial-gradient(circle, color-mix(in srgb, var(--color-white-h) 60%, transparent) 0 1.5px, transparent 2.5px), radial-gradient(circle, color-mix(in srgb, var(--color-blue-h) 60%, transparent) 0 1.5px, transparent 2.5px);
  animation: speck-fall 52s linear infinite;
}

/* Sparkle: specks that stay put and slowly twinkle. */
html[data-effect=sparkle]::after {
  background-image: radial-gradient(circle, var(--color-gold-h) 0 1.5px, transparent 3px), radial-gradient(circle, color-mix(in srgb, var(--color-white-h) 80%, transparent) 0 1px, transparent 2.5px), radial-gradient(circle, color-mix(in srgb, var(--color-gold-h) 70%, transparent) 0 1px, transparent 2.5px), radial-gradient(circle, var(--color-green-h) 0 1.5px, transparent 3px), radial-gradient(circle, color-mix(in srgb, var(--color-white-h) 60%, transparent) 0 1px, transparent 2.5px);
  animation: speck-twinkle 4.5s ease-in-out infinite alternate;
}

/* Halloween atmosphere: breathing fog (no moon spotlight — it read as a strange glow on the
   feed). The bats and spiders are real DOM nodes from public/js/seasonEffects.js, not
   background-image decoys. */
html[data-effect=haunt]::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: radial-gradient(ellipse 100% 48% at 50% 112%, color-mix(in srgb, var(--color-blue) 55%, transparent), transparent 74%), radial-gradient(ellipse 75% 34% at 12% 100%, color-mix(in srgb, var(--color-gold) 22%, transparent), transparent 72%), radial-gradient(ellipse 60% 32% at 88% 100%, color-mix(in srgb, var(--color-blue-h) 20%, transparent), transparent 70%), radial-gradient(ellipse 90% 60% at 50% -12%, color-mix(in srgb, var(--color-dark-h) 70%, transparent), transparent 72%);
  opacity: 0.9;
  animation: haunt-fog 16s ease-in-out infinite alternate;
}

html[data-effect=haunt]::after {
  display: none;
}

/* Fixed overlay for flying bats. Never steals clicks. z-index stays under the side rail (40)
   so a bat can never sit on the logo / LIBRARY like a "big bat". */
.haunt-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  overflow: hidden;
}

/* Spiders live on the account pill in the side rail, so they need a layer above it (rail is 40).
   Still under the mobile drawer (450) and never takes clicks. */
.haunt-layer--spiders {
  z-index: 45;
}

.haunt-bat,
.haunt-spider {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}

/* Hard cap so a missed inline size can never paint a full-bleed "big bat". */
.haunt-bat {
  max-width: 40px;
  overflow: visible;
}

.haunt-bat-svg,
.haunt-spider-svg,
.haunt-cobweb-svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Pure black silhouettes — intentional literals, not brand colours. A faint light rim keeps
   them readable against the dark fog instead of vanishing. */
.haunt-bat-svg path,
.haunt-spider-svg ellipse,
.haunt-spider-svg circle {
  fill: #000;
}

.haunt-bat-svg,
.haunt-spider-svg {
  filter: drop-shadow(0 0 2px color-mix(in srgb, var(--color-white-l) 35%, transparent));
}

.haunt-spider-svg path {
  fill: none;
  stroke: #000;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Silk thread for descending spiders — length/angle set from JS. */
.haunt-silk {
  position: absolute;
  top: 0;
  left: 0;
  height: 1px;
  width: 0;
  transform-origin: 0 50%;
  background: color-mix(in srgb, var(--color-white-l) 55%, transparent);
  pointer-events: none;
}

/* Gait: every leg swings around where it meets the body, from --haunt-gait (-1..1).
   Opposite legs (and neighbours on one side) move in antiphase, like a real tripod gait. */
.haunt-spider-leg {
  transform-box: view-box;
}

.haunt-spider-leg-l1 {
  transform-origin: 17px 14px;
  transform: rotate(calc(var(--haunt-gait, 0) * 16deg));
}

.haunt-spider-leg-l2 {
  transform-origin: 16.5px 16.5px;
  transform: rotate(calc(var(--haunt-gait, 0) * -16deg));
}

.haunt-spider-leg-l3 {
  transform-origin: 16.5px 19px;
  transform: rotate(calc(var(--haunt-gait, 0) * 16deg));
}

.haunt-spider-leg-l4 {
  transform-origin: 17.5px 21px;
  transform: rotate(calc(var(--haunt-gait, 0) * -16deg));
}

.haunt-spider-leg-r1 {
  transform-origin: 23px 14px;
  transform: rotate(calc(var(--haunt-gait, 0) * -16deg));
}

.haunt-spider-leg-r2 {
  transform-origin: 23.5px 16.5px;
  transform: rotate(calc(var(--haunt-gait, 0) * 16deg));
}

.haunt-spider-leg-r3 {
  transform-origin: 23.5px 19px;
  transform: rotate(calc(var(--haunt-gait, 0) * -16deg));
}

.haunt-spider-leg-r4 {
  transform-origin: 22.5px 21px;
  transform: rotate(calc(var(--haunt-gait, 0) * 16deg));
}

/* Wings flap from --haunt-flap (-1..1, positive = downstroke). The arm swings from the
   shoulder while the hand swings the other way from the wrist, so the tip trails the beat. */
.haunt-bat-arm,
.haunt-bat-hand {
  transform-box: view-box;
}

.haunt-bat-arm {
  transform-origin: 45px 24px;
  transform: rotate(calc(var(--haunt-flap, 0) * -26deg));
}

.haunt-bat-hand {
  transform-origin: 25px 11px;
  transform: rotate(calc(var(--haunt-flap, 0) * 20deg));
}

/* Cobwebs fade in while their strands draw on (spokes first, then rings); hover sweeps them
   away. Flipping into the four corners is a plain transform on the wrapper. */
.haunt-cobweb {
  position: absolute;
  width: 66px;
  height: 66px;
  pointer-events: none;
  z-index: 3;
  opacity: 0.7;
  animation: haunt-web-fade 1.2s ease-out both;
}

.haunt-cobweb-tl {
  top: 2px;
  left: 2px;
}

.haunt-cobweb-tr {
  top: 2px;
  right: 2px;
  transform: scaleX(-1);
}

.haunt-cobweb-bl {
  bottom: 2px;
  left: 2px;
  transform: scaleY(-1);
}

.haunt-cobweb-br {
  bottom: 2px;
  right: 2px;
  transform: scale(-1);
}

.haunt-cobweb-svg {
  transform-origin: 0 0;
  animation: haunt-web-sway 7s ease-in-out 2.5s infinite alternate;
}

.haunt-cobweb-svg path {
  fill: none;
  stroke: color-mix(in srgb, var(--color-white-l) 80%, transparent);
  stroke-width: 0.7;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: haunt-web-draw 0.9s ease-out forwards;
  animation-delay: calc(var(--i, 0) * 0.08s);
}

.haunt-cobweb-svg .haunt-web-ring {
  stroke-width: 0.45;
  animation-delay: calc(0.5s + var(--i, 0) * 0.2s);
}

.haunt-cobweb-clean {
  animation: haunt-web-clean 0.7s ease-in forwards !important;
}

html[data-effect] .header-title,
html[data-effect] .main-crumb-section {
  text-shadow: 0 0 10px color-mix(in srgb, var(--color-gold-h) 55%, transparent);
  animation: logo-glow 5s ease-in-out infinite;
}

/* Candle flicker: uneven on purpose so it reads as flame, not a soft pulse. */
html[data-effect=haunt] .header-title,
html[data-effect=haunt] .main-crumb-section {
  animation: haunt-candle 2.8s ease-in-out infinite;
}

@keyframes speck-rise {
  to {
    background-position: 40px -460px, 190px -240px, 330px -380px, 120px -90px, 450px -160px;
  }
}
@keyframes speck-fall {
  to {
    background-position: 40px 580px, 190px 800px, 330px 660px, 120px 950px, 450px 880px;
  }
}
@keyframes speck-twinkle {
  from {
    opacity: 0.25;
  }
  to {
    opacity: 0.8;
  }
}
@keyframes logo-glow {
  0%, 100% {
    text-shadow: 0 0 10px color-mix(in srgb, var(--color-gold-h) 55%, transparent);
  }
  45% {
    text-shadow: 0 0 6px color-mix(in srgb, var(--color-gold-h) 35%, transparent);
  }
  60% {
    text-shadow: 0 0 14px color-mix(in srgb, var(--color-gold-h) 70%, transparent);
  }
}
@keyframes haunt-fog {
  from {
    opacity: 0.72;
    filter: saturate(0.95);
    transform: translate3d(0, 0, 0) scale(1);
  }
  to {
    opacity: 1;
    filter: saturate(1.15);
    transform: translate3d(0, -1.5%, 0) scale(1.03);
  }
}
@keyframes haunt-web-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 0.7;
  }
}
@keyframes haunt-web-draw {
  to {
    stroke-dashoffset: 0;
  }
}
/* A breath of air: the whole web leans a degree or two, hinged on its corner. */
@keyframes haunt-web-sway {
  from {
    transform: rotate(-1.4deg) scale(1);
  }
  to {
    transform: rotate(1.6deg) scale(1.02);
  }
}
@keyframes haunt-web-clean {
  0% {
    opacity: 0.7;
    filter: blur(0);
  }
  100% {
    opacity: 0;
    filter: blur(3px);
  }
}
@keyframes haunt-candle {
  0%, 100% {
    text-shadow: 0 0 8px color-mix(in srgb, var(--color-gold-h) 50%, transparent), 0 0 18px color-mix(in srgb, var(--color-gold) 25%, transparent);
  }
  18% {
    text-shadow: 0 0 5px color-mix(in srgb, var(--color-gold-h) 30%, transparent), 0 0 12px color-mix(in srgb, var(--color-blue-h) 20%, transparent);
  }
  32% {
    text-shadow: 0 0 14px color-mix(in srgb, var(--color-gold-h) 75%, transparent), 0 0 28px color-mix(in srgb, var(--color-gold) 40%, transparent);
  }
  51% {
    text-shadow: 0 0 7px color-mix(in srgb, var(--color-gold-h) 40%, transparent), 0 0 16px color-mix(in srgb, var(--color-red-h) 18%, transparent);
  }
  67% {
    text-shadow: 0 0 16px color-mix(in srgb, var(--color-gold-h) 80%, transparent), 0 0 32px color-mix(in srgb, var(--color-gold) 45%, transparent);
  }
  84% {
    text-shadow: 0 0 6px color-mix(in srgb, var(--color-gold-h) 35%, transparent), 0 0 14px color-mix(in srgb, var(--color-blue) 22%, transparent);
  }
}
@media (prefers-reduced-motion: reduce) {
  html[data-effect]::before,
  html[data-effect]::after,
  html[data-effect] .header-title,
  html[data-effect] .main-crumb-section,
  .haunt-cobweb {
    animation: none;
  }
  .haunt-layer,
  .haunt-cobweb,
  .haunt-silk {
    display: none;
  }
}
.themeOptions {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px;
}

.themeOption {
  flex-direction: column;
  align-items: stretch;
  margin-bottom: 0;
  background-color: var(--color-dark-l);
  border: 2px solid var(--color-dark-h);
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.themeOption:hover {
  border-color: var(--color-white-l);
}
.themeOption.active {
  border-color: var(--color-green);
}

.themeOptionName {
  color: var(--color-white-h);
}

.themeOptionState {
  font-size: 0.8em;
  color: var(--color-green-h);
}

.themeSwatches {
  display: flex;
  gap: 4px;
}

.themeSwatch {
  flex: 1;
  height: 14px;
  border-radius: 4px;
}
.themeSwatch.swatch-dark-b {
  background-color: var(--color-dark-b);
}
.themeSwatch.swatch-dark {
  background-color: var(--color-dark);
}
.themeSwatch.swatch-white {
  background-color: var(--color-white);
}
.themeSwatch.swatch-green {
  background-color: var(--color-green);
}
.themeSwatch.swatch-blue {
  background-color: var(--color-blue);
}
.themeSwatch.swatch-red {
  background-color: var(--color-red);
}
.themeSwatch.swatch-gold {
  background-color: var(--color-gold);
}

#profileFullName.input-error,
#profileEmail.input-error,
#securityAddPhoneNumber.input-error,
#securityAddPhoneCode.input-error,
#mergeConfirmInput.input-error,
#upgradeCodeInput.input-error,
#adminEmailInput.input-error {
  border-color: var(--color-red);
}

.cm-prompt-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-dark-t);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.cm-prompt-dialog {
  background: var(--color-dark-l);
  padding: 1rem;
  border-radius: 8px;
  min-width: 300px;
}

.cm-prompt-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.cm-prompt-field {
  display: block;
  margin-top: 0.5rem;
}

.cm-prompt-field label {
  display: block;
  margin-bottom: 0.25rem;
}

.cm-prompt-field input {
  width: 100%;
  box-sizing: border-box;
}

.indexing-banner {
  position: fixed;
  right: 20px;
  bottom: 20px;
  display: none;
  align-items: center;
  gap: 0.6rem;
  background: var(--color-dark-l);
  color: var(--color-white-h);
  padding: 0.75rem 1rem;
  border-radius: 8px;
  border-left: 4px solid var(--color-blue);
  box-shadow: 0 2px 10px var(--color-dark);
  z-index: 9998;
  max-width: 320px;
}
.indexing-banner.active {
  display: flex;
}
.indexing-banner.ready {
  border-left-color: var(--color-green);
  cursor: pointer;
}
.indexing-banner.ready i {
  color: var(--color-green);
}
.indexing-banner.error {
  border-left-color: var(--color-red);
}
.indexing-banner.error i {
  color: var(--color-red);
}
.indexing-banner.banner-clickable {
  cursor: pointer;
}

/* Free month of Pro (public/js/trialOffer.js): the prompt shown after sign-in, in the same
   bottom-right spot and look as .indexing-banner above, and the banner at the top of /billing. */
.trial-offer-prompt {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 9998;
  max-width: 340px;
  background: var(--color-dark-l);
  color: var(--color-white-h);
  padding: 0.9rem 1rem;
  border-radius: 8px;
  border-left: 4px solid var(--color-gold);
  box-shadow: 0 2px 10px var(--color-dark);
}
.trial-offer-prompt p {
  margin: 0 0 0.5rem;
}
.trial-offer-prompt .trial-offer-title {
  font-weight: 700;
}
.trial-offer-prompt .trial-offer-title i {
  color: var(--color-gold);
  margin-right: 4px;
}
.trial-offer-prompt .trial-offer-text {
  color: var(--color-white);
  font-size: 0.9em;
}

.trial-offer-actions {
  display: flex;
  gap: 8px;
  margin-top: 0.6rem;
}

.trial-offer-start,
.trial-offer-later,
#billingTrialStartBtn {
  cursor: pointer;
  border: 0;
  border-radius: 6px;
  padding: 6px 12px;
  font: inherit;
}
.trial-offer-start:disabled,
.trial-offer-later:disabled,
#billingTrialStartBtn:disabled {
  opacity: 0.6;
  cursor: default;
}

.trial-offer-start,
#billingTrialStartBtn {
  background: var(--color-gold);
  color: var(--color-dark);
  font-weight: 700;
}

.trial-offer-later {
  background: transparent;
  color: var(--color-white-l);
}

.billingTrialBanner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  margin: 0 0 1.25rem;
  padding: 14px 18px;
  border-radius: 8px;
  background: var(--color-dark-l);
  border-left: 4px solid var(--color-gold);
}
.billingTrialBanner .billingTrialBannerText {
  flex: 1 1 320px;
}
.billingTrialBanner #billingTrialError:empty {
  display: none;
}

@media screen and (max-width: 600px) {
  html:not([data-viewport-mode=desktop]) .trial-offer-prompt {
    left: 12px;
    right: 12px;
    bottom: 12px;
    max-width: none;
  }
}
html[data-viewport-mode=mobile] .trial-offer-prompt {
  left: 12px;
  right: 12px;
  bottom: 12px;
  max-width: none;
}

/* Offline banner (public/js/offline.js): the strip across the top of every page while the site
   can't be reached, and briefly once it can again. Deliberately the same look as .cookieBanner
   (the site's one other page-wide notice), just pinned to the top so it's the first thing seen,
   and sticky so it stays in view while the page scrolls. */
.offlineBanner {
  position: sticky;
  top: 0;
  z-index: 9000;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px 24px;
  padding: 12px 24px;
  background-color: var(--color-dark-m);
  border-bottom: 1px solid var(--color-dark-h);
  text-align: left;
}

.offlineBannerText {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--color-white);
  margin: 0;
  max-width: 720px;
}
.offlineBannerText i {
  flex-shrink: 0;
}

.offlineBanner.offline .offlineBannerText i {
  color: var(--color-gold);
}

.offlineBanner.online .offlineBannerText i {
  color: var(--color-green);
}

.offlineBannerActions {
  display: flex;
  align-items: center;
  gap: 12px;
}

@media screen and (max-width: 600px) {
  html:not([data-viewport-mode=desktop]) .offlineBanner {
    padding: 10px 16px;
  }
}
html[data-viewport-mode=mobile] .offlineBanner {
  padding: 10px 16px;
}

/* Offline status chip and its panel of queued changes (public/js/offline.js). Bottom-left, so it
   never sits on top of the bottom-right .indexing-banner notifications above. */
.offline-status {
  position: fixed;
  left: 20px;
  bottom: 20px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--color-dark-l);
  color: var(--color-white-h);
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  border-left: 4px solid var(--color-blue);
  box-shadow: 0 2px 10px var(--color-dark);
  z-index: 9998;
  max-width: calc(100vw - 40px);
  cursor: pointer;
  font-size: 0.9rem;
}
.offline-status i {
  color: var(--color-blue-h);
}
.offline-status.error {
  border-left-color: var(--color-red);
}
.offline-status.error i {
  color: var(--color-red-h);
}

.offline-panel {
  position: fixed;
  left: 20px;
  bottom: 70px;
  width: 360px;
  max-width: calc(100vw - 40px);
  max-height: 60vh;
  overflow-y: auto;
  background: var(--color-dark-l);
  color: var(--color-white);
  padding: 1rem;
  border-radius: 8px;
  box-shadow: 0 2px 10px var(--color-dark);
  z-index: 9999;
}

.offline-panel-title {
  color: var(--color-green);
  font-weight: bold;
  margin-bottom: 0.4rem;
}

.offline-panel-note {
  margin: 0 0 0.8rem;
  font-size: 0.85rem;
  color: var(--color-white-l);
}

.offline-panel-row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--color-dark-b);
}
.offline-panel-row.failed .offline-panel-row-meta {
  color: var(--color-red-h);
}

.offline-panel-row-text {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

.offline-panel-row-meta {
  font-size: 0.8rem;
  color: var(--color-white-l);
}

.offline-panel-row-actions {
  display: flex;
  gap: 0.6rem;
}

.offline-panel-action {
  cursor: pointer;
  color: var(--color-white);
}
.offline-panel-action:hover {
  color: var(--color-green-h);
}

.offline-panel-footer {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-top: 0.8rem;
}

/* A card whose latest change is still waiting in the offline outbox. */
.cheat.offline-pending {
  outline: 2px dashed var(--color-gold);
  outline-offset: -2px;
}

.offline-pending-badge {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  font-size: 0.7rem;
  text-transform: uppercase;
  vertical-align: middle;
  background: var(--color-dark-b);
  color: var(--color-gold);
}

/* search bar */
.search_bar {
  float: right;
  margin-bottom: 15px;
}

.search_text, .pennyRowLabel, .duesRowLabel, .hoursRowLabel {
  color: var(--color-green);
  margin-right: 10px;
  font-weight: bold;
}

.search_form {
  display: inline-block;
}

.cheat-title[contenteditable=true]:empty:before,
.cheat-type[contenteditable=true]:empty:before {
  content: attr(placeholder);
  /* For Firefox */
  cursor: auto;
}

.cheat-title[contenteditable=true],
.cheat-type[contenteditable=true] {
  border: 1px dashed var(--color-white);
  min-width: 10px;
  cursor: auto;
}

.cheat-main {
  box-sizing: border-box;
  padding: 20px;
  overflow: hidden;
  min-height: 400px;
  height: 400px;
  cursor: pointer;
}

/* modules */
.cheat {
  min-width: 250px;
  width: 250px;
  height: 100%;
  margin: 4px;
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-b);
  border-radius: 6px;
  position: relative;
  display: inline-block;
  box-sizing: border-box;
  cursor: pointer;
}

.cheat:hover {
  background-color: var(--color-dark-h);
  border-color: color-mix(in srgb, var(--color-white) 16%, var(--color-dark-b));
}

.large,
.revise {
  width: 510px !important;
  background-color: var(--color-dark-h) !important;
}

.max {
  /*width: 30vw !important;*/
  width: calc(100% - 50px) !important;
  min-width: 200px;
  background-color: var(--color-dark-h) !important;
}

h1 {
  font-size: 18px;
  font-weight: bold;
  text-transform: uppercase;
  color: var(--color-white-h);
}

h2 {
  font-size: 15px;
  font-weight: bold;
  color: var(--color-white-h);
}

h3 {
  font-size: 13px;
  font-weight: bold;
  color: var(--color-white-h);
  margin-bottom: 4px;
}

.var {
  color: var(--color-green);
}

#apiDocsBody code {
  background-color: var(--color-dark-h);
  padding: 1px 5px;
  border-radius: 3px;
}
#apiDocsBody pre {
  background-color: var(--color-dark-h);
  padding: 12px 16px;
  border-radius: 4px;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

#apiDocsToc {
  margin-bottom: 6px;
  color: var(--color-white-l);
}

.apiDocsTocList {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  list-style: none;
  margin: 0 0 20px;
  padding: 12px 16px;
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-h);
  border-radius: 6px;
}

.apiEndpoint {
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-h);
  border-radius: 6px;
  padding: 4px 20px 16px;
  margin-bottom: 20px;
}

.apiMethod {
  display: inline-block;
  font-weight: bold;
  padding: 2px 8px;
  border-radius: 3px;
  margin-right: 8px;
  text-transform: uppercase;
}

.apiMethodGet {
  background-color: var(--color-green);
  color: var(--color-on-accent);
}

.apiMethodPost {
  background-color: var(--color-blue);
  color: var(--color-on-accent);
}

.apiScope {
  display: inline-block;
  color: var(--color-gold);
  font-style: italic;
}

.apiParamTable {
  width: 100%;
  border-collapse: collapse;
  margin: 8px 0 12px;
}
.apiParamTable th, .apiParamTable td {
  text-align: left;
  padding: 4px 8px;
  border-bottom: 1px solid var(--color-dark-h);
  vertical-align: top;
}
.apiParamTable th {
  color: var(--color-white-h);
}

.note {
  color: var(--color-blue);
}

/* Billing page (/billing) — tier cards borrow the same dark rounded-box look as .cheat/
   .apiEndpoint, just sized for a two-column content layout instead of the fixed-size cheat grid
   (not clickable, so no hover/cursor treatment). */
.billingTiers {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin: 16px 0;
}

.billingTierCard {
  flex: 1 1 280px;
  box-sizing: border-box;
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-h);
  border-radius: 10px;
  padding: 20px;
}

.billingTierCard h2 {
  margin-top: 0;
}

.billingTierCard ul {
  margin: 0;
  padding-left: 20px;
}

.billingTierCard li {
  margin-bottom: 6px;
}

/* Highlights whichever tier card matches the signed-in user's actual plan (toggled by
   billing.js) rather than always spotlighting Pro — .billingFreeBadge/.billingProBadge get
   swapped to "Current Plan" to match. */
.billingTierCurrent {
  border-color: var(--color-green);
}

.billingTierPrice {
  color: var(--color-white-l);
  font-weight: normal;
  margin: 4px 0 12px;
}

/* Muted footnote under the tier cards (renewal/VAT disclaimer) — smaller and quieter than
   regular body copy, same intent as .note but without the attention-grabbing blue. */
.billingFinePrint {
  color: var(--color-white-l);
  font-size: 13px;
  margin-top: -8px;
}

/* Shared "info card" treatment for a self-contained block within a page's body: each
   profile/security/API section on /user, the payment/contact details on /billing, an account
   lookup result on /admin, and each section of the /terms-of-service and /privacy-policy prose
   all use the same .pageSection box instead of one-off per-page card classes. .pageSectionList
   is the matching no-bullets list treatment for one that needs a list instead of paragraphs. */
.pageSection {
  margin-bottom: 16px;
  border-radius: 8px;
}
.pageSection:last-child {
  margin-bottom: 0;
}

.pageSection > h2:first-child,
.pageSection > h3:first-child {
  margin-top: 0;
  font-weight: 500;
  text-transform: none;
}

/* The global `a { text-transform: capitalize }` below reads fine on button-like nav links
   ("Terms Of Service", "Support"), but mangles a link whose own text is a literal email
   address ("Cheats@Aarontrotter.Com") — opt those specific links back out. */
.email-link {
  text-transform: none;
}

/* Legal/doc pages (/terms-of-service, /privacy-policy) — full width, each section wrapped in a
   .pageSection card like the rest of the site, instead of bare prose capped at a fixed width. */
.docEffectiveDate {
  display: inline-block;
  background-color: var(--color-dark);
  color: var(--color-white-l);
  padding: 4px 12px;
  border-radius: 10px;
  margin-bottom: 12px;
}

/* Scrollbar
::-webkit-scrollbar{
    color: rgba(255, 255, 255, 0);
}
::-webkit-scrollbar-corner{
    color: rgba(0, 0, 0, 0.7);
}
::-webkit-scrollbar-thumb {
    background-color: rgba(255, 255, 255, 0);
    -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5);
    box-shadow: 0 0 1px rgba(255,255,255,.5);
}*/
/* end Scrollbar */
a {
  color: var(--color-red);
  text-transform: capitalize;
  text-decoration: none;
  cursor: pointer;
}

a:hover {
  color: var(--color-red-h);
}

/* Workbench crumbs sit above the global `a` red/capitalize rule (same specificity otherwise). */
.main-crumb a.main-crumb-root,
.main-crumb .main-crumb-sep {
  color: var(--color-white-l);
  text-transform: none;
}

.main-crumb a.main-crumb-root:hover,
.main-crumb a.main-crumb-root:focus-visible {
  color: var(--color-white);
}

.main-crumb a.main-crumb-section {
  color: var(--color-white-h);
  font-weight: 500;
  text-transform: none;
}

.main-crumb a.main-crumb-section:hover,
.main-crumb a.main-crumb-section:focus-visible {
  color: var(--color-white);
}

.side-brand a.side-crumb-brand,
.side-brand .side-crumb-sep,
a.side-brand-mark {
  color: var(--color-green);
  text-transform: none;
}

.side-brand a.side-crumb-brand:hover,
.side-brand a.side-crumb-brand:focus-visible,
a.side-brand-mark:hover,
a.side-brand-mark:focus-visible {
  color: var(--color-green-h);
}

.clickable, .project-invite-accept,
.project-invite-decline, .project-invite-send, .share-panel-save {
  color: var(--color-red);
}

.clickable:hover, .project-invite-accept:hover,
.project-invite-decline:hover, .project-invite-send:hover, .share-panel-save:hover {
  color: var(--color-red-h);
  cursor: pointer;
}

.cheat-owner {
  float: left;
  color: var(--color-white-l);
  clear: left;
  margin-top: 5px;
}

.delete-cheat,
.share-cheat,
.share-settings {
  float: right;
  margin-left: 5px;
}

.delete-cheat:hover {
  color: var(--color-red) !important;
  cursor: pointer;
}

.share-cheat .fa-check {
  color: var(--color-green);
}

.share-settings-button:hover {
  cursor: pointer;
}

.share-panel {
  clear: both;
  background-color: var(--color-dark-h);
  border-radius: 10px;
  padding: 15px;
  margin: 10px 0;
}

.share-panel-title {
  margin-bottom: 8px;
}

.share-panel-option {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
  cursor: pointer;
}

.share-panel-option input[type=radio] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  margin: 0 8px 0 0;
  background-color: var(--color-dark-l);
  border: 2px solid var(--color-white-l);
  border-radius: 50%;
  cursor: pointer;
  position: relative;
}

.share-panel-option input[type=radio]:hover {
  border-color: var(--color-white);
}

.share-panel-option input[type=radio]:checked {
  border-color: var(--color-red);
}

.share-panel-option input[type=radio]:checked::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--color-red);
}

.share-panel-emails {
  margin: 10px 0;
}

.share-panel-note {
  color: var(--color-white-l);
  margin-bottom: 8px;
}

.share-panel-email-list {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 8px;
}

.share-panel-email-chip {
  background-color: var(--color-dark-l);
  border-radius: 15px;
  padding: 3px 10px;
}

.share-panel-email-remove {
  margin-left: 6px;
  cursor: pointer;
}

.share-panel-email-remove:hover {
  color: var(--color-red);
}

.share-panel-email-input {
  width: 100%;
  border-radius: 5px;
}

.share-panel-feedback {
  margin: 8px 0;
  color: var(--color-white-l);
}

.share-panel-save {
  display: inline-block;
}

.cheat-private-notice {
  padding: 20px;
  color: var(--color-white-l);
}

.min-max-cheat {
  clear: both;
  margin-bottom: 10px;
  overflow: hidden;
}

/* On a cheat card this holds the minimise/maximise buttons, but it's only filled in once the
   cheat is opened (see script.js) — in the browse grid it's an empty, zero-height div whose
   10px bottom margin would otherwise re-introduce the same uneven top gap that zeroing
   .cheat-title's top margin above removes. */
.min-max-cheat:empty {
  margin-bottom: 0;
}

.revisions-close {
  clear: both;
  float: right;
  margin-bottom: 10px;
}

.editLink-form input {
  width: 100%;
  border-radius: 5px;
  margin-bottom: 10px;
}

.editLink-form-btns {
  display: flex;
}

.editLink-save,
.editLink-close {
  margin-right: 5px;
  float: left;
}

.editLink-save .fa-check:hover {
  color: var(--color-green) !important;
  cursor: pointer;
}

.revisions-close .fa-times:hover,
.editLink-close .fa-times:hover {
  cursor: pointer;
}

.editLink {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-color: var(--color-dark);
}

.editLink-main {
  margin: auto;
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  width: 75%;
  min-width: 250px;
}

.editLink-dialog {
  background-color: var(--color-dark);
  padding: 20px;
  border-radius: 10px;
}

.max-cheat,
.min-cheat {
  float: right;
}

.edit-cheat {
  clear: left;
  float: left;
  margin-top: 10px;
}

.add-cheat {
  clear: left;
  float: left;
}

.save-reset-cheat {
  clear: left;
}

.save-cheat,
.reset-cheat,
.preview-cheat {
  float: left;
  margin-top: 10px;
  margin-right: 5px;
}

.max-cheat-button:hover,
.min-cheat-button:hover,
.share-cheat-button:hover,
.edit-cheat-button:hover,
.add-cheat-button:hover,
.save-cheat-button:hover,
.reset-cheat-button:hover,
.preview-cheat-button:hover {
  cursor: pointer;
}

.floating-add-btn {
  position: fixed;
  top: 50%;
  right: 0;
  z-index: 500;
  width: 44px;
  height: 44px;
  line-height: 44px;
  text-align: center;
  background-color: var(--color-dark);
  border-radius: 10px 0 0 10px;
  box-shadow: 0 2px 8px var(--color-dark);
  cursor: pointer;
  transform: translate(100%, -50%);
  transition: transform 0.25s ease, background-color 0.15s ease;
}

.floating-add-btn.visible {
  transform: translate(0, -50%);
}

.floating-add-btn:hover {
  background-color: var(--color-dark-h);
}

.floating-add-btn .fa-plus {
  font-size: 18px;
  color: var(--color-white-h);
}

.floating-add-btn:hover .fa-plus {
  color: var(--color-white-l);
}

@keyframes pop-in-from-side {
  from {
    transform: translateX(60px);
    opacity: 0.4;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}
.pop-in {
  animation: pop-in-from-side 0.4s ease-out;
}

.btnedit-container {
  clear: both;
  padding-left: 20px;
  margin-bottom: 5px;
}

.btnedit-container div {
  margin-right: 5px;
  display: inline;
}

.btnedit-container div:hover {
  cursor: pointer;
}

.btnedit-note .fa-circle {
  color: var(--color-blue);
}

.btnedit-note .fa-circle:hover {
  color: var(--color-blue-h);
}

.btnedit-var .fa-circle {
  color: var(--color-green);
}

.btnedit-var .fa-circle:hover {
  color: var(--color-green-h);
}

.btnedit-clear .fa-circle {
  color: var(--color-white);
}

.btnedit-clear .fa-circle:hover {
  color: var(--color-white-h);
}

/* Selected states with inner shadow */
.btnedit-note.selected .fa-circle,
.btnedit-var.selected .fa-circle,
.btnedit-clear.selected .fa-circle {
  text-shadow: 0 0 5px var(--color-dark-b);
  transform: scale(1.1);
}

.btnedit-link .fa-link {
  color: var(--color-white);
}

.btnedit-link .fa-link:hover {
  color: var(--color-white-h);
}

::-moz-selection {
  background: var(--color-gold-highlight);
}

::selection {
  background: var(--color-gold-highlight);
}

/* The browser's default h1 margin (0.67em, ~12px desktop / ~16px on the larger responsive
   size) sat on top of .cheat-main's own 20px padding, so every card — cheats, Tasks, Brain,
   Vault, Pennies, Projects — had visibly more space above its title than below its body, which
   ends flush against that same 20px. Zeroing the top margin makes the two match; the bottom
   margin stays em-based so the title-to-pills gap keeps scaling with the font size. */
.cheat-title {
  clear: both;
  margin-top: 0;
}

.revisions-title {
  clear: both;
}

.cheat-body-container {
  padding-top: 10px;
  clear: both;
}

.revision-code {
  width: 320px;
  float: left;
}

/* A maximised cheat keeps its full-page .max width behind the revision panel (see viewRevisions
   in database.js) instead of shrinking to .revise's fixed 510px, so the fixed 320px above would
   leave the rest of the page blank. Let the code side fill whatever's left of .revision-list's
   170px + 20px right padding instead. */
.max .revision-code {
  width: calc(100% - 190px);
}

.revision-list {
  height: 100%;
  width: 170px;
  float: right;
  padding: 20px 20px 20px 0px;
}

.revision-item {
  clear: both;
  margin-bottom: 5px;
  overflow-y: hidden;
  color: var(--color-white-l);
}

.revision-item * {
  color: var(--color-white-l);
}

.revision-active * {
  /*border: 1px dashed #AAA;*/
  color: var(--color-white);
}

.revision-item-element {
  float: left;
  margin-right: 5px;
}

.revision-item-title {
  color: var(--color-red);
  cursor: pointer;
}

.revision-item-title:hover {
  color: var(--color-red-h);
}

.revision-item-cheat-star-total-sel .fa-thumbs-up {
  color: var(--color-green);
}

.revision-item-diff .fa-exchange-alt {
  color: var(--color-blue);
  cursor: pointer;
}

.revision-item-diff .fa-exchange-alt:hover {
  color: var(--color-blue-h);
}

/* Marks whichever compare button (see setRevisionDiffButtonState in database.js) is the one
   currently diffed, so its swapped-in fa-undo icon reads as "on" rather than looking identical
   to the rest. */
.revision-item-diff.revision-diff-active .fa-undo {
  color: var(--color-green);
  cursor: pointer;
}

.revision-item-diff.revision-diff-active .fa-undo:hover {
  color: var(--color-green-h);
}

.star-cheat {
  float: left;
  margin-right: 5px;
}

.star-cheat .fa-star {
  color: var(--color-white-l);
}

.cheat-star-total .fa-thumbs-up {
  color: var(--color-white-l);
}

.revision-item-cheat-star-total .fa-thumbs-up {
  color: var(--color-white-l);
}

.cheat-star-total {
  float: left;
  margin-right: 5px;
}

.score-star-cheat,
.score-up-cheat {
  float: left;
  cursor: pointer;
  margin-right: 5px;
}

.score-star-cheat-button,
.score-up-cheat-button {
  height: 100%;
  vertical-align: middle;
}

.starred {
  color: var(--color-gold) !important;
}

.score-star-cheat .fa-star:hover {
  color: var(--color-gold-h) !important;
}

/* Halloween: cheat stars become jack-o’-lanterns.
   A monochrome CSS mask reads as a blob at ~14px; a tiny coloured SVG (orange body,
   green stem, carved face) is what actually looks like a pumpkin. Starred/hover swap
   to the theme’s brighter halloween gold. */
html[data-theme=halloween] .star-cheat .fa-star,
html[data-theme=halloween] .score-star-cheat .fa-star {
  font-size: 1.4em;
  line-height: 1;
  color: transparent !important;
}

html[data-theme=halloween] .star-cheat .fa-star::before,
html[data-theme=halloween] .score-star-cheat .fa-star::before {
  content: "" !important;
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.12em;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%233d8f3d' d='M10.8 2.2Q11.4 1.6 13 2.2L13.6 5.4H10.6Z'/%3E%3Cpath fill='%23c45512' d='M12 5C9.5 4.2 7.2 4.6 5 6.2 2.8 7.8 1.8 10.4 1.8 13.2 1.8 17.8 5.8 21.2 12 21.2 18.2 21.2 22.2 17.8 22.2 13.2 22.2 10.4 21.2 7.8 19 6.2 16.8 4.6 14.5 4.2 12 5Z'/%3E%3Cpath fill='%231a0f14' d='M7 10.2L9.6 13.6H4.4ZM17 10.2L19.6 13.6H14.4ZM6.2 15.8L8.6 17.2 10.2 15.6 12 17.4 13.8 15.6 15.4 17.2 17.8 15.8Q12 21 6.2 15.8Z'/%3E%3C/svg%3E") center/contain no-repeat;
}

html[data-theme=halloween] .star-cheat .fa-star.starred::before,
html[data-theme=halloween] .score-star-cheat .fa-star.starred::before,
html[data-theme=halloween] .score-star-cheat .fa-star:hover::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%233d8f3d' d='M10.8 2.2Q11.4 1.6 13 2.2L13.6 5.4H10.6Z'/%3E%3Cpath fill='%23ff9a3d' d='M12 5C9.5 4.2 7.2 4.6 5 6.2 2.8 7.8 1.8 10.4 1.8 13.2 1.8 17.8 5.8 21.2 12 21.2 18.2 21.2 22.2 17.8 22.2 13.2 22.2 10.4 21.2 7.8 19 6.2 16.8 4.6 14.5 4.2 12 5Z'/%3E%3Cpath fill='%23fff0a8' d='M7 10.2L9.6 13.6H4.4ZM17 10.2L19.6 13.6H14.4ZM6.2 15.8L8.6 17.2 10.2 15.6 12 17.4 13.8 15.6 15.4 17.2 17.8 15.8Q12 21 6.2 15.8Z'/%3E%3C/svg%3E");
}

.revision-notice {
  clear: both;
  float: left;
  width: 100%;
  margin-top: 5px;
  font-size: 12px;
}

.revision-notice-text {
  margin-right: 5px;
}

.revision-notice-stale .revision-notice-text {
  color: var(--color-gold);
}

.revision-notice-liked .revision-notice-text {
  color: var(--color-green);
}

.revision-notice-link {
  text-decoration: underline;
}

.score-up-cheat .fa-thumbs-up:hover {
  color: var(--color-green);
}

.score-down-cheat {
  float: left;
  cursor: pointer;
  margin-right: 5px;
  margin-top: 5px;
}

.score-down-cheat-button {
  height: 100%;
  vertical-align: middle;
  margin-top: 3px;
}

.score-down-cheat .fa-thumbs-down:hover {
  color: var(--color-red);
}

.choseUp {
  color: var(--color-green) !important;
}

.choseDown {
  color: var(--color-red) !important;
}

.choseUp:hover {
  color: var(--color-green-h) !important;
}

.choseDown:hover {
  color: var(--color-red-h) !important;
}

.fa-times:hover {
  color: var(--color-red) !important;
}

.fa-pen:hover,
.fa-copy:hover,
.fa-window-maximize:hover,
.fa-window-minimize:hover,
.fa-share-alt:hover,
.fa-plus:hover {
  color: var(--color-blue) !important;
}

.fa-save:hover {
  color: var(--color-green) !important;
}

.cheat-details, .billingPeriodToggle, .duesArchivedPill, .duesFrozenPill, .duesStatus, .duesCycle,
.duesSchedule, .hoursArchivedPill, .hoursOverride, .projectAuthorInput, .projectType, .projectName,
.projectStatus, .pennyStatus, .pennySide, .taskCategory,
.taskDuration, .cheat-stars, .cheat-point-total, .cheat-type, .revisions-cheat {
  color: var(--color-white-l);
  float: left;
  margin-right: 5px;
  text-transform: uppercase;
}

#ContainerCheatTypes,
#ContainerCheats,
#ContainerCheatsPagination {
  clear: both;
  overflow: visible;
  height: auto;
}

/* Only the containers that need bottom margin. #ContainerCheats layout comes from .cheat-feed
   (column / two-up) — do not set display here or the ID beats .cheat-feed--two's grid. */
#ContainerCheatTypes,
#ContainerCheats {
  margin-bottom: 10px;
}

#ContainerCheatTypes {
  display: flex;
  flex-wrap: wrap;
}

/* The tag row, labelled to match the "Filter:" and "Sort Search:" rows under it — without a
   label the cloud read as a free-floating block rather than as one of the page's controls.
   Baseline alignment puts "Tags:" on the same text line as the first row of pills, which the
   cloud's own align-items: baseline then holds true across the mixed tag-w1..tag-w5 sizes. */
#TagArea {
  display: flex;
  align-items: baseline;
  margin-bottom: 8px;
}

/* Tag cloud: baseline-align so mixed tag-w1..tag-w5 font sizes still sit on
   one text line per row instead of top-aligning like the flat pill list did.
   Left-aligned rather than centred: every other row on this page (title, user
   buttons, filter/sort labels, the cheat cards below) starts at the container's
   left edge, so a centred cloud was the one block that broke the page's left
   rail. Mobile re-centres it in the max-width:900px block, where every row is
   centred instead. */
#ContainerCheatTypes {
  align-items: baseline;
  justify-content: flex-start;
}

/* The cloud takes whatever the label leaves and wraps inside it. min-width: 0 overrides the
   flex item default of min-width: auto, which would otherwise let a row of wide pills push
   the cloud past the edge of the page instead of wrapping. The row's own margin-bottom
   replaces the one #ContainerCheatTypes carries when it isn't inside #TagArea. */
#TagArea #ContainerCheatTypes {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
}

/* No float here: a pill whose only child is floated has no in-flow line box, so
   the flex `align-items: baseline` above had nothing to align to and silently
   fell back to aligning the pills' bottom edges. As an ordinary block the <p>
   gives each pill a real first baseline, which is what makes the mixed
   tag-w1..tag-w5 sizes sit on a shared text line. The explicit margin is the
   browser's own default for <p>, restated so removing the float doesn't change
   the pill's height. */
.type-name {
  text-transform: uppercase;
  color: var(--color-white);
  margin: 0;
}

/* The vertical padding carries the pill's height on its own. It used to come mostly from the
   browser's default 1em margins on the <p> inside, which made a one-line tag pill about 46px
   tall and the cloud far sparser than it needed to be; .type-name zeroes those out now.
   Ghost outline by default so the cloud matches Workbench filter chips; weight tiers still
   carry popularity via size on .type-name. */
.type-cheat {
  padding: 4px 10px;
  background-color: transparent;
  margin: 3px;
  border: 1px dashed color-mix(in srgb, var(--color-white) 14%, var(--color-dark-b));
  border-radius: 4px;
  position: relative;
  display: inline-block;
  box-sizing: border-box;
  cursor: pointer;
}

/* Popularity weight tiers (tag-w1 least, tag-w5 most — see getTagWeightClass
   in database.js, driven by each type's weekCount). Grayscale only — size and
   weight carry the popularity signal, not hue, so the cloud stays inside the
   site's monochrome/white palette instead of borrowing the semantic green/
   red/blue used for actions elsewhere. Sizing/color live on .type-name itself,
   with specificity higher than the mobile `* { font-size: 1.0em }` reset, so
   the cloud effect survives on small screens too. */
.type-cheat.tag-w1 .type-name {
  font-size: 0.8em;
  color: var(--color-white-l);
}

.type-cheat.tag-w2 .type-name {
  font-size: 0.9em;
  color: var(--color-white-l);
}

.type-cheat.tag-w3 .type-name {
  font-size: 1em;
}

.type-cheat.tag-w4 .type-name {
  font-size: 1.15em;
  font-weight: 600;
}

.type-cheat.tag-w5 .type-name {
  font-size: 1.3em;
  font-weight: 700;
  color: var(--color-white-h);
}

/* Types the viewer has personally worked on (created/edited a cheat of, public or private) in
   the last week — driven by the server-computed isRecentOwn flag (see /getAllTypes in
   routes/db/types.js), so it applies just as much to an already-popular public tag as to a
   still-private draft. Gold pill background with a dark label: the gold is light enough that
   white text on it sits near 1.7:1, so the label takes $color-dark instead and reads at about
   10:1. Same specificity as the tag-wN rules above, so it has to come after them to win the
   color tie-break; size/weight still come from whichever tier the type also matched. */
.type-cheat.tag-recent {
  background-color: var(--color-gold);
  border-style: solid;
  border-color: var(--color-gold);
}

.type-cheat.tag-recent:hover {
  background-color: var(--color-gold-h);
  border-color: var(--color-gold-h);
}

.type-cheat.tag-recent .type-name {
  color: var(--color-dark);
}

.type-cheat.tag-recent:hover .type-name {
  color: var(--color-dark);
}

.type-cheat:hover {
  background-color: color-mix(in srgb, var(--color-dark-h) 70%, transparent);
  border-style: solid;
  border-color: color-mix(in srgb, var(--color-white) 22%, var(--color-dark-b));
}

.type-cheat:hover .type-name {
  color: var(--color-white-h);
}

.chosenType {
  background-color: color-mix(in srgb, var(--color-green) 12%, var(--color-dark-h)) !important;
  border-style: solid !important;
  border-color: color-mix(in srgb, var(--color-green) 45%, var(--color-dark-b)) !important;
  color: var(--color-white) !important;
}

.chosenType .type-name {
  color: var(--color-green) !important;
}

/* Active tag filter chip, sat at the end of the Filter row. The cloud alone can't be relied on
   to show that a tag filter is applied: it shows a single page of the most popular types, and
   clicking a cheat card's type filters by a tag that may not be on that page at all, so no pill
   lights up. The chip is rendered by renderActiveTagFilter in script.js and styled to echo the
   tag pill it stands in for, with an explicit × since the pill that would otherwise clear the
   filter may not be on screen. */
#ActiveTagFilter {
  display: flex;
  align-items: center;
}

/* Collapsed when there's no filter, so it doesn't leave #FilterButtonsArea's 5px gap dangling
   off the end of the pill row. */
#ActiveTagFilter:empty {
  display: none;
}

.active-filter-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  border-radius: 4px;
  background-color: color-mix(in srgb, var(--color-green) 12%, var(--color-dark-h));
  border: 1px solid color-mix(in srgb, var(--color-green) 40%, var(--color-dark-b));
  color: var(--color-white);
  text-transform: uppercase;
  cursor: pointer;
}

.active-filter-chip:hover {
  background-color: var(--color-dark-h);
  color: var(--color-white-h);
}

/* Skeleton loaders — shown in #ContainerCheats/#tasksList/#vaultCheatsList,
   #ContainerCheatTypes, #FilterButtons and #SortSelectSkeleton while data is still loading
   (see showSkeletonCards / showSkeletonTags / showSkeletonFilter / showSkeletonSort in
   commonScripts.js). Reuses .cheat/.type-cheat/.filter-seg/.sort-select so a skeleton is the
   same size as the content that replaces it, and .skeleton-bar is a shimmering block sized
   per-instance via an inline width. */
@keyframes skeleton-shimmer {
  0% {
    background-position: -300px 0;
  }
  100% {
    background-position: 300px 0;
  }
}
.skeleton-bar {
  height: 12px;
  border-radius: 4px;
  margin-bottom: 10px;
  background: linear-gradient(90deg, var(--color-dark-h) 25%, var(--color-dark-b) 37%, var(--color-dark-h) 63%);
  background-size: 600px 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
.skeleton-bar:last-child {
  margin-bottom: 0;
}

.skeleton-bar-title {
  height: 18px;
  margin-bottom: 18px;
}

.cheat.skeleton {
  cursor: default;
}
.cheat.skeleton:hover {
  background-color: var(--color-dark);
  border-color: var(--color-dark-b);
}

/* Feed-shaped cheat mocks: type + title + stats row, then a short body block. */
.cheat-feed .cheat.skeleton .cheat-head {
  margin-bottom: 10px;
}
.cheat-feed .cheat.skeleton .skeleton-bar-type {
  flex: 0 0 auto;
  width: 52px;
  height: 16px;
  margin-bottom: 0;
  border-radius: 3px;
}
.cheat-feed .cheat.skeleton .skeleton-bar-title {
  flex: 1 1 auto;
  min-width: 0;
  height: 14px;
  margin-bottom: 0;
}
.cheat-feed .cheat.skeleton .skeleton-bar-stats {
  width: 72px;
  height: 12px;
  margin-bottom: 0;
}
.cheat-feed .cheat.skeleton .skeleton-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 0;
}
.cheat-feed .cheat.skeleton .skeleton-body .skeleton-bar {
  margin-bottom: 0;
  height: 10px;
}

/* Summary / Totals loading: tally strip + table rows (not cheat cards). */
.skeleton-summary-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.skeleton-tally {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 30px;
  padding: 12px 15px;
}

.skeleton-tally-figure {
  min-width: 120px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.skeleton-tally-figure .skeleton-bar {
  margin-bottom: 0;
  height: 10px;
}
.skeleton-tally-figure .skeleton-bar:nth-child(2) {
  height: 16px;
}

.skeleton-table {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 15px;
}

.skeleton-table-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  align-items: center;
}
.skeleton-table-row .skeleton-bar {
  margin-bottom: 0;
  height: 11px;
  flex: 1 1 80px;
  max-width: 180px;
}

/* Export / template / letter loading: one form-shaped panel. */
.skeleton-form-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 15px;
  max-width: 720px;
}
.skeleton-form-panel > .skeleton-bar {
  margin-bottom: 0;
}

.skeleton-form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.skeleton-form-field .skeleton-bar {
  margin-bottom: 0;
  height: 10px;
}
.skeleton-form-field .skeleton-form-input {
  height: 28px;
  border-radius: 4px;
}

/* Projects board loading: three columns already in place. */
.project-column-skeleton {
  pointer-events: none;
}
.project-column-skeleton .skeleton-bar-count {
  width: 18px;
  height: 10px;
  margin-bottom: 0;
}
.project-column-skeleton .cheat.skeleton {
  width: 100% !important;
  min-width: 0;
  margin: 0 0 10px 0;
}

/* Filter segment mock chips — same shell as the real All/Yours/Starred/Liked buttons. */
.filter-seg .skeleton-filter-chip {
  display: flex;
  align-items: center;
  padding: 5px 10px;
  border-left: 1px solid var(--color-dark-b);
  pointer-events: none;
}
.filter-seg .skeleton-filter-chip:first-child {
  border-left: 0;
}
.filter-seg .skeleton-filter-chip .skeleton-bar {
  height: 12px;
  margin-bottom: 0;
}

/* Sort mock sits in flow; the real select is display:none while data-awaiting so they don't stack. */
select.sort-select[data-awaiting] {
  display: none;
}

#SortSelectSkeleton.sort-select.skeleton {
  display: block;
  box-sizing: border-box;
  min-width: 110px;
  min-height: 28px;
  padding: 5px 26px 5px 10px;
  pointer-events: none;
  cursor: default;
  background-color: var(--color-dark-h);
  background-image: none;
  border: 1px solid color-mix(in srgb, var(--color-gold) 35%, var(--color-dark-b));
  border-radius: 4px;
}
#SortSelectSkeleton.sort-select.skeleton::after {
  content: "";
  display: block;
  width: 58px;
  height: 12px;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--color-dark) 25%, var(--color-dark-b) 37%, var(--color-dark) 63%);
  background-size: 600px 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}

/* A control that waits for its data before showing (see revealAwaiting in commonScripts.js).
   visibility rather than display, so it keeps its space and the skeleton cards below sit exactly
   where the real cards will, with nothing jumping when it appears. Hidden elements can't be
   clicked or focused either, so there's no acting on a filter before there is anything to filter. */
[data-awaiting] {
  visibility: hidden;
}

.type-cheat.skeleton {
  cursor: default;
  pointer-events: none;
  background-color: var(--color-dark);
  border-style: solid;
  border-color: transparent;
}
.type-cheat.skeleton:hover {
  background-color: var(--color-dark);
  border-style: solid;
  border-color: transparent;
}
.type-cheat.skeleton {
  /* Sized so a skeleton pill matches the height of the real tag-w3 pill that replaces it
     (padding + bar ≈ a tag-w3 line), so the cloud doesn't jump when the fetch lands. */
}
.type-cheat.skeleton .skeleton-bar {
  height: 13px;
  margin: 3px 0;
}

.pagination {
  clear: both;
  margin-bottom: 10px;
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.page-link {
  cursor: pointer;
  min-width: 30px;
  height: 30px;
  padding: 0 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-dark);
  border: none;
  border-radius: 15px;
  color: var(--color-white);
  box-sizing: border-box;
  transition: background-color 0.2s ease, color 0.2s ease, transform 0.1s ease;
}

.page-link:hover {
  background-color: var(--color-dark-h);
  color: var(--color-white-h);
}

.current-page {
  background-color: var(--color-white-h);
  color: var(--color-dark-h);
  font-weight: 600;
}

.page-link:active {
  transform: translateY(1px);
}

.page-link.disabled,
.page-link.disabled-page {
  cursor: default;
  pointer-events: none;
  opacity: 0.4;
  background-color: transparent;
}

.cheat-body {
  height: auto !important;
}

.cm-editor {
  cursor: auto;
}

/* Task 'list' category checkbox gutter (src/CodeMirrorEditor.js's checklist compartment, opted
   into by public/js/tasks.js). Clickable everywhere it appears: in the edit form, and straight
   from a browse-view card, collapsed or not, where a tick saves on the spot. The shared read-only
   view never opts into the gutter, so there is no display-only case to exclude here. */
.cm-checklist-gutter {
  padding-right: 6px;
}

.cm-checklist-box {
  margin-top: 2px;
  cursor: pointer;
}

/* Same green-on-hover affordance the board's own done button uses (.project-done-btn), so ticking
   a list line and marking a card done read as the same gesture. */
.cm-checklist-box:hover {
  border-color: var(--color-green);
}

.cheat-body .cm-editor {
  max-height: 275px;
}

.large .cheat-body .cm-editor {
  max-height: 215px;
}

/* Tasks, Brain, Vault and project cards all use a fixed card surface, so a long CodeMirror
   document must scroll inside its editor rather than extend underneath the card's clipped edge.
   Cheats already supply this sizing through their own layout; scope these dimensions to the
   other three sections. min-height: 0 is essential for a flex child: without it the scroller's
   content height becomes its minimum size and the outer .cheat-main clips it before it can
   scroll. */
#tasksList .cheat-body .cm-editor,
#vaultCheats .cheat-body .cm-editor,
#projectsBoard .cheat-body .cm-editor {
  overflow: hidden;
  min-height: 0;
}

#tasksList .cheat-body .cm-scroller,
#vaultCheats .cheat-body .cm-scroller,
#projectsBoard .cheat-body .cm-scroller {
  min-height: 0;
  max-height: 100%;
  overflow: auto;
}

#tasksList .cheat-body .cm-editor,
#vaultCheats .cheat-body .cm-editor {
  height: 275px;
}

#tasksList .cheat.large .cheat-body .cm-editor,
#vaultCheats .cheat.large .cheat-body .cm-editor {
  height: 215px;
}

/* A maximised cheat is the whole page, so its card sizes to its content rather than to the fixed
   400px every card in the browse grid shares. min-height has to be zeroed along with the other
   two: without it the base .cheat-main rule (and the 200px one in the responsive block) still
   held a short cheat open to full card height, and since the body is the last thing in the card,
   every bit of that slack showed up as dead space underneath the text. With it gone the gap below
   the body is just .cheat-main's own 20px padding, the same as the gap above the title. */
.max .cheat-main {
  min-height: 0;
  height: fit-content;
  max-height: fit-content;
}

.max .cheat-body .cm-editor {
  max-height: 100%;
}

.cm-content .var {
  color: var(--color-green);
}

.cm-content .note {
  color: var(--color-blue);
}

/* No text-transform here, unlike the global `a` rule: a link's text is the cheat's own content,
   often the URL itself or a command in a code block, and capitalizing it turned
   https://example.com/.well-known/x into Https://Example.Com/.Well-Known/X, a path that would
   break if retyped from the screen. */
.cm-content .link .var,
.cm-content .link .note,
.cm-content .link {
  color: var(--color-red);
  cursor: pointer;
}

.editing .cm-content .link {
  cursor: text;
}

.cm-content .link:hover {
  color: var(--color-red-h);
}

.cm-wrap {
  height: 100%;
}

.cm-changedText,
.cm-insertedLine {
  background: color-mix(in srgb, var(--color-green) 20%, transparent);
}

.cm-deletedChunk,
.cm-deletedText {
  background: color-mix(in srgb, var(--color-red) 20%, transparent);
}

.cm-deletedText {
  text-decoration: line-through;
}

/* Scrollable area */
@media screen and (max-width: 1000px) {
  html:not([data-viewport-mode=desktop]) * {
    font-size: 1em;
  }
  html:not([data-viewport-mode=desktop]) .cheat {
    width: 100%;
  }
  html:not([data-viewport-mode=desktop]) .cheat-main {
    min-height: 200px;
    height: 100%;
    max-height: 500px;
  }
  html:not([data-viewport-mode=desktop]) .cheat-body .cm-editor {
    max-height: 300px;
  }
  html:not([data-viewport-mode=desktop]) .large,
  html:not([data-viewport-mode=desktop]) .max {
    width: 100% !important;
    box-sizing: border-box;
  }
  html:not([data-viewport-mode=desktop]) .large .cheat-main {
    max-height: 800px;
  }
  html:not([data-viewport-mode=desktop]) #addNewCheat.large .cheat-main,
  html:not([data-viewport-mode=desktop]) #addNewTask.large .cheat-main,
  html:not([data-viewport-mode=desktop]) #addNewVaultCheat.large .cheat-main {
    min-height: 400px !important;
    height: 100% !important;
  }
  html:not([data-viewport-mode=desktop]) .large .cheat-body .cm-editor {
    max-height: 500px;
  }
  html:not([data-viewport-mode=desktop]) h1 {
    font-size: 1.5em !important;
  }
  html:not([data-viewport-mode=desktop]) #FilterArea {
    flex-direction: column; /* stack vertically */
  }
  html:not([data-viewport-mode=desktop]) {
    /* The header stays a row (see #TitleArea above) with its pills on the left, but a view's
       search box drops onto a row of its own underneath, full width, rather than squeezing the
       pills. */
  }
  html:not([data-viewport-mode=desktop]) #TitleArea .search_bar {
    order: 3;
    flex-basis: 100%;
    margin: 0;
  }
  html:not([data-viewport-mode=desktop]) #TitleArea .search_form,
  html:not([data-viewport-mode=desktop]) #TitleArea .search_bar input {
    width: 100%;
    box-sizing: border-box;
  }
  html:not([data-viewport-mode=desktop]) .title {
    font-size: 2em !important;
    float: none;
  }
  html:not([data-viewport-mode=desktop]) .revise {
    width: 100% !important;
    box-sizing: border-box;
    height: fit-content;
  }
  html:not([data-viewport-mode=desktop]) .revision-code {
    width: calc(100% - 240px);
  }
  html:not([data-viewport-mode=desktop]) .revision-list {
    width: 220px;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding-left: 40px;
    padding-right: 40px;
    margin-left: -40px;
    margin-right: -40px;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-controls,
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-block,
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-types,
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-filters {
    width: 100%;
    flex: none;
    min-width: 0;
  }
  html:not([data-viewport-mode=desktop]) .filter-seg {
    width: 100%;
  }
  html:not([data-viewport-mode=desktop]) .filter-seg .userButton {
    flex: 1 1 auto;
    text-align: center;
  }
  html:not([data-viewport-mode=desktop]) .filter-seg .userButton a,
  html:not([data-viewport-mode=desktop]) .filter-seg .userButton:not(:has(a)) {
    padding: 4px 8px;
    font-size: 11px;
  }
  html:not([data-viewport-mode=desktop]) .sort-select {
    width: 100%;
    box-sizing: border-box;
    font-size: 11px;
    padding: 4px 24px 4px 8px;
    min-width: 0;
  }
  html:not([data-viewport-mode=desktop]) {
    /* Cap the type cloud so it cannot eat half the phone screen. */
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-type-row {
    max-height: 4.5rem;
    overflow: auto;
    align-content: flex-start;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .type-cheat {
    padding: 2px 6px;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .type-cheat.tag-w1 .type-name,
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .type-cheat.tag-w2 .type-name,
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .type-cheat.tag-w3 .type-name {
    font-size: 0.85em;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .type-cheat.tag-w4 .type-name,
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .type-cheat.tag-w5 .type-name {
    font-size: 0.95em;
    font-weight: 600;
  }
  html:not([data-viewport-mode=desktop]) #TitleArea .pill-group {
    justify-content: flex-start;
  }
}
html[data-viewport-mode=mobile] * {
  font-size: 1em;
}
html[data-viewport-mode=mobile] .cheat {
  width: 100%;
}
html[data-viewport-mode=mobile] .cheat-main {
  min-height: 200px;
  height: 100%;
  max-height: 500px;
}
html[data-viewport-mode=mobile] .cheat-body .cm-editor {
  max-height: 300px;
}
html[data-viewport-mode=mobile] .large,
html[data-viewport-mode=mobile] .max {
  width: 100% !important;
  box-sizing: border-box;
}
html[data-viewport-mode=mobile] .large .cheat-main {
  max-height: 800px;
}
html[data-viewport-mode=mobile] #addNewCheat.large .cheat-main,
html[data-viewport-mode=mobile] #addNewTask.large .cheat-main,
html[data-viewport-mode=mobile] #addNewVaultCheat.large .cheat-main {
  min-height: 400px !important;
  height: 100% !important;
}
html[data-viewport-mode=mobile] .large .cheat-body .cm-editor {
  max-height: 500px;
}
html[data-viewport-mode=mobile] h1 {
  font-size: 1.5em !important;
}
html[data-viewport-mode=mobile] #FilterArea {
  flex-direction: column; /* stack vertically */
}
html[data-viewport-mode=mobile] {
  /* The header stays a row (see #TitleArea above) with its pills on the left, but a view's
     search box drops onto a row of its own underneath, full width, rather than squeezing the
     pills. */
}
html[data-viewport-mode=mobile] #TitleArea .search_bar {
  order: 3;
  flex-basis: 100%;
  margin: 0;
}
html[data-viewport-mode=mobile] #TitleArea .search_form,
html[data-viewport-mode=mobile] #TitleArea .search_bar input {
  width: 100%;
  box-sizing: border-box;
}
html[data-viewport-mode=mobile] .title {
  font-size: 2em !important;
  float: none;
}
html[data-viewport-mode=mobile] .revise {
  width: 100% !important;
  box-sizing: border-box;
  height: fit-content;
}
html[data-viewport-mode=mobile] .revision-code {
  width: calc(100% - 240px);
}
html[data-viewport-mode=mobile] .revision-list {
  width: 220px;
}
html[data-viewport-mode=mobile] .cheats-toolbar {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding-left: 40px;
  padding-right: 40px;
  margin-left: -40px;
  margin-right: -40px;
}
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-controls,
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-block,
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-types,
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-filters {
  width: 100%;
  flex: none;
  min-width: 0;
}
html[data-viewport-mode=mobile] .filter-seg {
  width: 100%;
}
html[data-viewport-mode=mobile] .filter-seg .userButton {
  flex: 1 1 auto;
  text-align: center;
}
html[data-viewport-mode=mobile] .filter-seg .userButton a,
html[data-viewport-mode=mobile] .filter-seg .userButton:not(:has(a)) {
  padding: 4px 8px;
  font-size: 11px;
}
html[data-viewport-mode=mobile] .sort-select {
  width: 100%;
  box-sizing: border-box;
  font-size: 11px;
  padding: 4px 24px 4px 8px;
  min-width: 0;
}
html[data-viewport-mode=mobile] {
  /* Cap the type cloud so it cannot eat half the phone screen. */
}
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-type-row {
  max-height: 4.5rem;
  overflow: auto;
  align-content: flex-start;
}
html[data-viewport-mode=mobile] .cheats-toolbar .type-cheat {
  padding: 2px 6px;
}
html[data-viewport-mode=mobile] .cheats-toolbar .type-cheat.tag-w1 .type-name,
html[data-viewport-mode=mobile] .cheats-toolbar .type-cheat.tag-w2 .type-name,
html[data-viewport-mode=mobile] .cheats-toolbar .type-cheat.tag-w3 .type-name {
  font-size: 0.85em;
}
html[data-viewport-mode=mobile] .cheats-toolbar .type-cheat.tag-w4 .type-name,
html[data-viewport-mode=mobile] .cheats-toolbar .type-cheat.tag-w5 .type-name {
  font-size: 0.95em;
  font-weight: 600;
}
html[data-viewport-mode=mobile] #TitleArea .pill-group {
  justify-content: flex-start;
}

/* Phones only — tablets keep the padded card layout above */
@media screen and (max-width: 600px) {
  html:not([data-viewport-mode=desktop]) {
    /* Legacy (non-workbench) pages still want a small page inset. */
  }
  html:not([data-viewport-mode=desktop]) #ContainerMain {
    padding: 10px;
  }
  html:not([data-viewport-mode=desktop]) {
    /* Workbench already insets via #MainColumn. Padding #ContainerMain here left a second
       gutter that TitleArea / .cheats-toolbar could not cancel (their -10px bleed only
       matches #MainColumn), so the toolbar looked inset on mobile / forced-Mobile. */
  }
  html:not([data-viewport-mode=desktop]) #ContainerMain.workbench-shell {
    padding: 0;
  }
  html:not([data-viewport-mode=desktop]) #ContainerMain.workbench-shell #MainColumn {
    padding: 10px;
  }
  html:not([data-viewport-mode=desktop]) {
    /* Matches the 10px #MainColumn padding just above, so the band still reaches the edges. */
  }
  html:not([data-viewport-mode=desktop]) #TitleArea {
    margin: -10px -10px 16px;
    padding: 8px 10px;
    min-height: 0;
    row-gap: 6px;
  }
  html:not([data-viewport-mode=desktop]) body:has(.cheats-toolbar) #TitleArea {
    margin-bottom: 0;
    border-bottom: 0;
  }
  html:not([data-viewport-mode=desktop]) #TitleArea .search_bar input {
    padding: 6px 8px;
    font-size: 12px;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar {
    padding: 8px 10px;
    margin: 0 -10px 10px;
    gap: 6px;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-controls {
    gap: 6px;
  }
  html:not([data-viewport-mode=desktop]) .cheats-toolbar .toolbar-type-row {
    max-height: 3.75rem;
  }
  html:not([data-viewport-mode=desktop]) {
    /* A phone's utility bar: Menu + crumb. Sections live in the side drawer. */
  }
  html:not([data-viewport-mode=desktop]) .title.header-title {
    font-size: 18px !important;
  }
  html:not([data-viewport-mode=desktop]) .main-crumb {
    font-size: 12px;
  }
  html:not([data-viewport-mode=desktop]) .cheat-feed .cheat-title {
    font-size: 13px !important;
  }
  html:not([data-viewport-mode=desktop]) .cheat-feed .cheat-main {
    padding: 8px 10px 10px;
  }
  html:not([data-viewport-mode=desktop]) #TitleLeft {
    flex-wrap: nowrap;
    gap: 10px;
  }
  html:not([data-viewport-mode=desktop]) #TitleArea #UserArea.pill-group {
    flex-wrap: nowrap;
    gap: 6px;
  }
  html:not([data-viewport-mode=desktop]) #TitleArea .pill-group .userButton {
    padding: 6px 10px;
  }
  html:not([data-viewport-mode=desktop]) .cheat {
    margin-left: 0;
    margin-right: 0;
  }
  html:not([data-viewport-mode=desktop]) #FooterColumns {
    flex-direction: column;
    align-items: center;
  }
  html:not([data-viewport-mode=desktop]) .footerColumn {
    width: 100%;
    text-align: center;
  }
}
html[data-viewport-mode=mobile] {
  /* Legacy (non-workbench) pages still want a small page inset. */
}
html[data-viewport-mode=mobile] #ContainerMain {
  padding: 10px;
}
html[data-viewport-mode=mobile] {
  /* Workbench already insets via #MainColumn. Padding #ContainerMain here left a second
     gutter that TitleArea / .cheats-toolbar could not cancel (their -10px bleed only
     matches #MainColumn), so the toolbar looked inset on mobile / forced-Mobile. */
}
html[data-viewport-mode=mobile] #ContainerMain.workbench-shell {
  padding: 0;
}
html[data-viewport-mode=mobile] #ContainerMain.workbench-shell #MainColumn {
  padding: 10px;
}
html[data-viewport-mode=mobile] {
  /* Matches the 10px #MainColumn padding just above, so the band still reaches the edges. */
}
html[data-viewport-mode=mobile] #TitleArea {
  margin: -10px -10px 16px;
  padding: 8px 10px;
  min-height: 0;
  row-gap: 6px;
}
html[data-viewport-mode=mobile] body:has(.cheats-toolbar) #TitleArea {
  margin-bottom: 0;
  border-bottom: 0;
}
html[data-viewport-mode=mobile] #TitleArea .search_bar input {
  padding: 6px 8px;
  font-size: 12px;
}
html[data-viewport-mode=mobile] .cheats-toolbar {
  padding: 8px 10px;
  margin: 0 -10px 10px;
  gap: 6px;
}
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-controls {
  gap: 6px;
}
html[data-viewport-mode=mobile] .cheats-toolbar .toolbar-type-row {
  max-height: 3.75rem;
}
html[data-viewport-mode=mobile] {
  /* A phone's utility bar: Menu + crumb. Sections live in the side drawer. */
}
html[data-viewport-mode=mobile] .title.header-title {
  font-size: 18px !important;
}
html[data-viewport-mode=mobile] .main-crumb {
  font-size: 12px;
}
html[data-viewport-mode=mobile] .cheat-feed .cheat-title {
  font-size: 13px !important;
}
html[data-viewport-mode=mobile] .cheat-feed .cheat-main {
  padding: 8px 10px 10px;
}
html[data-viewport-mode=mobile] #TitleLeft {
  flex-wrap: nowrap;
  gap: 10px;
}
html[data-viewport-mode=mobile] #TitleArea #UserArea.pill-group {
  flex-wrap: nowrap;
  gap: 6px;
}
html[data-viewport-mode=mobile] #TitleArea .pill-group .userButton {
  padding: 6px 10px;
}
html[data-viewport-mode=mobile] .cheat {
  margin-left: 0;
  margin-right: 0;
}
html[data-viewport-mode=mobile] #FooterColumns {
  flex-direction: column;
  align-items: center;
}
html[data-viewport-mode=mobile] .footerColumn {
  width: 100%;
  text-align: center;
}

/* Vault */
#vaultBody {
  padding-top: 10px;
}

#vaultSetupArea input,
#vaultUnlockArea input {
  margin-bottom: 10px;
}

#vaultSetupArea input.input-error,
#vaultUnlockArea input.input-error {
  border-color: var(--color-red);
}

.vault-error {
  color: var(--color-red-h);
  margin-bottom: 10px;
  min-height: 1.2em;
}

#vaultCheatsList:not(.cheat-feed) {
  clear: both;
  display: flex;
  flex-wrap: wrap;
}

/* Hidden until the card is expanded — same as the main cheat page, where edit-cheat/
   delete-cheat only get added to the DOM once a cheat becomes active (setCheatActive in
   public/js/script.js); here the icons always exist in the markup, so they're hidden by
   default and revealed once .large is present instead. Shared with .task-actions below. */
.vault-cheat-actions,
.task-actions,
.project-task-actions {
  display: none;
  float: right;
}

.cheat.large .vault-cheat-actions,
.cheat.large .task-actions,
.cheat.large .project-task-actions {
  display: block;
}

.vault-cheat-actions a,
.task-actions a,
.project-task-actions a {
  margin-left: 8px;
}

/* Tasks */
#tasksBody {
  padding-top: 10px;
}

#tasksList:not(.cheat-feed) {
  clear: both;
  display: flex;
  flex-wrap: wrap;
}

.cheat-feed .cheat.editing .cheat-type.taskCategory.editable {
  cursor: pointer;
}

/* About-this-section panel in the rail (syncSideHelp in auth.js). Replaces the old floating
   .sectionHelp "?" — same copy, quieter chrome, sits under the section links. */
.side-help {
  flex-shrink: 0;
  padding: 0 8px;
}

.side-help[hidden] {
  display: none;
}

.side-help-panel {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 10px;
  border-radius: 6px;
  background-color: color-mix(in srgb, var(--color-dark-l) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-white) 8%, transparent);
}

.side-help-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin: 1px 0 0;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--color-green) 40%, var(--color-dark-b));
  border-radius: 6px;
  background-color: color-mix(in srgb, var(--color-green) 10%, transparent);
  color: var(--color-green);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  cursor: help;
}

.side-help-btn:hover,
.side-help-btn:focus-visible {
  border-color: color-mix(in srgb, var(--color-green) 65%, var(--color-dark-b));
  color: var(--color-green-h);
  background-color: color-mix(in srgb, var(--color-green) 16%, transparent);
  outline: none;
}

.side-help-copy {
  min-width: 0;
  flex: 1 1 auto;
}

.side-help-label {
  display: block;
  margin: 0 0 4px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-white-l);
}

.side-help-text {
  margin: 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--color-white);
  /* Clip long blurbs in the rail; the "?" still carries the full text as a tooltip. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}

body.side-nav-collapsed .side-help {
  padding: 0 4px;
}

body.side-nav-collapsed .side-help-panel {
  justify-content: center;
  padding: 6px 0;
  background: transparent;
  border: 0;
}

body.side-nav-collapsed .side-help-copy {
  display: none;
}

body.side-nav-collapsed .side-help-btn {
  width: 28px;
  height: 28px;
}

.task-done-btn .fa-check {
  color: var(--color-white-l);
}

.task-done-btn:hover .fa-check {
  color: var(--color-green);
}

/* Same button, but on /brain it deletes rather than completes (see taskSectionCompletesItems in
   public/js/tasks.js), so it turns the site's red on hover instead of the "finished" green. */
.task-done-btn .fa-trash {
  color: var(--color-white-l);
}

.task-done-btn:hover .fa-trash {
  color: var(--color-red-h);
}

/* Category/duration pills. .taskCategory shows up in two contexts — plain display text in the
   browse-view card (buildTaskCard in public/js/tasks.js — no click handler, so no reason to look
   clickable), and an actual cycling control in the edit form (renderTaskEditor), which only gets
   the brighter, pointer-cursor %clickable-accent treatment via the .editable modifier that JS
   adds precisely where it also binds the click handler — including staying off a locked 'note'
   task's category pill. Same small pill treatment as the main cheat editor's Public/Private label
   (.makePrivate/.makePublic) either way. .taskDuration only ever appears in the edit form and is
   never locked, so it's unconditionally clickable. Tasks used to carry a workflow status pill
   here too; that concept now lives only in Projects (.projectStatus below), where a status is
   what puts a card in a board column rather than a field bolted onto a note. */
/* Pennies: private buy/sell order log + portfolio summary + estimator. Reuses the .cheat card
   shell and .cheat-details pill styling throughout, same as Tasks/Vault above. */
#penniesBody {
  padding-top: 10px;
}

.pennies-tabs, .dues-tabs, .hours-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
  clear: both;
}

/* The tab row is a .pennyFilterRow like the filter rows below it, so its "View:" label and its
   pills land in exactly the same two columns as "Type:"/"Asset:" — one left rail down the whole
   pane rather than tabs at the page edge and filter pills indented past their labels. The row
   carries the bottom margin in place of the inner .pennies-tabs, so the two don't stack. */
#penniesViewRow {
  margin-bottom: 10px;
}

#penniesViewRow .pennies-tabs, #penniesViewRow .dues-tabs, #penniesViewRow .hours-tabs {
  margin-bottom: 0;
}

.pennies-tab, .dues-tab, .hours-tab, .project-tab, .penny-filter-pill, .dues-filter-pill, .hours-filter-pill {
  padding: 5px 10px;
  border-radius: 4px;
  background-color: transparent;
  border: 1px solid color-mix(in srgb, var(--color-white) 12%, var(--color-dark-b));
  text-transform: none;
}

.pennies-tab:hover, .dues-tab:hover, .hours-tab:hover, .project-tab:hover, .penny-filter-pill:hover, .dues-filter-pill:hover, .hours-filter-pill:hover {
  background-color: color-mix(in srgb, var(--color-dark-h) 55%, transparent);
  border-color: color-mix(in srgb, var(--color-white) 20%, var(--color-dark-b));
}

.pennies-tab.active, .active.dues-tab, .active.hours-tab, .active.project-tab, .active.penny-filter-pill, .active.dues-filter-pill, .active.hours-filter-pill {
  color: var(--color-green) !important;
  background-color: color-mix(in srgb, var(--color-green) 12%, var(--color-dark-h));
  border-color: color-mix(in srgb, var(--color-green) 40%, var(--color-dark-b));
}

/* Top-level view tabs (Orders / Summary / …) read as an underline strip; filter chips keep the
   ghost-pill look above. hours-tab and dues-tab @extend .pennies-tab, so the same strip applies. */
.pennies-tabs,
.dues-tabs,
.hours-tabs {
  gap: 4px;
  border-bottom: 1px solid var(--color-dark-l);
  padding-bottom: 0;
}

.pennies-tabs .pennies-tab, .pennies-tabs .dues-tab, .dues-tabs .pennies-tab, .pennies-tabs .hours-tab, .dues-tabs .hours-tab, .hours-tabs .pennies-tab, .hours-tabs .dues-tab, .pennies-tabs .project-tab, .dues-tabs .project-tab, .hours-tabs .project-tab, .pennies-tabs .penny-filter-pill, .pennies-tabs .dues-filter-pill, .dues-tabs .penny-filter-pill, .dues-tabs .dues-filter-pill, .pennies-tabs .hours-filter-pill, .dues-tabs .hours-filter-pill, .hours-tabs .penny-filter-pill, .hours-tabs .dues-filter-pill, .hours-tabs .hours-filter-pill,
.hours-tabs .hours-tab,
.dues-tabs .dues-tab {
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background-color: transparent;
  margin-bottom: -1px;
  padding: 8px 12px;
}

.pennies-tabs .pennies-tab:hover, .pennies-tabs .dues-tab:hover, .dues-tabs .pennies-tab:hover, .pennies-tabs .hours-tab:hover, .dues-tabs .hours-tab:hover, .hours-tabs .pennies-tab:hover, .hours-tabs .dues-tab:hover, .pennies-tabs .project-tab:hover, .dues-tabs .project-tab:hover, .hours-tabs .project-tab:hover, .pennies-tabs .penny-filter-pill:hover, .pennies-tabs .dues-filter-pill:hover, .dues-tabs .penny-filter-pill:hover, .dues-tabs .dues-filter-pill:hover, .pennies-tabs .hours-filter-pill:hover, .dues-tabs .hours-filter-pill:hover, .hours-tabs .penny-filter-pill:hover, .hours-tabs .dues-filter-pill:hover, .hours-tabs .hours-filter-pill:hover,
.hours-tabs .hours-tab:hover,
.dues-tabs .dues-tab:hover {
  background-color: transparent;
  border-color: transparent;
  border-bottom-color: color-mix(in srgb, var(--color-white) 25%, transparent);
}

.pennies-tabs .pennies-tab.active, .pennies-tabs .active.dues-tab, .dues-tabs .pennies-tab.active, .pennies-tabs .active.hours-tab, .dues-tabs .active.hours-tab, .hours-tabs .pennies-tab.active, .hours-tabs .active.dues-tab, .pennies-tabs .active.project-tab, .dues-tabs .active.project-tab, .hours-tabs .active.project-tab, .pennies-tabs .active.penny-filter-pill, .pennies-tabs .active.dues-filter-pill, .dues-tabs .active.penny-filter-pill, .dues-tabs .active.dues-filter-pill, .pennies-tabs .active.hours-filter-pill, .dues-tabs .active.hours-filter-pill, .hours-tabs .active.penny-filter-pill, .hours-tabs .active.dues-filter-pill, .hours-tabs .active.hours-filter-pill,
.hours-tabs .hours-tab.active,
.dues-tabs .dues-tab.active {
  background-color: transparent;
  border-color: transparent;
  border-bottom-color: var(--color-green);
  color: var(--color-white-h) !important;
}

.pennies-pane, .dues-pane, .hours-pane {
  clear: both;
}

#penniesList, #duesList,
#duesPayersList,
#duesServicesList,
#duesMethodsList, #hoursList,
#hoursProjectsList {
  clear: both;
}

.pennyImportOpen {
  margin: 0 0 12px;
}

.pennyImportPanel button {
  padding: 7px 12px;
  border: 0;
  border-radius: 8px;
}

.pennyImportPanel button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.pennyImportPanel {
  margin: 0 0 18px;
  padding: 14px;
  border: 1px solid var(--color-dark-h);
  border-radius: 10px;
  background: var(--color-dark);
}

.pennyImportHeader,
.pennyImportControls,
.pennyImportDefaults {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.pennyImportHeader {
  justify-content: space-between;
  align-items: flex-start;
}

.pennyImportHeader h2,
.pennyImportMapping h3 {
  margin: 0 0 6px;
}

.pennyImportHeader p,
.pennyImportMapping p,
.pennyImportPreviewArea p {
  margin: 0 0 10px;
}

.pennyImportControls,
.pennyImportDefaults {
  margin: 10px 0;
}

.pennyImportControls label,
.pennyImportDefaults label,
.pennyImportColumnGrid label,
.pennyImportTypeGrid label {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pennyImportColumnGrid,
.pennyImportTypeGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
  margin: 10px 0;
}

.pennyImportColumnGrid select,
.pennyImportDefaults select,
.pennyImportTypeGrid select,
.pennyImportPlatform,
.pennyImportFile {
  max-width: 100%;
}

.pennyImportStatus {
  min-height: 1.4em;
  margin: 8px 0;
}

.pennyImportTableWrap {
  max-height: 360px;
  overflow: auto;
  margin: 10px 0;
}

.pennyImportTableWrap table {
  width: 100%;
  border-collapse: collapse;
}

.pennyImportTableWrap th,
.pennyImportTableWrap td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--color-dark-h);
  text-align: left;
  white-space: nowrap;
}

.pennyImportTableWrap .duplicate {
  opacity: 0.65;
}

#penniesList .cheat.large .cheat-main, #duesList .cheat.large .cheat-main,
#duesPayersList .cheat.large .cheat-main,
#duesServicesList .cheat.large .cheat-main,
#duesMethodsList .cheat.large .cheat-main, #hoursList .cheat.large .cheat-main,
#hoursProjectsList .cheat.large .cheat-main {
  height: auto;
  max-height: 700px;
}

/* Collapsed preset-field cards are a handful of label/value lines — size to that content instead
   of a fixed 180/400px shell that leaves a silly empty band under short entries. .cheat-feed's
   own height:auto already covers the feed; these ID rules beat the generic 400px .cheat-main. */
#penniesList .cheat:not(.large) .cheat-main,
#hoursList .cheat:not(.large) .cheat-main,
#hoursProjectsList .cheat:not(.large) .cheat-main,
#duesList .cheat:not(.large) .cheat-main,
#duesPayersList .cheat:not(.large) .cheat-main,
#duesServicesList .cheat:not(.large) .cheat-main,
#duesMethodsList .cheat:not(.large) .cheat-main {
  min-height: 0;
  height: auto;
}

/* Expanded dues: grow to fit like Pennies (the old fixed 400px clipped forms and left slack on
   short details). .duesDetails still caps and scrolls for unusually long content. */
#duesList .cheat.large .cheat-main {
  height: auto;
  max-height: 700px;
}

/* Hidden until the card is expanded, same show-on-.large treatment as .task-actions/
   .vault-cheat-actions above. */
.penny-actions, .dues-actions, .hours-actions {
  display: none;
  float: right;
}

.cheat.large .penny-actions, .cheat.large .dues-actions, .cheat.large .hours-actions {
  display: block;
}

.penny-actions a, .dues-actions a, .hours-actions a {
  margin-left: 8px;
}

.pennySide.pennyBuy {
  color: var(--color-green-h);
}

.pennySide.pennySell {
  color: var(--color-red-h);
}

/* Stake/unstake are position movements rather than trades, so they deliberately sit outside the
   green/red buy/sell pair — nothing was gained or lost, units just changed where they live. */
.pennySide.pennyStake,
.pennySide.pennyUnstake {
  color: var(--color-blue-h);
}

/* A reward is the one movement that does leave you better off, so it takes the same green as a
   buy rather than the movement blue — units arrived, they just weren't bought. */
.pennySide.pennyReward {
  color: var(--color-green-h);
}

/* A pending limit order's status pill — the same plain, non-clickable .cheat-details treatment
   the other section pills get, and always visible, since a pending order is materially different
   from a completed trade at a glance, not just a workflow nuance. */
.pennyStatus.pennyPending {
  color: var(--color-gold-h);
}

/* Hint shown under the Order type selector once "Limit" is picked (renderPennyEditor) — same
   muted, italic treatment as .pennyProjectedDisclaimer below. */
.pennyOrderKindHint, .duesFreezeHint, .duesTemplatePreviewLabel, .duesMethodHandleHint, .duesGrossHint,
.duesSummaryNote, .duesFormError, .hoursEarnsPreview, .hoursRateHint,
.hoursSummaryNote, .hoursFormError, .pennyMovementHint {
  font-size: 0.85em;
  font-style: italic;
  color: var(--color-gold-h);
  margin: 0;
}

/* Same muted, italic explainer treatment as .pennyOrderKindHint, in the movement colour the
   Stake/Unstake pills use rather than the pending-order yellow. */
.pennyMovementHint {
  color: var(--color-blue-h);
}

/* Sized to fit within #penniesList .cheat.large .cheat-main's own 700px cap above (minus its
   padding and, for the form, the save/reset icon row below) — a comfortable fit for a normal
   order's details or the full add-order form, so scrolling only ever kicks in for something
   unusually long (e.g. a lengthy note), via the same thin scrollbar as the CodeMirror body. */
.pennyDetails, .duesDetails, .hoursDetails,
.pennyForm,
.duesForm,
.hoursForm {
  clear: both;
  max-height: 620px;
  overflow-y: auto;
  padding-top: 10px;
}

.pennyDetails, .duesDetails, .hoursDetails {
  display: none;
}

/* Historical market comparisons are deliberately fetched only after this button is pressed: a
   full transaction log must not fan out into third-party price requests just by being opened. */
.pennyMarketCompare {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  color: var(--color-white-l);
  font-size: 0.85em;
}

.penny-market-btn {
  border: none;
  font: inherit;
}

.cheat.large .pennyDetails, .cheat.large .duesDetails, .cheat.large .hoursDetails {
  display: block;
}

/* Headline trade facts (qty/price/total/date) — visible on the collapsed card too, unlike the
   fees/tax/notes breakdown above, which only earns its place once the card is expanded. Same
   muted, constant-size treatment as .cheat-details elsewhere (cheats/Tasks don't resize their
   pill text between collapsed and .large either), so expanding a card only grows its container,
   never its font. */
.pennyQuickInfo, .duesQuickInfo, .hoursQuickInfo {
  clear: both;
  padding-top: 6px;
  color: var(--color-white-l);
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.9em;
  line-height: 1.35;
}

/* The <strong> field labels (Qty/Price/Total/Date/Fees/Tax/Notes) are semantic markup, not a
   styling cue — every other pill/label in the app (.cheat-details, .pennyForm label) leans on
   color and uppercase for emphasis rather than weight, so bold here read noticeably heavier than
   the rest of the page. Normal weight keeps that same look. */
.pennyQuickInfo strong, .duesQuickInfo strong, .hoursQuickInfo strong,
.pennyDetails strong,
.duesDetails strong,
.hoursDetails strong {
  font-weight: normal;
}

.pennyForm, .duesForm, .hoursForm {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pennyEstimatorSection label,
.pennyForm label,
.duesForm label,
.hoursForm label {
  display: flex;
  flex-direction: column;
  color: var(--color-white-l);
  font-size: 0.85em;
  text-transform: uppercase;
}

.pennyEstimatorSection input {
  background-color: var(--color-dark-b);
  color: var(--color-white-h);
  color-scheme: var(--color-scheme);
  margin-top: 3px;
}

/* Checkboxes excluded: this rule comes after the site-wide themed input[type="checkbox"] at the
   same specificity, so it would otherwise repaint the box as a rounded text field. */
.pennyForm input:not([type=checkbox]), .duesForm input:not([type=checkbox]), .hoursForm input:not([type=checkbox]) {
  margin-top: 3px;
}

/* A checkbox reads beside its label rather than under it, same as .hoursCheckboxRow. */
.pennyForm label.pennyCheckboxRow, .duesForm label.pennyCheckboxRow, .hoursForm label.pennyCheckboxRow {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.pennyEstimatorSection select,
.pennyForm select,
.duesForm select,
.hoursForm select {
  margin-top: 3px;
}

/* The table has too many columns to fit a phone screen at readable widths, so the wrapper
   scrolls horizontally instead of relying on #container's overflow-x: hidden, which would just
   clip it off-screen with no way to reach the cut-off columns. */
#penniesSummary {
  max-width: 100%;
  overflow-x: auto;
}

.pennySummaryTable, .duesBreakdownTable, .hoursBreakdownTable {
  width: 100%;
  min-width: 700px;
  border-collapse: collapse;
}

.pennySummaryTable th, .duesBreakdownTable th, .hoursBreakdownTable th,
.pennySummaryTable td,
.duesBreakdownTable td,
.hoursBreakdownTable td {
  padding: 8px 10px;
  text-align: left;
  border-bottom: 1px solid var(--color-dark-l);
}

.pennySummaryTable input, .duesBreakdownTable input, .hoursBreakdownTable input {
  background-color: var(--color-dark-b);
  color: var(--color-white-h);
  width: 100px;
}

/* Every holding row expands to its own order ledger, so the whole row is a click target — the
   caret is the affordance, and it rotates once the row is open (same idea as the section headers
   elsewhere, without needing a separate control column). */
.pennyHoldingRow {
  cursor: pointer;
}

.pennyHoldingRow:hover {
  background-color: var(--color-dark-h);
}

.pennyExpandCaret {
  display: inline-block;
  color: var(--color-white-l);
  margin-right: 4px;
  transition: transform 0.15s ease;
}

.pennyHoldingRow.expanded .pennyExpandCaret {
  transform: rotate(90deg);
}

/* The same figure in the account's base currency, under the holding's own — a secondary reading of
   one number rather than a second number, so it stays visibly subordinate to the line above it. */
.pennyBaseAmount, .pennyQtyNote, .pennyQtyWarning {
  font-size: 0.8em;
  color: var(--color-white-l);
  margin-top: 2px;
}

/* "0.3 staked" / "+0.01 reward" under a quantity. Same subordinate treatment as .pennyBaseAmount,
   which these sit alongside in the summary and ledger tables. */
/* Flags a holding whose logged sells exceed its logged buys. Same subordinate size as the notes
   above, in the pending-order yellow, since both mean "this needs something from you" rather than
   "this is broken". */
.pennyQtyWarning {
  color: var(--color-gold-h);
  cursor: help;
}

/* The per-holding order ledger revealed by expanding a summary row. Inset and darker so it reads
   as belonging to the row above rather than as more rows of the same table. */
.pennyLedgerRow > td {
  padding: 0 !important;
  background-color: var(--color-dark-h);
}

.pennyLedger {
  overflow-x: auto;
  padding: 10px 10px 10px 26px;
}

.pennyLedgerTable {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  font-size: 0.9em;
}

.pennyLedgerTable th,
.pennyLedgerTable td {
  padding: 6px 10px;
  text-align: left;
  border-bottom: 1px solid var(--color-dark-l);
}

.pennyLedgerSide {
  text-transform: uppercase;
  font-size: 0.85em;
}

.pennyLedgerPlatform {
  color: var(--color-white-l);
  font-size: 0.85em;
}

.pennyLedgerNote {
  font-size: 0.8em;
  font-style: italic;
  color: var(--color-white-l);
  margin: 6px 0 0;
}

/* Summary tab type/asset filters. @extend .pennies-tab rather than a copy, same as
   .project-tab below, so all three pill rows stay identical by construction and the active
   pill's green comes through for free. */
.pennyFilters, .duesFilters, .hoursFilters {
  margin-bottom: 12px;
}

.pennyFilterRow, .duesFilterRow, .hoursFilterRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

/* The label at the head of a Pennies control row: the View row of tabs, and the Type/Asset/
   Tax year/Currency filter rows under it. Same green bold label the cheat-browse page puts in
   front of its own rows ("Search:", "Tags:", "Filter:"), rather than the small grey uppercase
   caption this used to be — a labelled control row is the same kind of thing on both pages.

   The min-width holds every row's pills in one column. The site's face is monospace, so 1ch is
   exactly one character: 10ch is the longest label ("Tax year:") plus a character of clear
   space, so even that row keeps a visible gap before its first pill rather than running
   straight into it. Widen this if a longer label is ever added. */
/* Balance check: recorded real-world holdings against what the order log implies. Sits below the
   holdings table and reuses .pennyLedgerTable's compact look, since it is the same kind of
   supporting detail rather than a second headline table. */
.pennyBalanceCheck {
  overflow-x: auto;
  margin-top: 20px;
}

.pennyBalanceCheck h2 {
  margin: 0 0 8px;
}

.pennyBalanceTable {
  min-width: 520px;
}

.pennyBalanceInput {
  background-color: var(--color-dark-b);
  color: var(--color-white-h);
  width: 120px;
}

/* Whole-portfolio roll-up above the holdings table, shown only once a base currency makes adding
   different currencies together meaningful. Wraps to as many rows as it needs on narrow screens,
   same flex-wrap approach as .pennyEstimatorSections below. */
.pennyTotalsPanel {
  margin-bottom: 15px;
  padding: 12px 15px;
}

.pennyTotalsPanel h2 {
  margin: 0 0 10px;
}

.pennyTaxExport {
  margin: 10px 0 15px;
}

.pennyTotalsFigures {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 30px;
}

.pennyTotalFigure {
  display: flex;
  flex-direction: column;
}

.pennyTotalLabel {
  font-size: 0.8em;
  text-transform: uppercase;
  color: var(--color-white-l);
}

.pennyTotalValue {
  font-size: 1.1em;
}

.pennyTotalsNote {
  font-size: 0.8em;
  font-style: italic;
  color: var(--color-white-l);
  margin: 8px 0 0;
}

.pennyPositive {
  color: var(--color-green-h);
}

.pennyNegative {
  color: var(--color-red-h);
}

.pennyPriceFreshness {
  font-size: 0.75em;
  color: var(--color-white-l);
  margin-top: 2px;
}

.pennyProjectedDisclaimer {
  display: block;
  font-size: 0.75em;
  color: var(--color-white-l);
  font-style: italic;
}

/* Side by side on desktop, wrapping to full width on narrow screens — same flex-wrap pattern as
   .billingTiers above, so no separate @media rule is needed for the mobile case. */
.pennyEstimatorSections {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.pennyEstimatorSection {
  flex: 1 1 320px;
}

.pennyEstimatorSection label {
  margin-bottom: 8px;
}

/* Calculate buttons — plain <button> elements have no themed reset of their own anywhere in the
   site (every other "button" is a styled <a>/<div>), so left alone they render with the browser's
   native grey chrome. Same dark rounded pill as .pennies-tab/.pill-group .userButton just above
   on this same page, so the two match instead of one looking native and the other themed. */
.pennyEstCalcBtn {
  font-family: inherit;
  font-size: 1em;
  background-color: var(--color-dark);
  border: none;
  padding: 6px 15px;
  border-radius: 10px;
  text-transform: uppercase;
  margin-top: 4px;
}

.pennyEstCalcBtn .fa-calculator {
  margin-right: 4px;
}

.pennyEstimatorSection input.input-error {
  border-color: var(--color-red);
}

/* Live "drag a price, watch the profit" slider shown under an estimator result. */
.pennyEstLive {
  margin-top: 10px;
}

.pennyEstLive label {
  display: flex;
  flex-direction: column;
  color: var(--color-white-l);
  font-size: 0.85em;
  text-transform: uppercase;
}

/* Slider and exact-price box side by side; the box wraps under the slider on a narrow phone
   rather than squeezing the slider down to nothing. */
.pennyEstLiveControls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 3px;
}

.pennyEstLiveSlider {
  flex: 1 1 180px;
  min-width: 0;
  margin-top: 0;
  accent-color: var(--color-green-h);
  min-height: 32px;
}

.pennyEstimatorSection input.pennyEstLiveInput {
  flex: 0 1 9em;
  min-width: 0;
  margin-top: 0;
  font-size: 16px;
  text-transform: none;
}

.pennyEstLiveReadout {
  margin-top: 6px;
}

/* Projects: a private Kanban board. Reuses the .cheat card shell, the .cheat-details pill styling
   and the .pennies-tab filter-pill look wholesale — the only genuinely new layout here is the
   column grid and the drag-and-drop affordances. */
#projectsBody {
  padding-top: 10px;
}

/* Project filter pills (All / each project / +). @extend rather than a copy of .pennies-tab, so
   the two rows stay identical by construction — that also pulls .pennies-tab.active's green
   through to .project-tab.active, which is exactly the treatment wanted here. */
.project-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
  clear: both;
}

/* Project switcher stays ghost chips (not the underline strip used for tool panes). */
.project-tabs .project-tab.active {
  color: var(--color-white-h) !important;
}

/* Rename/delete on the selected project, and save/cancel on the inline name form. Sits inside a
   pill, so it only needs spacing — the pill itself already carries the clickable treatment. */
.project-tab-action {
  margin-left: 8px;
}

.project-tab-form {
  display: flex;
  align-items: center;
  padding: 3px 10px;
}

.project-name-input {
  padding: 3px 10px;
  width: 140px;
}

/* An archived board, only ever in the row while the Archived toggle is on. Dimmed rather than
   struck through: it is filed away, not cancelled, and every card on it is still there. */
.project-tab-archived {
  opacity: 0.6;
}

.project-tab-archived:hover {
  opacity: 1;
}

/* The Show/Hide Archived pill at the end of the row. A filter over the pills beside it rather
   than a board of its own, so it takes the same pill shape but never the green "selected board"
   treatment unless the archived view is actually on. */
.project-tab-archive-toggle {
  font-size: 0.85em;
}

/* The little "this board has other people on it" marker inside a project pill — shared with you,
   or shared by you. Muted rather than accented: it labels a pill, it isn't a control. */
.project-tab-badge {
  margin-left: 8px;
  color: var(--color-white-l);
}

/* Members panel, opened from the selected project's pill. Same nested-panel treatment as
   .share-panel on a card ($color-dark-h against the page), since it is the same kind of thing:
   a sharing surface that belongs to the row above it. */
.project-members-panel {
  background-color: var(--color-dark-h);
  border-radius: 10px;
  padding: 15px;
  margin-bottom: 15px;
}

.project-members-title {
  margin-bottom: 10px;
}

.project-members-list {
  margin-bottom: 10px;
}

.project-member-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
}

/* An invite nobody has answered yet is dimmed, so the list reads as "these people are on the
   board, these have only been asked". */
.project-member-row.pending {
  color: var(--color-white-l);
}

.project-member-email {
  flex: 1 1 auto;
  overflow-wrap: anywhere;
}

.project-member-role {
  color: var(--color-white-l);
  white-space: nowrap;
}

.project-member-remove {
  cursor: pointer;
}

.project-member-remove:hover {
  color: var(--color-red);
}

.project-invite-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.project-invite-email {
  flex: 1 1 200px;
  border-radius: 5px;
}

.project-invite-send {
  white-space: nowrap;
}

.project-members-note,
.project-members-feedback {
  color: var(--color-white-l);
  margin-top: 8px;
}

/* Banner above the pill row, one per invite waiting to be answered. Green-edged rather than red:
   this is an offer, not a problem, and it is the one thing on the page asking to be acted on. */
.project-invite-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  background-color: var(--color-dark-h);
  border-left: 3px solid var(--color-green);
  border-radius: 10px;
  padding: 10px 15px;
  margin-bottom: 15px;
}

.project-invite-text {
  flex: 1 1 200px;
}

.project-invite-accept,
.project-invite-decline {
  white-space: nowrap;
}

.project-invite-status {
  color: var(--color-white-l);
}

/* The standalone page the emailed link opens (/projects?invite=<token>), which has no board
   behind it — it is readable signed out, so it has to explain itself on its own. */
.project-invite-panel {
  background-color: var(--color-dark-h);
  border-radius: 10px;
  padding: 20px;
  max-width: 600px;
}

.project-invite-actions {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-top: 15px;
}

/* Board. Columns share the width evenly on desktop and scroll horizontally rather than squashing
   below a readable card width; .project-column-cards is both the layout track and the drop
   target, which is why the highlight lives on it and not on .project-column. */
.project-board {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  clear: both;
  overflow-x: auto;
  padding-bottom: 10px;
}

.project-column {
  flex: 1 1 0;
  min-width: 260px;
  background-color: var(--color-dark-m);
  border-radius: 6px;
  padding: 10px;
  box-sizing: border-box;
}

.project-column-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: var(--color-white-l);
  text-transform: none;
  letter-spacing: 0.04em;
  font-size: 12px;
  margin-bottom: 10px;
}

.project-column-count {
  color: var(--color-white);
}

.project-column-cards {
  min-height: 80px;
  border-radius: 6px;
  border: 1px dashed transparent;
}

.project-column-cards.drag-over {
  border-color: var(--color-green);
  background-color: var(--color-dark-h);
}

.cheat.dragging {
  opacity: 0.4;
}

/* A board card is column-width, not the fixed 250px/510px a free-floating .cheat gets — the
   column decides the width here, and expanding a card grows it downward instead of sideways
   (going wide would either overflow the column or reflow the whole board). !important only
   because .large's own width carries one. */
#projectsBoard .cheat,
#projectsBoard .cheat.large {
  width: 100% !important;
  min-width: 0;
  margin: 0 0 10px 0;
}

/* Kanban cards are meant to be skimmed a column at a time, so a collapsed one is a short summary
   rather than the 400px block the cheat/Tasks lists use, and only grows once opened. */
#projectsBoard .cheat .cheat-main {
  min-height: 0;
  height: auto;
}

#projectsBoard .cheat .cheat-body .cm-editor {
  max-height: 110px;
  height: 110px;
}

#projectsBoard .cheat.large .cheat-body .cm-editor {
  max-height: 300px;
  height: 300px;
}

/* The add/edit form needs real room to type in, unlike the read-only cards above. */
#projectsBoard .cheat.editing .cheat-main {
  min-height: 380px;
}

#projectsBoard .cheat.editing .cheat-body .cm-editor {
  max-height: 200px;
  height: 200px;
}

/* Project/status pills on a card. .projectStatus is always clickable (it's the click-to-move
   fallback for dragging, and the only way to move a card on a touch screen), so unlike Tasks'
   pills it carries .editable in every context — see buildProjectTaskCard/renderProjectTaskEditor
   in public/js/projects.js. */
/* A card's type (Bug, Feature...). Read-only on the board, where it is coloured so a bug stands
   out from a column of features at a glance; in the editor it becomes a click-to-cycle pill like
   its neighbours, and drops the colour so it matches them. Chore and the untyped "No Type" keep
   the plain pill colour. */
/* The Author field in the card editor: a plain labelled text box beside the pills. */
.projectAuthorInput input {
  margin-left: 6px;
  padding: 2px 10px;
}

.projectType.projectType-bug {
  color: var(--color-red-h);
}

.projectType.projectType-feature {
  color: var(--color-green-h);
}

.projectType.projectType-improvement {
  color: var(--color-blue-h);
}

.projectType.projectType-docs,
.projectType.projectType-research {
  color: var(--color-gold-h);
}

.project-done-btn .fa-check {
  color: var(--color-white-l);
}

.project-done-btn:hover .fa-check {
  color: var(--color-green);
}

/* Every other section hides its whole action row until the card is expanded (see
   .task-actions/.vault-cheat-actions above), but a board is meant to be rearranged without
   opening anything first — so the grab handle stays out on a collapsed card and only the rest of
   the row waits for .large. */
#projectsBoard .cheat .project-task-actions {
  display: block;
}

#projectsBoard .cheat:not(.large) .project-task-actions a:not(.project-drag-btn) {
  display: none;
}

.project-drag-btn {
  cursor: grab;
}

.project-drag-btn:active {
  cursor: grabbing;
}

.project-drag-btn .fa-arrows-alt:hover {
  color: var(--color-blue);
}

/* Columns can't sit side by side on a phone at any readable card width, so they stack and the
   board stops scrolling horizontally. */
@media screen and (max-width: 1000px) {
  html:not([data-viewport-mode=desktop]) .project-board {
    flex-direction: column;
    overflow-x: visible;
  }
  html:not([data-viewport-mode=desktop]) .project-column {
    width: 100%;
  }
}
html[data-viewport-mode=mobile] .project-board {
  flex-direction: column;
  overflow-x: visible;
}
html[data-viewport-mode=mobile] .project-column {
  width: 100%;
}

/* Time: private log of hours worked and what they earned, across a Log / Totals / Projects trio of
   tabs. Structurally the same page as Pennies — preset-field cards in a list, a tab row, filter
   pill rows and a roll-up panel — so it @extends those classes rather than restating them, the
   same way .project-tab does. Everything below is either a name of its own for one of those
   shared looks, or a genuinely new piece (the tally tiles, the breakdown table). */
#hoursBody {
  padding-top: 10px;
}

/* The View row carries the bottom margin in place of the inner tab row, so the two don't stack —
   same reasoning as #penniesViewRow, which this mirrors. */
#hoursViewRow {
  margin-bottom: 10px;
}

#hoursViewRow .hours-tabs {
  margin-bottom: 0;
}

/* Extending #penniesList also carries its "let an expanded preset-field card grow to fit its own
   content" rule (#penniesList .cheat.large .cheat-main) onto both of these lists, which is exactly
   what is wanted here and is why neither restates it. Same story for the three below: @extend
   applies at every selector the extended class appears in, so .hours-actions picks up its
   show-on-.large rule and .hoursDetails its hidden-until-expanded one for free. */
/* Empty-state / "no matches" copy inside a feed — spacing only. Multi-column feeds already
   force > p to span the row via .cheat-feed--two/--three. Written against #penniesList so Hours
   and Dues lists that @extend it inherit the same margin. */
#penniesList > p, #duesList > p,
#duesPayersList > p,
#duesServicesList > p,
#duesMethodsList > p, #hoursList > p,
#hoursProjectsList > p {
  margin: 0 0 10px;
}

/* What went wrong with a save, shown in the form rather than in an alert() the user has to
   dismiss before they can act on it. Same muted, italic aside shape as .hoursRateHint, in the
   site's error red. */
.hoursFormError {
  color: var(--color-red-h);
}

.hoursForm label {
  display: flex;
  flex-direction: column;
  color: var(--color-white-l);
  font-size: 0.85em;
  text-transform: uppercase;
}

.hoursForm input {
  margin-top: 3px;
}

.hoursForm select {
  margin-top: 3px;
}

/* Hours and minutes are one duration typed as two fields, so they sit on one line rather than
   stacking like every other field in the form. */
.hoursDurationRow {
  display: flex;
  gap: 8px;
}

.hoursDurationRow label {
  flex: 1;
}

/* The "leave blank for the project's rate" note and the live "this earns X" preview under the
   duration — same muted, italic aside treatment as .pennyOrderKindHint. */
.hoursEarnsPreview {
  color: var(--color-green);
}

/* Marks an entry logged at something other than its project's usual rate. Gold rather than the
   green/red the Pennies pills use: it is a flag worth noticing, not a good or bad outcome. */
.hoursOverride {
  color: var(--color-gold);
}

/* The five headline tallies. Same roll-up-panel treatment as .pennyTotalsPanel, wrapping to as
   many rows as the screen needs. */
.hoursTallyPanel {
  margin-bottom: 15px;
  padding: 12px 15px;
}

.hoursTallyPanel h2 {
  margin: 0 0 10px;
}

.hoursTallyFigures {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 30px;
}

/* Each tile is a period, its hours, and what those hours earned, stacked. The money is the
   headline figure of the three, so it is the one that carries the accent colour. */
.hoursTallyFigure {
  min-width: 120px;
}

.hoursTallyLabel {
  color: var(--color-white-l);
  font-size: 0.8em;
  text-transform: uppercase;
}

.hoursTallyHours {
  color: var(--color-white-h);
  font-size: 1.2em;
}

.hoursTallyMoney {
  color: var(--color-green);
}

/* Breakdown table under the tallies. Scrolls horizontally on a narrow screen for the same reason
   #penniesSummary does, rather than being clipped by #container's overflow-x. */
.hoursBreakdown {
  max-width: 100%;
  overflow-x: auto;
}

.hoursBreakdownTable {
  min-width: 520px;
}

/* An archived project: still fully readable and still counted in every total, just no longer
   something you log new time against. Dimmed rather than hidden or struck through, since the card
   is not cancelled, only filed away. */
.cheat.hoursArchived {
  opacity: 0.6;
}

.cheat.hoursArchived:hover {
  opacity: 1;
}

/* The Export and Timesheet Template tabs' one card each. Same persistent single-panel treatment as
   .duesTemplatePanel, which this extends for its dark card and its containment of the floated
   save/preview buttons. */
.hoursExportPanel .hoursFilters {
  margin-bottom: 0;
}

/* The template's multi-line blocks, the same shape as the Dues reminder letter's body. */
.hoursForm textarea {
  display: block;
  width: 100%;
  min-height: 90px;
  resize: vertical;
  font-family: inherit;
  margin-top: 3px;
  box-sizing: border-box;
}

/* A checkbox reads beside its label rather than under it like the other fields. */
.hoursForm label.hoursCheckboxRow {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

/* The tab's one action, labelled rather than icon-only so it cannot be missed. Green like an active
   pill rather than the site's default red link colour, which would read as a warning. */
.hoursExportDownload {
  color: var(--color-green);
}

.hoursExportDownload:hover {
  color: var(--color-green-h);
}

/* While a PDF is being built, so a second click does not queue a second download. */
.hoursExportDownload.busy {
  opacity: 0.4;
  pointer-events: none;
}

/* Same gold "worth noticing, neither good nor bad" treatment as .hoursOverride above. */
.hoursArchivedPill {
  color: var(--color-gold);
}

/* Dues: private record of money other people owe you, across a Due / Totals / Payers / Services
   quartet of tabs. Structurally the same page as Pennies and Hours again — preset-field cards in a
   list, a tab row, filter pill rows and a roll-up panel — so it @extends those rather than
   restating them. The genuinely new pieces here are the paid/unpaid/overdue status pills and the
   frozen treatment, since no other section has a state that changes on its own as a date passes. */
#duesBody {
  padding-top: 10px;
}

/* Same reasoning as #hoursViewRow and #penniesViewRow: the View row carries the bottom margin in
   place of the inner tab row, so the two don't stack. */
#duesViewRow {
  margin-bottom: 10px;
}

#duesViewRow .dues-tabs {
  margin-bottom: 0;
}

/* Ledger + sub-view lists extend #penniesList for expanded-card height and empty-state width. */
.duesFormError {
  color: var(--color-red-h);
}

/* Schedule hint on a service card — only once expanded, so collapsed three-up stays skim-sized. */
#duesServicesList .duesServiceHint {
  display: none;
}

#duesServicesList .cheat.large .duesServiceHint {
  display: block;
}

#duesList .duesDetails,
#duesList .duesForm {
  max-height: 620px;
}

.duesForm label {
  display: flex;
  flex-direction: column;
  color: var(--color-white-l);
  font-size: 0.85em;
  text-transform: uppercase;
}

.duesForm input {
  margin-top: 3px;
}

.duesForm select {
  margin-top: 3px;
}

.duesForm textarea {
  display: block;
  width: 100%;
  min-height: 160px;
  resize: vertical;
  font-family: inherit;
  margin-top: 3px;
  box-sizing: border-box;
}

/* A payment method's "Send it to" is usually a handful of short lines (account name, sort code,
   account number) rather than paragraphs, so it starts noticeably shorter than the reminder
   letter's body above — still resizable if somebody genuinely needs more room. */
.duesFieldMethodHandle {
  min-height: 70px;
}

/* An amount and its VAT rate are one price typed as two fields, so they share a line rather than
   stacking — same treatment as .hoursDurationRow. */
.duesAmountRow {
  display: flex;
  gap: 8px;
}

.duesAmountRow label {
  flex: 1;
}

/* The live "net + VAT = gross" readout under the amount, and the "next one falls due on ..." note
   on a service card. Same muted, italic aside as .pennyOrderKindHint. */
/* The live "sends to ..." readout under the payer editor's "Pay me by" picker, and the link beside
   it to the Payment Methods tab. Same muted aside as the hints above; the link gets the same plain
   clickable-text treatment .duesCycle/.duesSchedule get, just without their pill background.
   pre-line rather than the default normal, since a handle copied from a payment method can be a
   short multi-line block (account name, sort code, account number) rather than one line, and this
   is the one place that block should actually show as multiple lines rather than run together. */
.duesMethodHandleHint {
  white-space: pre-line;
}

.duesManageMethodsRow {
  margin: -6px 0 10px;
}

.duesManageMethodsLink {
  font-size: 0.85em;
  text-decoration: underline;
}

/* The same multi-line handle, wherever it's shown as read-only quick info: a payer's own "Pay me
   by" line and a payment method's own "Send it to" line. */
.duesPayerPay,
.duesMethodHandle {
  white-space: pre-line;
}

/* Cycle and schedule are click-to-cycle pills rather than dropdowns, the same lightweight
   treatment .taskDuration gets: a handful of fixed options, and a select would be heavier than the
   choice deserves. */
/* The status pill. Paid, unpaid and overdue is the one three-state thing in the app where the
   middle state is neutral rather than bad, so it follows .pennyStatus' base-pill-plus-colour shape
   with gold for waiting, green for settled and red for late. Overdue is derived from the date at
   read time (see dueSummary in routes/db/dues.js), never stored, so this pill can go red on its
   own between one page load and the next without anything having been written. */
.duesStatus.duesPaid {
  color: var(--color-green-h);
}

.duesStatus.duesUnpaid {
  color: var(--color-gold-h);
}

.duesStatus.duesOverdue {
  color: var(--color-red-h);
}

/* Frozen is red like overdue, because it is the consequence of it: this client has been switched
   off. Deliberately louder than .hoursArchivedPill's gold, since archiving files a finished client
   away while freezing stops billing a current one, and only one of those is a problem. */
.duesFrozenPill {
  color: var(--color-red-h);
}

/* A frozen payer or service card. Dimmed like an archived one but keeping its red pill at full
   strength, so the card reads as inactive while the reason stays legible. */
.cheat.duesFrozen {
  opacity: 0.6;
}

.cheat.duesFrozen:hover {
  opacity: 1;
}

.cheat.duesArchived {
  opacity: 0.6;
}

.cheat.duesArchived:hover {
  opacity: 1;
}

.duesArchivedPill {
  color: var(--color-gold);
}

/* The four headline balances: outstanding, overdue, due soon, settled this year. Same roll-up
   panel as .hoursTallyPanel and .pennyTotalsPanel. */
.duesTallyPanel {
  margin-bottom: 15px;
  padding: 12px 15px;
}

.duesTallyPanel h2 {
  margin: 0 0 10px;
}

.duesTallyFigures {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 30px;
}

.duesTemplatePanel, .hoursExportPanel {
  padding: 12px 15px;
  overflow: hidden;
}

.duesTemplatePreview {
  clear: both;
  margin-top: 12px;
  padding: 12px 15px;
  border-radius: 10px;
  background-color: var(--color-dark-b);
  max-height: 320px;
  overflow-y: auto;
}

.duesTemplatePreviewLabel {
  margin: 0 0 8px;
}

.duesTemplatePreviewSubject {
  font-weight: bold;
  margin: 0 0 8px;
}

.duesTemplatePreviewText {
  white-space: pre-wrap;
}

.duesTallyFigure {
  min-width: 140px;
}

.duesTallyLabel {
  color: var(--color-white-l);
  font-size: 0.8em;
  text-transform: uppercase;
}

.duesTallyMoney {
  color: var(--color-green);
  font-size: 1.2em;
}

.duesTallyCount {
  color: var(--color-white-l);
  font-size: 0.8em;
}

/* The overdue tile is the one nobody wants to be looking at, so it is the one that is red. */
.duesTallyFigure.duesTallyLate .duesTallyMoney {
  color: var(--color-red-h);
}

/* Per-payer breakdown under the balances. Scrolls horizontally on a narrow screen for the same
   reason #penniesSummary does, rather than being clipped by #container's overflow-x. */
.duesBreakdown {
  max-width: 100%;
  overflow-x: auto;
}

.duesBreakdownTable {
  min-width: 620px;
}

/* The freeze suggestion on an overdue payer's row: a plain sentence and a button, not a warning
   banner. Nothing freezes itself here, so this is an offer rather than a notification. */
.duesFreezeHint {
  color: var(--color-red-h);
}

/* Billing period (monthly/annual) toggle, same cycling-pill treatment as .taskDuration — used on
   /admin (choosing the period to apply on a Pro grant, an internal tool where the lightweight
   single-label treatment is fine). /billing's own picker is the segmented control below instead,
   since customers need both options and the current selection visible at a glance. */
/* /billing's monthly/annual picker — two clickable segments in a rounded pill, matching the dark
   card + green-accent language already used for the Pro tier card/border elsewhere on this page. */
.billingPeriodSegments {
  display: inline-flex;
  gap: 4px;
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-h);
  border-radius: 10px;
  padding: 4px;
  margin-bottom: 12px;
}

.billingPeriodOption {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: 7px;
  color: var(--color-white-l);
  cursor: pointer;
  white-space: nowrap;
}

.billingPeriodOption:hover {
  color: var(--color-white);
}

.billingPeriodOption.active {
  background-color: var(--color-green);
  color: var(--color-on-accent);
}

.billingPeriodOptionPrice {
  opacity: 0.8;
}

.billingPeriodBadge, .billingTierBadge {
  background-color: var(--color-dark-h);
  color: var(--color-white-h);
  font-size: 11px;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 6px;
}

/* "Recommended"/"Current Plan" flag on a tier card (billing.js swaps the text and which card
   it's shown on based on the signed-in user's actual tier) — same small uppercase pill as
   .billingPeriodBadge above, just green, instead of a one-off badge style. */
.billingTierBadge {
  background-color: var(--color-green);
  color: var(--color-on-accent);
  vertical-align: middle;
  margin-left: 6px;
}

/* Admin panel (/admin) — internal only, not linked anywhere. #adminTierToggle reuses
   .makePrivate/.makePublic directly for its clickable pill treatment, and a lookup result
   renders as a .pageSection card like the rest of the site. */
#adminSearchArea {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

/* Cookie consent banner (functions/views/partials/footer.ejs, driven by public/js/cookieConsent.js).
   Fixed to the bottom on every page until the visitor answers it, and reopened from the footer's
   Cookie Settings link afterwards. Sits below #globalTooltip's z-index so tooltips on its own two
   buttons still render over it. Accept and Refuse share .userButton so neither is styled as the
   easier choice. */
.cookieBanner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9000;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px 24px;
  padding: 16px 24px;
  background-color: var(--color-dark-m);
  border-top: 1px solid var(--color-dark-h);
  text-align: left;
}

/* [hidden] alone loses to the display:flex above, so the banner needs this to actually hide. */
.cookieBanner[hidden] {
  display: none;
}

.cookieBannerText {
  color: var(--color-white);
  margin: 0;
  max-width: 640px;
}

.cookieBannerActions {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Upgrade flow (public/js/billing.js): the withdrawal-right acknowledgement that has to be ticked
   before Stripe Checkout can be started, and the greyed-out state of the button until it is. */
#upgradeConsent {
  display: flex;
  align-items: flex-start;
  max-width: 480px;
  margin: 12px 0;
  cursor: pointer;
}

#upgradeConsent input {
  margin-top: 3px;
}

#upgradeBtn.upgradeBtnDisabled {
  opacity: 0.5;
  cursor: not-allowed;
}

#upgradeError {
  color: var(--color-red-h);
}

/* Dashboard: one card per view. The global `a` rule capitalises and paints links red,
   which would rewrite asset names and the figures, so the card opts out of both. */
.dashboard-intro {
  padding: 8px 16px 0;
}
.dashboard-intro h1 {
  margin: 0 0 4px;
  font-size: 22px;
  font-weight: normal;
  color: var(--color-white-h);
}
.dashboard-intro p {
  margin: 0;
  color: var(--color-white);
}

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
  padding: 12px 16px 28px;
}

a.dashboard-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 148px;
  padding: 14px 16px 16px;
  background-color: var(--color-dark);
  border: 1px solid var(--color-dark-h);
  color: var(--color-white);
  text-decoration: none;
  text-transform: none;
  box-sizing: border-box;
}
a.dashboard-card:hover, a.dashboard-card:focus-visible {
  border-color: color-mix(in srgb, var(--color-gold) 55%, var(--color-dark-h));
  color: var(--color-white);
  outline: none;
}
a.dashboard-card h2 {
  margin: 0;
  font-size: 16px;
  font-weight: normal;
  color: var(--color-white-h);
  text-transform: none;
}

.dashboard-kicker {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-white-l);
}

.dashboard-stat {
  margin: 0;
  font-size: 20px;
  line-height: 1.3;
  color: var(--color-white-h);
}

.dashboard-note,
.dashboard-list {
  margin: 0;
  color: var(--color-white);
  font-size: 13px;
  line-height: 1.4;
}

.dashboard-list {
  padding-left: 18px;
}

.dashboard-up {
  color: var(--color-green-h);
}

.dashboard-down {
  color: var(--color-red-h);
}
