/* The Projects calendar (`projects/calendar.rs`), on top of `projects.css`:
 * the card, the grid's look (Event Calendar's own variables, which live on
 * `.ec`), the shading, the week column, and the stage the image is made in.
 *
 * The shading is one hue in four steps, light and dark. Each step keeps the
 * day's number, in ink, at 4.5:1 or more on it (checked with the dataviz
 * validator's contrast(), 2026-10-25): light steps against #2b2420, dark
 * steps against #e8e9ec. The numbers carry the figure; the shading only
 * groups the days, and the legend under the grid says which step is which. */

/* --- The ramps ------------------------------------------------------------- */

[data-palette="green"] {
  --heat-l1: #d1f2d7; --heat-l2: #a7e2b2; --heat-l3: #7fd091; --heat-l4: #5bbd74;
  --heat-d1: #1c3723; --heat-d2: #1a4b28; --heat-d3: #10602d; --heat-d4: #0d7435;
}

[data-palette="blue"] {
  --heat-l1: #cfebff; --heat-l2: #a4d6ff; --heat-l3: #7dc0ff; --heat-l4: #59aaf8;
  --heat-d1: #1c3249; --heat-d2: #1a4268; --heat-d3: #125289; --heat-d4: #1263a6;
}

[data-palette="orange"] {
  --heat-l1: #ffe0c9; --heat-l2: #ffc298; --heat-l3: #f6a56d; --heat-l4: #e78a45;
  --heat-d1: #442916; --heat-d2: #5f330f; --heat-d3: #7c3c00; --heat-d4: #964700;
}

[data-palette="purple"] {
  --heat-l1: #efe0ff; --heat-l2: #dfc3ff; --heat-l3: #cca7f8; --heat-l4: #b98cea;
  --heat-d1: #362a45; --heat-d2: #4a3461; --heat-d3: #5e3d80; --heat-d4: #724a9b;
}

/* Added 2026-10-27, checked the same way: light steps 4.79:1 or more against
 * #2b2420, dark steps 4.83:1 or more against #e8e9ec. */
[data-palette="teal"] {
  --heat-l1: #cdf0ec; --heat-l2: #9fe0d8; --heat-l3: #6fcbc1; --heat-l4: #45b3a8;
  --heat-d1: #163634; --heat-d2: #134a46; --heat-d3: #0f5e58; --heat-d4: #0b716a;
}

[data-palette="red"] {
  --heat-l1: #ffd9d6; --heat-l2: #ffb3ac; --heat-l3: #f68a80; --heat-l4: #e66a5f;
  --heat-d1: #431c1c; --heat-d2: #5e1f1f; --heat-d3: #7a2222; --heat-d4: #962626;
}

[data-palette="gold"] {
  --heat-l1: #fbefc2; --heat-l2: #f6df8e; --heat-l3: #ecc95a; --heat-l4: #dcb030;
  --heat-d1: #3b3216; --heat-d2: #524316; --heat-d3: #64500f; --heat-d4: #7a5f0b;
}

[data-palette="gray"] {
  --heat-l1: #e6e6e6; --heat-l2: #cccccc; --heat-l3: #b0b0b0; --heat-l4: #959595;
  --heat-d1: #2b2d31; --heat-d2: #3a3d42; --heat-d3: #4b4f56; --heat-d4: #5e636b;
}

/* Dark by default, as the panel is; light on the paper theme and in a light
 * image. A palette swatch in Options takes the same steps. */
.cal-card,
.cal-inline,
.cal-palettes [data-palette] {
  --heat-1: var(--heat-d1); --heat-2: var(--heat-d2); --heat-3: var(--heat-d3); --heat-4: var(--heat-d4);
}

:root[data-theme="paper"] .cal-card,
:root[data-theme="paper"] .cal-inline,
:root[data-theme="paper"] .cal-palettes [data-palette] {
  --heat-1: var(--heat-l1); --heat-2: var(--heat-l2); --heat-3: var(--heat-l3); --heat-4: var(--heat-l4);
}

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

.cal-open button {
  min-height: 2rem;
}

.cal-head {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.cal-card .cal-title {
  margin: 0;
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

.cal-month {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* The calendar in the Writing card on a project's page
 * (`CalendarScreen::inline`): the month, the grid and its sentence, with
 * the card's own heading above. */
.cal-inline {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.cal-inline .cal-say {
  margin: 0;
}

/* The month, and the tick for what each day added at the far end. */
.cal-head-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem 1rem;
}

.cal-both {
  margin: 0;
}

/* The project's icon before the lines under the grid. */
.cal-say-icon {
  display: inline-flex;
  vertical-align: -0.2em;
  margin-inline-end: 0.35em;
}

.cal-say-icon svg {
  width: 1.2em;
  height: 1.2em;
}

/* Not the cards' small uppercase heading: here the month is the subject. */
.cal-card h2.cal-month-name,
.cal-inline h2.cal-month-name {
  margin: 0;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
}

button.cal-nav {
  min-width: 2rem;
  min-height: 2rem;
  padding: 0 0.5rem;
  font-size: 1.1rem;
  line-height: 1;
}

.cal-total,
.cal-goal {
  margin: 0;
  font-size: 0.88rem;
  color: var(--muted);
}

/* --- The grid -------------------------------------------------------------- */

.cal-host {
  min-width: 0;
}

.cal-host .ec {
  --ec-bg-color: var(--surface);
  --ec-border-color: var(--border);
  --ec-text-color: var(--ink);
  /* The browser's today is not the writer's: no day is marked. */
  --ec-today-bg-color: var(--surface);
  --ec-bg-event-opacity: 1;
  --ec-event-bg-color: transparent;
  --ec-event-text-color: var(--ink);
  color-scheme: inherit;
  font-size: 0.85rem;
}

.cal-host .ec-col-head {
  padding: 0.3rem 0;
  font-size: 0.78rem;
  color: var(--muted);
  text-align: center;
}

.cal-host .ec-day {
  min-block-size: 3.6em;
}

.cal-host .ec-day-head {
  padding: 0.2rem 0.3rem;
  font-size: 0.72rem;
  color: var(--muted);
  position: relative;
  z-index: 1;
}

/* Only the month's own days. */
.cal-host .ec-other-month .ec-day-head {
  visibility: hidden;
}

.cal-host .ec-other-month {
  --ec-day-bg-color: var(--paper);
}

/* A week has no other month: the calendar marks the days past the month
 * its first day is in as if it did. */
.cal-host[data-period="week"] .ec-other-month .ec-day-head {
  visibility: visible;
}

.cal-host[data-period="week"] .ec-other-month {
  --ec-day-bg-color: var(--ec-bg-color);
}

/* A day's number: the figure, centered in its square. */
.cal-host .ec-event:not(.ec-bg-event) {
  background: none;
  box-shadow: none;
  inline-size: 100%;
  justify-content: center;
  padding: 0;
  margin-block-end: 0.25rem;
  font-size: 1em;
  font-weight: 600;
  pointer-events: auto;
}

/* In the middle of the day's square, circle or leaf, which fills the cell,
 * rather than under the date, where the calendar puts it with an inline
 * margin (owner, 2026-10-30). */
.cal-host .ec-event:not(.ec-bg-event) {
  align-self: center;
  margin-block: 0 !important;
}

.cal-host .ec-event-body {
  justify-content: center;
  align-items: center;
}

.cal-host .ec-event-title {
  position: static;
  min-block-size: 0;
}

.cal-n {
  display: inline-flex;
  align-items: center;
  gap: 0.15em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* What the day added over the total (owner, 2026-10-30): right aligned in
 * tabular figures so the digits line up, the total bold, the amount added
 * in the normal weight. */
.cal-stack {
  display: inline-grid;
  justify-items: end;
  line-height: 1.15;
}

.cal-add {
  display: inline-flex;
  align-items: center;
  gap: 0.15em;
  font-weight: 400;
  font-size: 0.85em;
}

.cal-tot {
  font-weight: 700;
}

.cal-check {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}

/* The check with no number beside it (numbers hidden): the square's one
 * mark, so larger and in the middle. */
.cal-n.is-alone {
  inline-size: 100%;
  justify-content: center;
}

.cal-n.is-alone .cal-check {
  width: 1.9em;
  height: 1.9em;
}

/* A shaded day: its square inset a little, so two shaded days beside each
 * other still read as two. Specific enough to win over the calendar's own
 * `.ec-bg-event` color, which loads after this file. */
.cal-host .ec-bg-event {
  margin: 2px;
  border-radius: 6px;
}

/* The image's squares are bigger, so their corners are. */
.cal-export .cal-host .ec-bg-event {
  border-radius: 12px;
}

.cal-export.is-wide .cal-host .ec-bg-event {
  border-radius: 8px;
}

.cal-heat-1,
.cal-host .ec-bg-event.cal-heat-1 { background-color: var(--heat-1); }
.cal-heat-2,
.cal-host .ec-bg-event.cal-heat-2 { background-color: var(--heat-2); }
.cal-heat-3,
.cal-host .ec-bg-event.cal-heat-3 { background-color: var(--heat-3); }
.cal-heat-4,
.cal-host .ec-bg-event.cal-heat-4 { background-color: var(--heat-4); }

/* The week totals: an eighth column of the calendar's own grid, put there by
 * the page (`projects-calendar.js`). */
.cal-host.has-weeks .ec-day-grid .ec-main {
  grid-template-columns: repeat(7, minmax(0, 1fr)) minmax(3.2em, 1.05fr);
}

/* Unlike a day: no square, set off by a thicker rule, muted and in the
 * normal weight, so it reads as a sum beside the days and not as an eighth
 * day or one more total of the same kind (owner, 2026-10-30). */
.cal-week {
  grid-column: 8;
  display: flex;
  align-items: center;
  justify-content: center;
  border-block-end: 1px solid var(--ec-border-color);
  border-inline-start: 3px solid var(--ec-border-color);
  background: none;
  color: var(--muted);
  font-weight: 400;
  font-size: 0.9em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  padding: 0 0.2rem;
}

.ec-header .cal-week {
  grid-row: 1;
  font-weight: 500;
  font-size: 0.72rem;
  color: var(--muted);
  padding: 0.3rem 0.1rem;
  white-space: normal;
  text-align: center;
  line-height: 1.1;
}

@container panel (max-width: 26rem) {
  .cal-host .ec {
    font-size: 0.72rem;
  }

  /* A five-figure total, "14,097" in bold, is wider than a phone's square
   * (about 40px): a little smaller and tighter, so neighbours don't touch. */
  .cal-host .cal-n {
    font-size: 0.9em;
    letter-spacing: -0.03em;
  }

  /* A phone's squares are too short to centre a number clear of the date:
   * at the foot. */
  .cal-host .ec-event:not(.ec-bg-event) {
    align-self: end;
    margin-block-end: 0.2rem !important;
  }
}

/* --- What the grid shows, as the options have it (`grid_classes`) ---------- */

.no-dates .cal-host .ec-day-head,
.no-dates .cal-host[data-period="week"] .ec-other-month .ec-day-head {
  visibility: hidden;
}

.no-weekdays .cal-host .ec-header {
  display: none;
}

/* Corners: the shaded squares lose their rounding. (Not `.is-square`: that
 * is the 1080 x 1080 image's own class, which would square every corner of
 * it.) */
.square-corners .cal-host .ec-bg-event {
  border-radius: 0;
}

/* The date in the corner of a day on the two darkest steps: in the ink the
 * day's number has, 4.7:1 or more on every ramp. The muted color came out
 * under 3:1 there (2.1:1 on Paper's red, 2.2:1 on Ink's green), which read as
 * faint (owner, 2026-10-30). The lighter steps keep the muted color, 3.6:1 or
 * more. `cal-day-s-N` is put on the day by `projects-calendar.js`. The
 * designs set their own date colors in `projects-calendar-designs.css`. */
.cal-host .ec-day.cal-day-s-3 .ec-day-head,
.cal-host .ec-day.cal-day-s-4 .ec-day-head {
  color: var(--ink);
}

/* The writer's today (`data-today`): its date in a filled circle, as a
 * wall calendar marks it, so it is told apart from the best day's ring. */
.cal-host .ec-day.cal-today .ec-day-head {
  visibility: visible;
}

.cal-host .ec-day.cal-today .ec-day-head time,
.cal-host .ec-day.cal-today .ec-day-head > * {
  display: inline-block;
  min-width: 1.6em;
  padding: 0.05em 0.3em;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  text-align: center;
  font-weight: 600;
}

/* The best day: a ring around its square. */
.cal-host .ec-day.cal-best {
  box-shadow: inset 0 0 0 2px var(--ink);
}

/* --- A year (`calendar_view/year.rs`) --------------------------------------- */

/* Twelve small months, drawn by the server: shading only. Three across on
 * the page; the image sets its own grid for its size, below. */
.cal-year {
  --year-cols: 3;
  display: grid;
  grid-template-columns: repeat(var(--year-cols), minmax(0, 1fr));
  gap: 0.9em 1.1em;
  font-size: 0.8rem;
}

@container panel (max-width: 26rem) {
  .cal-year {
    --year-cols: 2;
  }
}

/* `--head` is what the name and the weekday row take, for the image's
 * squares to fit under them (`.cal-export .cal-ym`). */
.cal-ym {
  --head: 3em;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cal-ym-name {
  align-self: stretch;
  margin: 0 0 0.25em;
  font-weight: 600;
  line-height: 1.3;
}

.cal-ym-head,
.cal-ym-days {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
  width: 100%;
}

.cal-ym-head span {
  font-size: 0.75em;
  line-height: 1.5;
  color: var(--muted);
  text-align: center;
}

.no-weekdays .cal-ym-head {
  display: none;
}

.no-weekdays .cal-ym {
  --head: 1.6em;
}

/* An empty day is a plain square, so the month keeps its shape; the
 * shading is a layer over it (`.cal-yd-fill`), which the animation hides
 * until its day. */
.cal-yd {
  position: relative;
  aspect-ratio: 1;
  border-radius: 3px;
  background: var(--surface-2);
}

.cal-yd.is-blank {
  background: none;
}

/* Days after today, still to come. */
.cal-yd.is-ahead {
  opacity: 0.45;
}

.cal-yd-fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.square-corners .cal-yd {
  border-radius: 0;
}

/* The best day's ring, over its shading; today in the accent, outside the
 * square, so a day can be both. */
.cal-yd.cal-best::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 2px var(--ink);
}

.cal-yd.cal-today {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.is-anim:not(.is-anim-done) .cal-yd.cal-best::after {
  box-shadow: none;
}

/* Fonts, on the image and the card it is made from. */
.cal-card[data-font="serif"] {
  font-family: var(--font-serif);
}

.cal-card[data-font="mono"] {
  font-family: var(--font-mono);
}

/* The month's total as a big number, and the bar toward the month goal. */
.cal-big {
  margin: 0.1em 0 0;
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.cal-progress {
  display: flex;
  flex-direction: column;
  gap: 0.3em;
  margin-top: 0.2em;
}

.cal-progress-bar {
  height: 0.6em;
  min-height: 8px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  overflow: hidden;
}

.cal-progress-fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--heat-4);
}

.cal-progress-say {
  margin: 0;
  font-size: 0.88rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.cal-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2em 1.2em;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.88rem;
}

/* The figures as a table of labels and values, no rules (owner,
 * 2026-10-30): the labels muted, the values lined up in a column after
 * them. Two columns of pairs, filled row by row, or one. */
.cal-stats-table {
  display: grid;
  grid-template-columns: max-content max-content;
  gap: 0.15em 0.8em;
  align-content: start;
}

.cal-stats-table.is-two {
  grid-template-columns: max-content max-content max-content max-content;
  column-gap: 0.8em;
}

.cal-stats-table.is-two > div:nth-child(even) dt {
  padding-inline-start: 1.2em;
}

.cal-stats-table > div {
  display: contents;
}

.cal-stats-table dt {
  color: var(--muted);
}

.cal-stats-table dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.cal-credit {
  margin: 0;
  font-size: 0.78rem;
  color: var(--muted);
  text-align: right;
}

/* The animation (`projects-calendar.js`): days after the one on screen are
 * not drawn yet, and what states the finished month waits for the end. */
.is-anim .cal-host .is-later {
  visibility: hidden;
}

/* The week column too, its head with it: an empty "Week" column read as
 * missing figures. */
.is-anim:not(.is-anim-done) .cal-anim-late,
.is-anim:not(.is-anim-done) .cal-week {
  visibility: hidden;
}

.is-anim:not(.is-anim-done) .cal-host .ec-day.cal-best {
  box-shadow: none;
}

/* --- The options' extra rows ------------------------------------------------- */

.cal-presets {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.75rem;
}

.cal-presets-say {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--muted);
}

/* The ticks for what the image shows: two columns where the panel has room. */
.cal-ticks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: 0.5rem 0.9rem;
}

/* The month goal, under the progress bar's tick it belongs to. */
.cal-sub {
  margin: -0.3rem 0 0 1.7rem;
}

/* --- The legend and the rest ------------------------------------------------ */

.cal-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.75rem;
  font-size: 0.8rem;
  color: var(--muted);
}

.cal-legend ol {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.cal-legend li {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.cal-swatch-tick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
}

.cal-swatch-tick .cal-check {
  width: 100%;
  height: 100%;
}

/* The project's icon, in the colour of the title, inline with its first
 * line: a long title wraps under the icon (owner, 2026-10-30). */
.cal-card .cal-title {
  display: block;
}

.cal-icon {
  display: inline-flex;
  flex: none;
  vertical-align: -0.15em;
  margin-inline-end: 0.3em;
}

/* About the height of the title's letters, so the line it sits in is no
 * taller than the others. */
.cal-icon svg {
  width: 1.05em;
  height: 1.05em;
}

.cal-swatch {
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  border: 1px solid var(--border);
  border-radius: 2px;
  vertical-align: -0.12em;
}

.cal-fields {
  border: none;
  margin: 0;
  padding: 0;
}

.cal-fields legend {
  padding: 0;
  margin-bottom: 0.2rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--muted);
}

.cal-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1rem;
}

.cal-row legend {
  width: 100%;
}

.cal-goal-box {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.cal-goal-box input {
  width: 7rem;
}

.cal-list table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

.cal-list th,
.cal-list td {
  padding: 0.25rem 0.4rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
}

.cal-list .num {
  text-align: right;
}

.cal-image-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
}

.cal-image-fields .field {
  flex: 1 1 14rem;
  min-width: 0;
}

.cal-image select {
  width: 100%;
  min-height: 2.4rem;
  padding: 0.45rem 0.6rem;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
}

.cal-image-say:empty {
  display: none;
}

/* Download and Copy on the website; in the Lounge, Send to DMs and the line
 * saying where the website's buttons are. `!important` over the display
 * the buttons' own rules give them. */
body:not(.lounge-web) .cal-image [data-web-only],
body.lounge-web .cal-image [data-lounge-only],
body.lounge-web .cal-in-discord {
  display: none !important;
}

/* The website's address in that line, as a link. */
.cal-in-discord a {
  color: var(--link);
}

/* --- The calendar image screen --------------------------------------------- */

/* The image on the left, its options on the right (`CalendarScreen::render`;
 * owner, 2026-10-27: the options were a closed fold under the calendar, far
 * from what they change). The left column runs the options' height, so the
 * image can stay in view while they scroll. */
.cal-editor {
  display: grid;
  /* 23rem holds "Wide, 1200 × 630 (Bluesky, X, Facebook)" uncut. */
  grid-template-columns: minmax(0, 1fr) minmax(16rem, 23rem);
  gap: 1rem 1.25rem;
}

.cal-editor-view {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-width: 0;
}

/* Under the strip with Back, which is held at the top as well. */
.cal-editor-stick {
  position: sticky;
  top: 3.25rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* Solid, so the sentence and list that scroll under it do not show
   * through beside a narrow image. */
  padding-bottom: 0.5rem;
  background: var(--paper);
}

/* The buttons over the image only: the image's own month line stays where
 * the image puts it. */
.cal-editor-stick > .cal-month {
  justify-content: center;
}

.cal-editor-stick > .cal-month h2.cal-month-name {
  margin: 0;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
}

/* The image at its own size, scaled to the room (`--fit`, set by
 * `projects-calendar.js`, which also sets the box's height). */
.cal-preview {
  position: relative;
  width: 100%;
  /* A square or story image as wide as the column would be taller than the
   * screen, with the month, the caption and the buttons pushed out of it. */
  max-height: calc(100vh - 17rem);
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.cal-export.is-preview {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  transform: scale(var(--fit, 1));
}

.cal-preview-say {
  margin: 0;
  text-align: center;
}

.cal-image-acts {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}

.cal-image-acts .proj-btns {
  justify-content: center;
}

/* The card the image is made from: off the screen on the website, laid out
 * at a card's width; in the Lounge, where there is no image, it is the
 * calendar on screen. */
.cal-source {
  position: fixed;
  left: -30000px;
  top: 0;
  width: 40rem;
}

body:not(.lounge-web) .cal-source {
  position: static;
  width: auto;
}

body:not(.lounge-web) .cal-preview,
body:not(.lounge-web) .cal-preview-say {
  display: none;
}

.cal-side {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-width: 0;
}

.cal-group {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-width: 0;
  margin: 0;
  padding: 0.75rem 0.85rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.cal-group > legend {
  padding: 0 0.3rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.cal-group .field {
  margin: 0;
}

/* Wider than the other screens' 58rem where there is room: at 58rem the
 * image beside the options came out about half its width, its numbers too
 * small to read. */
@container panel (min-width: 62rem) {
  #activity-root:has(.cal-editor) {
    max-width: 76rem;
  }
}

/* One column on a narrow panel: the image first, held at the top in a third
 * of the screen's height while the options scroll under it. */
@container panel (max-width: 44rem) {
  .cal-editor {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The image's column is unwrapped so the held image belongs to the whole
   * screen, options and all; the sentence and the list go last. */
  .cal-editor-view {
    display: contents;
  }

  .cal-editor > .cal-side {
    order: 1;
  }

  .cal-editor .cal-say,
  .cal-editor .cal-list {
    order: 2;
  }

  .cal-editor-stick {
    top: 2.8rem;
    padding: 0.4rem 0 0.5rem;
    background: var(--paper);
  }

  /* With the month above and four buttons under it, the held block stays
   * under half the screen. The size and colors line is left to the Image
   * options right under it. */
  .cal-preview {
    max-height: 26vh;
  }

  .cal-preview-say {
    display: none;
  }

  .cal-image-acts .proj-btns {
    gap: 0.35rem;
  }

  .cal-image-acts .proj-btns button {
    min-height: 2.1rem;
    padding: 0.3rem 0.6rem;
    font-size: 0.85rem;
  }
}

/* --- The image ------------------------------------------------------------- */

/* The stage the image is made in: off the screen but laid out, at the
 * image's own size, in its own colors whatever the page's are. */
.cal-export {
  position: fixed;
  left: -30000px;
  top: 0;
  box-sizing: border-box;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  color: var(--ink);
  font-family: "Jost", var(--font-sans);
  line-height: 1.3;
}

.cal-export.is-light {
  --paper: #f6f0e4;
  --surface: #fdfaf2;
  --surface-2: #efe7d6;
  --ink: #2b2420;
  --muted: #665b4b;
  --border: #e2d7c2;
}

.cal-export.is-dark {
  --paper: #11151c;
  --surface: #181e28;
  --surface-2: #202835;
  --ink: #e8e9ec;
  --muted: #98a2b3;
  --border: #2c3544;
}

/* The other dark themes, as `tokens.css` has them (Settings, Colors); Ink is
 * `is-dark` itself. */
.cal-export.is-theme-charcoal {
  --paper: #17181a; --surface: #202124; --surface-2: #292a2e;
  --ink: #ece8e1; --muted: #a5a39f; --border: #36383d;
}

.cal-export.is-theme-terracotta {
  --paper: #1c1813; --surface: #26201a; --surface-2: #2f2820;
  --ink: #efe6d6; --muted: #a99d89; --border: #3a3128;
}

.cal-export.is-theme-forest {
  --paper: #121a16; --surface: #19241f; --surface-2: #212e28;
  --ink: #e9ebe3; --muted: #9daca3; --border: #2d3d35;
}

.cal-export.is-theme-plum {
  --paper: #18141d; --surface: #211c28; --surface-2: #2a2433;
  --ink: #eee7ee; --muted: #aaa0b4; --border: #383043;
}

/* `--bad` is the chart's bars for days that lowered the count
 * (`projects.js`), as `tokens.css` has it for light and dark, so the image
 * is the same whatever the site's own colors are. A design sets its own
 * (`projects-calendar-designs.css`). */
.cal-export.is-light {
  --accent: #b94a25;
  --on-accent: #fff;
  --bad: #a33c26;
}

.cal-export.is-dark {
  --accent: #e0653a;
  --on-accent: #1b1410;
  --bad: #d9776a;
}

.cal-export.is-light .cal-card {
  --heat-1: var(--heat-l1); --heat-2: var(--heat-l2); --heat-3: var(--heat-l3); --heat-4: var(--heat-l4);
}

.cal-export.is-dark .cal-card {
  --heat-1: var(--heat-d1); --heat-2: var(--heat-d2); --heat-3: var(--heat-d3); --heat-4: var(--heat-d4);
}

.cal-export.is-square {
  width: 1080px;
  height: 1080px;
  padding: 64px 64px 56px;
  font-size: 24px;
}

.cal-export.is-wide {
  width: 1200px;
  height: 630px;
  padding: 40px 44px;
  font-size: 18px;
}

.cal-export.is-portrait {
  width: 1080px;
  height: 1350px;
  padding: 72px 64px 64px;
  font-size: 25px;
}

/* A story: the apps draw their own bars over the top and bottom 250 px or
 * so, which the padding keeps clear. */
.cal-export.is-story {
  width: 1080px;
  height: 1920px;
  padding: 260px 64px 280px;
  font-size: 26px;
}

.cal-export .cal-big {
  font-size: 2.6em;
}

.cal-export .cal-progress-say {
  font-size: 0.85em;
}

/* `--fit-stats` is under 1 when the figures are wider than their room, as
 * in Wide's 300px column with a long value in Typewriter (`fitText` in
 * `projects-calendar.js`). */
.cal-export .cal-stats {
  font-size: calc(0.85em * var(--fit-stats, 1));
}

/* `--fit-side` is under 1 when the title, the figures and the key are taller
 * than the image, as in Wide with a long title and every figure on: the
 * card's text shrinks to fit, and the grid keeps its own size. */
.cal-export .cal-card {
  font-size: calc(1em * var(--fit-side, 1));
}

.cal-export .cal-host {
  font-size: calc(1em / var(--fit-side, 1));
}

/* In the image's bottom right corner, over the margin, so it takes no row
 * of the layout and moves nothing when ticked (owner, 2026-10-30).
 * `--credit-bottom` keeps a story's clear of the apps' own bars. */
.cal-export .cal-credit {
  position: absolute;
  right: var(--credit-side, 64px);
  bottom: var(--credit-bottom, 18px);
  font-size: calc(0.7em / var(--fit-side, 1));
}

.cal-export.is-wide {
  --credit-side: 44px;
  --credit-bottom: 12px;
}

.cal-export.is-portrait {
  --credit-bottom: 22px;
}

.cal-export.is-story {
  --credit-bottom: 236px;
}

.cal-export .cal-card {
  flex: 1;
  min-height: 0;
  border: none;
  border-radius: 0;
  padding: 0;
  background: transparent;
  gap: 0.8em;
}

.cal-export .cal-title {
  font-size: 2.2em;
}

.cal-export .cal-card h2.cal-month-name {
  font-size: 1.35em;
}

.cal-export .cal-total,
.cal-export .cal-goal,
.cal-export .cal-legend {
  font-size: 0.85em;
}

.cal-export .cal-host {
  flex: 1;
  min-height: 0;
}

.cal-export .cal-host .ec {
  font-size: 0.9em;
}

/* The rows share the stage's height between them. Nothing scrolls in an
 * image: the calendar's own `overflow: auto` drew scroll bars into it
 * where the image's fonts came out a pixel taller than the stage's. */
.cal-export .ec-day-grid .ec-main {
  --ec-row-height: minmax(0, 1fr);
  flex-grow: 1;
  overflow: hidden;
}

.cal-export .ec-day-head {
  font-size: 0.75em;
}

/* Wide: the title, the figures and the legend in a column on the left, the
 * grid on the right. */
.cal-export.is-wide .cal-card {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  column-gap: 36px;
}

/* The month stands apart from the title and the figures; the total and
 * goal lines sit together under it, as on the page. */
.cal-export.is-wide .cal-head {
  grid-column: 1;
  grid-row: 1;
  gap: 0.15em;
}

.cal-export.is-wide .cal-month {
  margin-block: 0.25em;
}

.cal-export.is-wide .cal-title {
  font-size: 1.9em;
}

.cal-export.is-wide .cal-host {
  grid-column: 2;
  grid-row: 1 / 4;
}

.cal-export.is-wide .cal-legend {
  grid-column: 1;
  grid-row: 3;
}

/* The figures under the head, at the foot of the left column; the credit
 * under the key. The grid runs the whole height beside them. */
.cal-export.is-wide .cal-card {
  grid-template-rows: auto 1fr auto auto;
}

.cal-export.is-wide .cal-host {
  grid-row: 1 / 5;
}

.cal-export.is-wide .cal-stats {
  grid-column: 1;
  grid-row: 2;
  align-self: end;
  flex-direction: column;
}

/* The left column is too narrow for two pairs side by side. A value that
 * is still too wide at the smallest `--fit-stats` wraps inside the column
 * instead of running under the grid. */
.cal-export.is-wide .cal-stats-table,
.cal-export.is-wide .cal-stats-table.is-two {
  grid-template-columns: max-content minmax(0, 1fr);
}

.cal-export.is-wide .cal-stats-table.is-two > div:nth-child(even) dt {
  padding-inline-start: 0;
}


.cal-export.is-wide .cal-big {
  font-size: 2.2em;
}

/* A week in the image: its one row, as tall as its squares are wide
 * (`buildStage` in `projects-calendar.js`), in the middle of the room the
 * grid has. */
.cal-export .cal-host[data-period="week"] {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* A year in the image: 4 × 3 on Square and Wide, 3 × 4 on Portrait and
 * Story, the months sharing the room the grid has. Each month's squares
 * are as big as both its width and its height allow (`container-type`),
 * for six weeks under its name and weekday row, so every month's squares
 * are the same size. Wide has no room for the weekday row. */
.cal-export .cal-year {
  --year-cols: 4;
  grid-template-rows: repeat(3, minmax(0, 1fr));
  gap: 0.7em 1.2em;
  font-size: 0.8em;
}

/* Story too: the design note's 2 × 6 left each month about 110px wide,
 * held down by its sixth of the height; 3 × 4 doubles its squares. */
.cal-export.is-portrait .cal-year,
.cal-export.is-story .cal-year {
  --year-cols: 3;
  grid-template-rows: repeat(4, minmax(0, 1fr));
}

.cal-export .cal-ym {
  container-type: size;
}

.cal-export .cal-ym-head,
.cal-export .cal-ym-days {
  width: min(100cqw, calc((100cqh - var(--head) - 12px) * 7 / 6));
}

.cal-export.is-wide .cal-ym-head {
  display: none;
}

.cal-export.is-wide .cal-ym {
  --head: 1.6em;
}

.cal-export .cal-ym-name {
  text-align: center;
}

/* The chart picture (`calendar_view/chart_card.rs`): on its card in the
 * Lounge, a little taller than the Writing card's chart; in the image, the
 * room the title and the figures leave, as the grid has (`.cal-host`). */
.cal-card .chart-host {
  position: relative;
  height: 14rem;
}

.cal-card .chart-host canvas {
  display: block;
  max-width: 100%;
}

.cal-export .cal-card .chart-host {
  height: auto;
}
/* The calendar image's designs (`calendar::THEMES`, owner 2026-10-29:
 * "design themes that feel more like cohesive genuine graphic design
 * themes"). Joined after `projects-calendar.css`, so where a rule ties with
 * the stage's own, the design's wins.
 *
 * Each design is one idea taken from a field's own work, carried through
 * the background, the type, the shading and the squares:
 *
 *   Risograph    two spot inks on cream stock, fluorescent pink and blue,
 *                a halftone texture and an off-register total;
 *   Swiss style  the International Typographic Style: white, black, one
 *                red; flush-left, a strong scale between month, title and
 *                figures, a heavy rule, a plain square grid;
 *   Night sky    a deep navy night, a thin gold frame, gold type accents,
 *                the days as violet dots that grow with the day's words;
 *   Graph paper  a notebook: blue grid, red margin, pen-navy ink, the days
 *                and the title marked in highlighter;
 *   Sunset       a warm gradient, white type, translucent tiles;
 *   Sage leaves  sage stock, deep green ink, terracotta accents, the days
 *                as leaves.
 *
 * Only Jost is embedded in the image (html-to-image takes the page's
 * `@font-face` fonts, and the serif and mono stacks are whatever the
 * reader's machine has), so the designs set themselves apart by weight,
 * case, size and spacing, and keep Jost whatever the Font option says.
 *
 * Every shading step keeps the day's number at 4.5:1 or more against it:
 * where a design's ink falls under that on its darkest steps, the number
 * takes the design's light color there instead (`.cal-n.cal-s-N`, the step
 * under the number, from `projects-calendar.js`). The ratios are noted
 * beside each ramp. The date in a day's corner follows the number on the
 * two darkest steps (`.ec-day.cal-day-s-N .ec-day-head`, in
 * `projects-calendar.css`), and on every step in Sunset. Night sky's dots
 * and Sage's leaves leave the corner clear, so their dates stay muted on
 * the background (measured on the PNG: 6.6:1 and 5.1:1 or more). */

/* --- What every design shares ---------------------------------------------- */

/* The design's own font, over the Font option. */
.cal-export.is-design .cal-card {
  font-family: "Jost", var(--font-sans);
}

/* The design's background shows through the grid: no filled calendar, no
 * filled days from the months either side. */
.cal-export.is-design .cal-host .ec {
  --ec-bg-color: transparent;
  --ec-day-bg-color: transparent;
  --ec-today-bg-color: transparent;
}

.cal-export.is-design .cal-host .ec-other-month {
  --ec-day-bg-color: transparent;
}

/* No grid lines, but where a design draws its own. */
.cal-export.is-design:not(.is-theme-swiss) .cal-host .ec {
  --ec-border-color: transparent;
}

.cal-export.is-design .cal-host .ec-col-head {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.68em;
  font-weight: 500;
}

.cal-export.is-design .cal-week {
  border: none;
  border-radius: 0.5em;
  margin: 2px;
}

.cal-export.is-design .ec-header .cal-week {
  background: none;
}

/* The squares stand apart a little more than on the site's colors. Their
 * shape is the design's, whatever the Corners option says (greyed under a
 * design): each design sets its own radius below. */
.cal-export.is-design .cal-host .ec-bg-event {
  margin: 3px;
}

/* A dot or a leaf leaves the square's corner clear, so the date there is on
 * the background, not on the shading: it keeps the muted color on every
 * step, as on a day with nothing added. */
.cal-export.is-theme-midnight .cal-host .ec-day:is(.cal-day-s-3, .cal-day-s-4) .ec-day-head,
.cal-export.is-theme-garden .cal-host .ec-day:is(.cal-day-s-3, .cal-day-s-4) .ec-day-head {
  color: var(--muted);
}

/* --- Risograph ------------------------------------------------------------- */

.cal-export.is-theme-riso {
  --paper: #f3ede2;
  --surface: #f3ede2;
  --surface-2: #e8dfcf;
  /* A blue deep enough for the number on the pink squares. */
  --ink: #1a3580;
  --muted: #4f5f96;
  --border: #d8ccb8;
  --accent: #e6007e;
  --on-accent: #ffffff;
  /* The chart's bars for days that lowered the count (`projects.js`): the
   * second ink, 9.7:1 on the stock. */
  --bad: #1a3580;
  --riso-pink: #f0389a;
  /* Two halftone screens a dot apart, one in each ink, over cream stock. */
  background:
    radial-gradient(rgba(26, 53, 128, 0.07) 1.2px, transparent 1.5px) 0 0 / 9px 9px,
    radial-gradient(rgba(240, 56, 154, 0.07) 1.2px, transparent 1.5px) 4.5px 4.5px / 9px 9px,
    #f3ede2;
}

/* Pink in four tints, the full ink last. Against the blue ink: 9.0, 7.0
 * and 5.1:1; the full pink takes a white number, 4.5:1. */
.cal-export.is-theme-riso .cal-card {
  --heat-1: #ffdcee;
  --heat-2: #ffb6da;
  --heat-3: #ff86c1;
  --heat-4: #e6007e;
}

.cal-export.is-theme-riso .cal-n.cal-s-4,
.cal-export.is-theme-riso .cal-host .ec-day.cal-day-s-4 .ec-day-head {
  color: #ffffff;
}

/* Under the total in size, so the figure leads (a reviewer found the title
 * in capitals outweighed it). */
.cal-export.is-theme-riso .cal-title {
  font-size: 1.7em;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.05;
}

.cal-export.is-theme-riso .cal-card h2.cal-month-name {
  color: var(--riso-pink);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 700;
}

/* The total printed in pink with the blue plate a little off register. */
.cal-export.is-theme-riso .cal-big {
  color: var(--riso-pink);
  text-shadow: 0.05em 0.05em 0 var(--ink);
  letter-spacing: -0.01em;
}

.cal-export.is-theme-riso .cal-host .ec-col-head {
  color: var(--ink);
  font-weight: 700;
}

/* Each square printed through a halftone screen, as the riso's ink is. */
.cal-export.is-theme-riso .cal-host .ec-bg-event {
  border-radius: 10px;
  background-image: radial-gradient(rgba(255, 255, 255, 0.22) 1.1px, transparent 1.5px);
  background-size: 7px 7px;
}

/* The week totals in the paper's own tint, the blue ink for the figure: a
 * quiet column beside the days, not the heaviest thing on the page. */
.cal-export.is-theme-riso .cal-week {
  background: var(--surface-2);
  color: var(--ink);
}

.cal-export.is-theme-riso .ec-header .cal-week {
  background: none;
}

.cal-export.is-theme-riso .cal-progress-bar {
  background: #ffdcee;
  border-color: var(--riso-pink);
}

.cal-export.is-theme-riso .cal-progress-fill {
  background: var(--riso-pink);
}

/* --- Swiss style ----------------------------------------------------------- */

.cal-export.is-theme-swiss {
  --paper: #f1f1ef;
  --surface: #ffffff;
  --surface-2: #f1f1ef;
  --ink: #111111;
  --muted: #555555;
  --border: #111111;
  --accent: #e30613;
  --on-accent: #ffffff;
  /* The chart's bars for days that lowered the count: gray beside the red
   * ones, 7.5:1 on white. */
  --bad: #555555;
  background: #ffffff;
}

/* Red tints, then the red itself. Against black: 15.7, 11.8 and 8.3:1; the
 * red takes a white number, 4.9:1. */
.cal-export.is-theme-swiss .cal-card {
  --heat-1: #ffe4e4;
  --heat-2: #ffbcbc;
  --heat-3: #ff8a8a;
  --heat-4: #e30613;
}

.cal-export.is-theme-swiss .cal-n.cal-s-4,
.cal-export.is-theme-swiss .cal-host .ec-day.cal-day-s-4 .ec-day-head {
  color: #ffffff;
}

/* The month first, small and red, as a running head; then the title at the
 * top of the scale, set tight; a heavy rule closes the head. */
.cal-export.is-theme-swiss .cal-head {
  padding-bottom: 0.6em;
  border-bottom: 0.3em solid var(--ink);
}

.cal-export.is-theme-swiss .cal-month {
  order: -1;
}

.cal-export.is-theme-swiss .cal-card h2.cal-month-name {
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 700;
  font-size: 0.85em;
}

.cal-export.is-theme-swiss .cal-title {
  font-size: 2.5em;
  letter-spacing: -0.025em;
  line-height: 0.98;
}

/* The project's icon above the title, so the title keeps the one left edge
 * the month, the total and the grid share. */
.cal-export.is-theme-swiss .cal-title .cal-icon {
  display: flex;
  inline-size: fit-content;
  margin-block-end: 0.2em;
}

.cal-export.is-theme-swiss .cal-big {
  letter-spacing: -0.03em;
}

/* Hairline rules between the days, the cells filled edge to edge. */
.cal-export.is-theme-swiss .cal-host .ec {
  --ec-border-color: #d4d4d4;
}

.cal-export.is-theme-swiss .cal-host .ec-bg-event {
  margin: 0;
  border-radius: 0;
}

.cal-export.is-theme-swiss .cal-host .ec-col-head {
  color: var(--ink);
  font-weight: 700;
  text-align: left;
  padding-left: 0.5em;
}

.cal-export.is-theme-swiss .cal-host .ec-day-head {
  color: var(--ink);
  font-weight: 500;
}

.cal-export.is-theme-swiss .cal-week {
  margin: 0;
  border-radius: 0;
  background: var(--ink);
  color: #ffffff;
}

.cal-export.is-theme-swiss .ec-header .cal-week {
  color: var(--ink);
}

.cal-export.is-theme-swiss .cal-progress-bar {
  height: 0.35em;
  border: none;
  border-radius: 0;
  background: #e6e6e6;
}

.cal-export.is-theme-swiss .cal-progress-fill {
  border-radius: 0;
  background: var(--accent);
}

/* --- Night sky ------------------------------------------------------------- */

.cal-export.is-theme-midnight {
  --paper: #0d1330;
  --surface: #111a3c;
  --surface-2: #1b2350;
  --ink: #f5efe0;
  --muted: #b6b2d8;
  --border: rgba(245, 239, 224, 0.16);
  --accent: #f2c14e;
  --on-accent: #1a1440;
  /* The chart's bars for days that lowered the count: coral beside the
   * gold ones, 5.5:1 on the night. */
  --bad: #d9776a;
  /* A glow at the top. No stars: drawn ones sat awkwardly whatever their
   * placement (owner, 2026-10-31). */
  background:
    radial-gradient(ellipse at 85% -10%, rgba(130, 100, 230, 0.38), transparent 60%),
    linear-gradient(165deg, #0b1230 0%, #161447 55%, #2a1752 100%);
}

/* The frame: a thin gold line inset from the edge. */
.cal-export.is-theme-midnight::before {
  content: "";
  position: absolute;
  inset: 22px;
  border: 1.5px solid rgba(242, 193, 78, 0.55);
  border-radius: 20px;
  pointer-events: none;
}

/* Violet, light to bright, each a clear step up from the night behind it,
 * so the cream number reads on all four: 9.7, 7.8, 6.4 and 4.9:1. */
.cal-export.is-theme-midnight .cal-card {
  --heat-1: #303575;
  --heat-2: #3c3f98;
  --heat-3: #4f47b2;
  --heat-4: #6c53cc;
}

/* The days as dots, larger the more was written (`--r`, a share of the
 * largest circle the square holds), each a few pixels off center (`--dx`,
 * `--dy`) so the rows don't line up like a printed grid. */
.cal-export.is-theme-midnight .cal-host .ec-bg-event {
  --r: 1;
  --dx: 0px;
  --dy: 0px;
  margin: 0;
  border-radius: 0;
  background-color: transparent;
  background-image: radial-gradient(
    circle closest-side at calc(50% + var(--dx)) calc(50% + var(--dy)),
    var(--dot) calc(var(--r) * 100% - 1.5px),
    transparent calc(var(--r) * 100%)
  );
}

.cal-export.is-theme-midnight .cal-host .ec-bg-event.cal-heat-1 { --dot: var(--heat-1); --r: 0.72; }
.cal-export.is-theme-midnight .cal-host .ec-bg-event.cal-heat-2 { --dot: var(--heat-2); --r: 0.82; }
.cal-export.is-theme-midnight .cal-host .ec-bg-event.cal-heat-3 { --dot: var(--heat-3); --r: 0.91; }
.cal-export.is-theme-midnight .cal-host .ec-bg-event.cal-heat-4 { --dot: var(--heat-4); --r: 1; }

.cal-export.is-theme-midnight .cal-host .ec-bg-event:nth-child(3n + 1) { --dx: 3px; --dy: -2px; }
.cal-export.is-theme-midnight .cal-host .ec-bg-event:nth-child(3n + 2) { --dx: -3px; --dy: 2px; }
.cal-export.is-theme-midnight .cal-host .ec-bg-event:nth-child(5n) { --dx: 1px; --dy: 3px; }

.cal-export.is-theme-midnight .cal-swatch {
  border-radius: 50%;
}

.cal-export.is-theme-midnight .cal-title {
  font-weight: 500;
  letter-spacing: 0.02em;
}

.cal-export.is-theme-midnight .cal-card h2.cal-month-name {
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.3em;
  font-size: 0.8em;
}

.cal-export.is-theme-midnight .cal-big {
  color: var(--accent);
  font-weight: 500;
  letter-spacing: 0.02em;
}

.cal-export.is-theme-midnight .cal-check {
  color: var(--accent);
}

.cal-export.is-theme-midnight .cal-host .ec-day.cal-best {
  box-shadow: inset 0 0 0 2px var(--accent);
  border-radius: 50%;
}

/* The week totals as gold figures on the night itself: the gold tint they
 * had came out brown on navy. */
.cal-export.is-theme-midnight .cal-week {
  color: var(--accent);
  background: rgba(245, 239, 224, 0.06);
  box-shadow: inset 0 0 0 1px rgba(242, 193, 78, 0.35);
}

.cal-export.is-theme-midnight .ec-header .cal-week {
  box-shadow: none;
}

.cal-export.is-theme-midnight .cal-progress-bar {
  background: rgba(245, 239, 224, 0.1);
  border-color: rgba(242, 193, 78, 0.45);
}

.cal-export.is-theme-midnight .cal-progress-fill {
  background: var(--accent);
}

/* --- Graph paper ----------------------------------------------------------- */

.cal-export.is-theme-graph {
  --paper: #fbfcf8;
  --surface: #fbfcf8;
  --surface-2: #eef3fb;
  --ink: #1c2a4d;
  --muted: #4f5c80;
  --border: #c5d3ea;
  --accent: #d8443a;
  --on-accent: #ffffff;
  /* The chart's bars for days that lowered the count: the pencil blue
   * beside the red ones, 6.4:1 on the paper. */
  --bad: #4f5c80;
  /* A blue grid at a 30px pitch, and the red margin line in the padding. */
  background:
    linear-gradient(90deg, transparent 38px, rgba(216, 68, 58, 0.55) 38px 40px, transparent 40px),
    linear-gradient(#dae4f3 1px, transparent 1px) 0 0 / 100% 30px,
    linear-gradient(90deg, #dae4f3 1px, transparent 1px) 0 0 / 30px 100%,
    #fbfcf8;
}

/* Highlighter yellow, pale to full, translucent so the grid shows through as
 * it does under real highlighter; the navy ink reads on all of it, 9.5:1 or
 * more. */
.cal-export.is-theme-graph .cal-card {
  --heat-1: rgba(255, 215, 0, 0.26);
  --heat-2: rgba(255, 215, 0, 0.46);
  --heat-3: rgba(255, 215, 0, 0.66);
  --heat-4: rgba(255, 210, 0, 0.84);
}

/* Marked by hand: a little uneven, a little turned. */
.cal-export.is-theme-graph .cal-host .ec-bg-event {
  border-radius: 4px 10px 5px 11px;
}

.cal-export.is-theme-graph .cal-host .ec-bg-event:nth-child(odd) {
  transform: rotate(-1.4deg);
}

.cal-export.is-theme-graph .cal-host .ec-bg-event:nth-child(even) {
  transform: rotate(1.1deg);
}

/* The title marked in highlighter, line by line: a thick underline raised
 * behind the letters. (A background on the title's text covered only its
 * last line: the text is a flex item, so a block.) */
.cal-export.is-theme-graph .cal-title-text {
  text-decoration-line: underline;
  text-decoration-color: #ffe24f;
  text-decoration-thickness: 0.42em;
  text-underline-offset: -0.3em;
  text-decoration-skip-ink: none;
}

.cal-export.is-theme-graph .cal-card h2.cal-month-name {
  color: var(--accent);
  font-weight: 700;
}

.cal-export.is-theme-graph .cal-host .ec-col-head {
  color: var(--ink);
}

/* The week totals written in the red pen, on the paper: no box of their
 * own, as a sum in a notebook's margin has none. */
.cal-export.is-theme-graph .cal-week {
  background: none;
  color: var(--accent);
}

.cal-export.is-theme-graph .cal-progress-bar {
  background: #ffffff;
  border-color: var(--ink);
}

.cal-export.is-theme-graph .cal-progress-fill {
  background: #ffe24f;
}

/* --- Sunset ---------------------------------------------------------------- */

.cal-export.is-theme-sunset {
  --paper: #8a35b0;
  --surface: #cf3f74;
  --surface-2: rgba(255, 255, 255, 0.14);
  /* The smaller lines in solid white too: translucent white on the
   * gradient read too faint (a reviewer's finding). The size and weight
   * rank them. */
  --ink: #ffffff;
  --muted: #ffffff;
  --border: rgba(255, 255, 255, 0.24);
  --accent: #ffffff;
  --on-accent: #b0336b;
  /* The chart's bars for days that lowered the count: gold beside the
   * white ones, 3.9:1 or more anywhere on the gradient. */
  --bad: #ffd36b;
  --sunset-plum: #4a1650;
  /* Deep enough at the top for white type, 5.5:1 at its lightest, and for
   * the day's date on a tile, 4.6:1. */
  background: linear-gradient(170deg, #bb3c3c 0%, #b13268 42%, #7a2fa3 78%, #4e2496 100%);
}

.cal-export.is-theme-sunset .cal-head,
.cal-export.is-theme-sunset .cal-legend,
.cal-export.is-theme-sunset .cal-stats {
  text-shadow: 0 1px 2px rgba(60, 0, 40, 0.3);
}

/* White, more of it for more words; the plum number reads on every step
 * wherever it is on the gradient, 5.0:1 or more. */
.cal-export.is-theme-sunset .cal-card {
  --heat-1: rgba(255, 255, 255, 0.5);
  --heat-2: rgba(255, 255, 255, 0.62);
  --heat-3: rgba(255, 255, 255, 0.8);
  --heat-4: #ffffff;
}

.cal-export.is-theme-sunset .cal-n[class*="cal-s-"] {
  color: var(--sunset-plum);
  text-shadow: none;
}

/* The date in a shaded day's corner in the plum too: white on the white
 * steps was 1.0 to 2.5:1. Plum is 5.6:1 or more on every step. */
.cal-export.is-theme-sunset .cal-host .ec-day:is(.cal-day-s-1, .cal-day-s-2, .cal-day-s-3, .cal-day-s-4) .ec-day-head {
  color: var(--sunset-plum);
}

/* Every day of the month a tile, its shading over it. */
.cal-export.is-theme-sunset .cal-host .ec-day:not(.ec-other-month) {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  margin: 3px;
}

.cal-export.is-theme-sunset .cal-host .ec-bg-event {
  border-radius: 14px;
}

.cal-export.is-theme-sunset .cal-title {
  letter-spacing: -0.01em;
}

.cal-export.is-theme-sunset .cal-card h2.cal-month-name {
  text-transform: uppercase;
  letter-spacing: 0.22em;
  font-weight: 600;
  font-size: 0.85em;
}

.cal-export.is-theme-sunset .cal-host .ec-col-head,
.cal-export.is-theme-sunset .cal-host .ec-day-head {
  color: #ffffff;
}

.cal-export.is-theme-sunset .cal-week {
  background: rgba(255, 255, 255, 0.16);
  border-radius: 14px;
}

.cal-export.is-theme-sunset .cal-swatch {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.6);
}

.cal-export.is-theme-sunset .cal-progress-bar {
  background: rgba(255, 255, 255, 0.18);
  border-color: rgba(255, 255, 255, 0.5);
}

.cal-export.is-theme-sunset .cal-progress-fill {
  background: #ffffff;
}

/* The best day's ring and today's mark, in plum on the white. */
.cal-export.is-theme-sunset .cal-host .ec-day.cal-best {
  box-shadow: inset 0 0 0 2px #ffffff;
  border-radius: 14px;
}

/* --- Sage leaves ----------------------------------------------------------- */

.cal-export.is-theme-garden {
  --paper: #e3e9d6;
  --surface: #eef1e4;
  --surface-2: #dfe6cf;
  --ink: #22382a;
  --muted: #4d6352;
  --border: #c6d2b5;
  --accent: #c2573a;
  --on-accent: #ffffff;
  /* The chart's bars for days that lowered the count: slate blue beside
   * the terracotta ones, 6.2:1 on the stock. */
  --bad: #3f5a7a;
  /* Sage stock, warmer in one corner and greener in the other. */
  background:
    radial-gradient(ellipse at 100% 0%, rgba(194, 87, 58, 0.12), transparent 45%),
    radial-gradient(ellipse at 0% 100%, rgba(79, 138, 75, 0.16), transparent 50%),
    #eef1e4;
}

/* Greens, new leaf to old. Against the green ink: 9.3, 7.0 and 4.6:1; the
 * darkest takes the paper's color for its number, 4.8:1. */
.cal-export.is-theme-garden .cal-card {
  --heat-1: #d2e3c2;
  --heat-2: #abcb97;
  --heat-3: #7aa96b;
  --heat-4: #3f7a45;
}

.cal-export.is-theme-garden .cal-n.cal-s-4 {
  color: #f7f9f0;
}

/* A leaf: two corners pointed, two rounded. */
.cal-export.is-theme-garden .cal-host .ec-bg-event {
  margin: 4px;
  border-radius: 0 70% 0 70%;
}

.cal-export.is-theme-garden .cal-swatch {
  border-radius: 0 70% 0 70%;
}

.cal-export.is-theme-garden .cal-title {
  font-weight: 500;
  letter-spacing: 0.01em;
}

.cal-export.is-theme-garden .cal-card h2.cal-month-name {
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: 0.82em;
  font-weight: 600;
}

.cal-export.is-theme-garden .cal-big {
  color: #2f5a36;
}

.cal-export.is-theme-garden .cal-host .ec-col-head {
  color: var(--ink);
}

/* The week totals on a leaf of their own, the newest green. */
.cal-export.is-theme-garden .cal-week {
  background: var(--heat-1);
  color: var(--ink);
  border-radius: 0 50% 0 50%;
}

.cal-export.is-theme-garden .ec-header .cal-week {
  background: none;
}

.cal-export.is-theme-garden .cal-progress-bar {
  background: #dfe6cf;
  border-color: #abcb97;
}

.cal-export.is-theme-garden .cal-progress-fill {
  background: #3f7a45;
}
/* Stickers on the calendar image (`projects-calendar-stickers.js`,
 * `projects/calendar_stickers.rs`): on every stage the image is made in, the
 * frames and handles that move them on the preview, and the tray of animals
 * beside it.
 *
 * The stickers' white outline is the owner's ask for the share image
 * (2026-10-29), not the pets' look: outlined pet emotes were tried for
 * Discord and turned down (2026-08-13), and that still stands there. */

/* --- On the image ------------------------------------------------------------- */

/* Over the whole stage, the card included; nothing in it takes a press (the
 * preview's frames do). */
.cal-export > .cal-stickers {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
}

/* One sticker, its middle at its place (set in `%` of the stage), its size
 * and its turn set by the script. Its font size is a hundredth of its width,
 * so the outline and the shadow below grow with it: an outline 3% of the
 * sticker's width, drawn as four white shadows (a filter html-to-image
 * keeps in the PNG; checked 2026-10-29), and a soft shadow under it, as a
 * vinyl sticker on paper has. */
.cal-sticker {
  position: absolute;
  transform-origin: 50% 50%;
}

.cal-sticker img,
.cal-sticker-text {
  display: block;
  width: 100%;
  height: 100%;
  filter:
    drop-shadow(3em 0 0 #ffffff)
    drop-shadow(-3em 0 0 #ffffff)
    drop-shadow(0 3em 0 #ffffff)
    drop-shadow(0 -3em 0 #ffffff)
    drop-shadow(0 1.6em 2.2em rgba(20, 10, 30, 0.38));
}

/* This device's emoji: the emoji as text in the device's own emoji font,
 * in the middle of the sticker's square. The outline above is on the
 * wrapper, at the sticker's hundredth; the glyph inside is 80 of those, as
 * an emoji glyph is drawn a little wider than its font size, and a
 * Twemoji picture leaves about that much room at its edges. */
.cal-sticker-text {
  display: flex;
  align-items: center;
  justify-content: center;
}

.cal-sticker-text > span,
.cal-sticker-glyph {
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Twemoji Mozilla", sans-serif;
  font-style: normal;
  font-weight: 400;
  line-height: 1;
  white-space: nowrap;
}

.cal-sticker-text > span {
  font-size: 80em;
}

/* --- On the preview ----------------------------------------------------------- */

/* Handles reach past the image's edge for a sticker near it. */
.cal-preview.has-stickers {
  overflow: visible;
}

.cal-sticker-frames {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
}

/* Over each sticker: where it is pressed and dragged, and focused for its
 * keys. Seen only when selected, focused or pointed at. */
.cal-sticker-frame {
  position: absolute;
  box-sizing: border-box;
  border-radius: 10%;
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
  outline: none;
}

.cal-sticker-frame:hover {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85), 0 0 0 2.5px rgba(0, 0, 0, 0.35);
}

.cal-sticker-frame.is-selected,
.cal-sticker-frame:focus-visible {
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 4px rgba(255, 255, 255, 0.8);
}

.cal-sticker-frame:active {
  cursor: grabbing;
}

/* The handles: round, 28px, on the frame's corners and above it. They turn
 * with the frame, so each stays where it means the same. */
.cal-sticker-h {
  position: absolute;
  width: 28px;
  height: 28px;
  min-height: 0;
  padding: 0;
  border: 2px solid #ffffff;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent, #ffffff);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
  touch-action: none;
}

/* The glyph stays upright while the frame turns (`--r`, the sticker's turn,
 * set by the script): turned with it, × read as + (a reviewer's finding). */
.cal-sticker-h::before {
  display: block;
  font-size: 15px;
  font-weight: 700;
  line-height: 24px;
  text-align: center;
  transform: rotate(calc(-1 * var(--r, 0deg)));
}

/* Turn: above the middle, on a short stalk, as photo editors draw it. */
.cal-sticker-h.is-rotate {
  left: calc(50% - 14px);
  top: -44px;
  cursor: grab;
}

.cal-sticker-h.is-rotate::before {
  content: "\21bb";
}

.cal-sticker-h.is-rotate::after {
  content: "";
  position: absolute;
  left: 11px;
  top: 26px;
  width: 2px;
  height: 18px;
  background: #ffffff;
  box-shadow: 0 0 2px rgba(0, 0, 0, 0.4);
}

/* Size: the bottom right corner. */
.cal-sticker-h.is-resize {
  right: -14px;
  bottom: -14px;
  cursor: nwse-resize;
}

/* The arrow along the drag: corner to corner, top left to bottom right. */
.cal-sticker-h.is-resize::before {
  content: "\2921";
}

/* Flip: the top left corner, pressed. The frame is not mirrored with the
 * sticker, so the handles stay where they are. */
.cal-sticker-h.is-flip {
  left: -14px;
  top: -14px;
  cursor: pointer;
}

.cal-sticker-h.is-flip::before {
  content: "\21c4";
}

/* Remove: the top right corner. */
.cal-sticker-h.is-remove {
  right: -14px;
  top: -14px;
  background: #2b2420;
  color: #ffffff;
  cursor: pointer;
}

.cal-sticker-h.is-remove::before {
  content: "\00d7";
  font-size: 19px;
  line-height: 23px;
}

/* On a touch screen the handles reach 44px, as every Projects button does. */
@media (pointer: coarse) {
  .cal-sticker-h::after {
    content: "";
    position: absolute;
    inset: -8px;
  }

  .cal-sticker-h.is-rotate::after {
    inset: -8px;
    width: auto;
    height: auto;
    background: none;
    box-shadow: none;
  }
}

/* --- The tray ------------------------------------------------------------------- */

/* Website only, as the image is. */
body:not(.lounge-web) .cal-stickers-tray {
  display: none;
}

.cal-stickers-help {
  margin: 0;
}

.cal-sticker-group {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

.cal-sticker-group h3 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
}

.cal-sticker-search {
  width: 100%;
  min-height: 2.2rem;
  box-sizing: border-box;
}

/* Every animal in a box of its own height: the list is long. */
.cal-sticker-scroll {
  max-height: 16rem;
  overflow-y: auto;
  padding: 0.2rem 0.3rem 0.4rem 0;
  border-radius: var(--radius-sm);
}

.cal-sticker-cat h4 {
  margin: 0.5rem 0 0.25rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--muted);
}

.cal-sticker-cat[hidden] {
  display: none;
}

.cal-sticker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.6rem, 1fr));
  gap: 0.25rem;
}

/* An animal: its picture, the whole tile the target. */
button.cal-sticker-add {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.6rem;
  padding: 0.3rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

button.cal-sticker-add:hover {
  border-color: var(--border);
  background: var(--paper);
}

button.cal-sticker-add[hidden] {
  display: none;
}

button.cal-sticker-add img {
  width: 1.8rem;
  height: 1.8rem;
}

/* A pet whose art style is the drawing turned to face right (Noto_R,
 * Twemoji_R): shown as its sticker starts, flipped. */
button.cal-sticker-add.is-mirrored img {
  transform: scaleX(-1);
}

/* An animal in This device's emoji: the emoji as text, the picture's size. */
.cal-sticker-glyph {
  display: block;
  font-size: 1.5rem;
  height: 1.8rem;
  line-height: 1.8rem;
}

/* Emoji style, at the tray's foot. */
.cal-sticker-art .hint {
  margin: 0;
}

.cal-sticker-art .hint[hidden] {
  display: none;
}

/* Sprinto and the writer's pets: each with its name under it, in the tray
 * only (owner, 2026-10-30), so their tiles are wider. A name too long for
 * its tile ends in an ellipsis; the button's tooltip has it whole. */
.cal-sticker-grid:has(.has-caption) {
  grid-template-columns: repeat(auto-fill, minmax(4.6rem, 1fr));
}

button.cal-sticker-add.has-caption {
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.cal-sticker-caption {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.75rem;
  color: var(--muted);
}

.cal-sticker-none {
  margin: 0.4rem 0 0;
}
