/* ==========================================================================
   The Discordian Calendar. One stylesheet, every page.

   Register: a well-made almanac. Letterpress-adjacent, quiet, generous. The
   content is absurd; the design is not in on the joke. Emphasis comes from
   rules, letterspaced labels and space, never from colour.
   ========================================================================== */

/* --- Tokens ------------------------------------------------------------- */

:root {
  --font-serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino,
                "Book Antiqua", Georgia, "Times New Roman", serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
  --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --fs-xs: 0.8rem;
  --fs-sm: 0.9375rem;
  --fs-base: 1.0625rem;
  --fs-md: 1.25rem;
  --fs-lg: 1.5625rem;
  --fs-xl: 1.953rem;
  --fs-2xl: 2.441rem;
  --fs-hero: clamp(2rem, 1.1rem + 4.4vw, 4.25rem);

  --lh-tight: 1.14;
  --lh-snug: 1.32;
  --lh-base: 1.62;

  --measure: 34rem;
  --measure-wide: 64rem;

  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-12: 3rem;
  --sp-16: 4rem;
  --sp-24: 6rem;
  --gutter: clamp(1rem, 4vw, 2.5rem);

  /* Light, the default. Warm paper, warm ink. */
  --paper: #F7F4EC;
  --paper-raised: #FFFDF7;
  --ink: #1C1A17;
  --ink-muted: #56514A;
  --rule: #DCD5C6;
  --rule-strong: #C4B99F;
  --accent: #8C5E10;
  --accent-mark: #C99A2E;
  --accent-wash: #F0E7CF;
  /* Interactive boundaries, held at >= 3:1 against --paper in both themes
     (WCAG 1.4.11). --rule-strong stays decorative. */
  --field-border: #8E8369;
  --caution: #8A3B1E;

  color-scheme: light dark;
}

/* The dark palette is declared twice, verbatim: once for the system
   preference (unless the reader has explicitly chosen light) and once for the
   explicit choice, so the manual toggle wins in either direction. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #14120F;
    --paper-raised: #1D1A16;
    --ink: #EDE7DA;
    --ink-muted: #A79E8C;
    --rule: #332E26;
    --rule-strong: #4A4235;
    --accent: #E0B44A;
    --accent-mark: #C99A2E;
    --accent-wash: #2A2317;
    --field-border: #776B57;
    --caution: #E2946F;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --paper: #14120F;
  --paper-raised: #1D1A16;
  --ink: #EDE7DA;
  --ink-muted: #A79E8C;
  --rule: #332E26;
  --rule-strong: #4A4235;
  --accent: #E0B44A;
  --accent-mark: #C99A2E;
  --accent-wash: #2A2317;
  --field-border: #776B57;
  --caution: #E2946F;

  /* Native widgets follow color-scheme, not the palette: the date picker, the
     checkbox, the select chevron, the scrollbars. The manual toggle has to move
     it or they render in the theme the reader just turned off. */
  color-scheme: dark;
}

:root[data-theme="light"] { color-scheme: light; }

/* --- Reset -------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background-color: var(--paper);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3 { margin: 0 0 var(--sp-4); line-height: var(--lh-snug); font-weight: 600; }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
p { margin: 0 0 var(--sp-4); }
ul, ol { margin: 0 0 var(--sp-4); padding-inline-start: var(--sp-6); }
li { margin-bottom: var(--sp-2); }

a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}
a:hover, a:focus-visible { text-decoration-color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

[hidden] { display: none !important; }

/* Text for assistive technology only. A tooltip is not a way to tell someone
   which weekday a cell is in. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: no-preference) {
  a, button { transition: color 120ms, border-color 120ms, text-decoration-color 120ms; }
}

/* --- Layout ------------------------------------------------------------- */

.wrap {
  width: min(100% - 2 * var(--gutter), var(--measure-wide));
  margin-inline: auto;
}

.prose { max-width: var(--measure); }
.prose h2 { margin-top: var(--sp-12); }

main { flex: 1 0 auto; padding-block: var(--sp-8) var(--sp-16); }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--sp-2);
}

.rule { border: 0; border-top: 1px solid var(--rule); margin: var(--sp-16) 0; }

/* --- Masthead ----------------------------------------------------------- */

.masthead {
  border-bottom: 3px double var(--rule-strong);
  padding-block: var(--sp-4);
}
.masthead .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-3) var(--sp-6);
}
.wordmark {
  font-size: var(--fs-md);
  letter-spacing: 0.02em;
  text-decoration: none;
  border-bottom: 2px solid var(--accent);
  padding-bottom: 2px;
  margin-right: auto;
  min-width: 0;
}
.masthead nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  align-items: baseline;
  min-width: 0;
}
.masthead nav a {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  text-decoration: none;
}
.masthead nav a:hover,
.masthead nav a:focus-visible,
.masthead nav a[aria-current="page"] { color: var(--ink); }

.theme-toggle {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background-color: transparent;
  border: 1px solid var(--field-border);
  border-radius: 2px;
  padding: var(--sp-1) var(--sp-2);
  cursor: pointer;
}
.theme-toggle:hover { color: var(--ink); border-color: var(--ink-muted); }

/* --- Colophon ----------------------------------------------------------- */

.colophon {
  border-top: 1px solid var(--rule);
  padding-block: var(--sp-6);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}
.colophon p { margin: 0; }

/* --- Hero (home + date page) -------------------------------------------- */

.hero { padding-block: clamp(3rem, 10vh, 7rem) var(--sp-8); }
.hero-date {
  font-size: var(--fs-hero);
  line-height: var(--lh-tight);
  letter-spacing: -0.011em;
  font-weight: 500;
  max-width: 22ch;
  text-wrap: balance;
  overflow-wrap: anywhere;
  margin: 0;
}
.hero .eyebrow { margin-bottom: var(--sp-3); }
.lede { font-size: var(--fs-md); max-width: var(--measure); }
.hero-date + .lede, .hero-date + .lede + .lede { margin-top: clamp(1.5rem, 3vw, 2.5rem); }
.lede .accent, .holyday-name { color: var(--accent); }
.count { color: var(--accent); font-variant-numeric: tabular-nums; }

/* --- Nav blocks (home) --------------------------------------------------- */

.blocks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--sp-4);
  padding: 0;
  margin: 0;
  list-style: none;
}
.blocks li { margin: 0; min-width: 0; }
.blocks a {
  display: block;
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: var(--sp-6);
  height: 100%;
  text-decoration: none;
  background-color: var(--paper-raised);
}
.blocks a:hover, .blocks a:focus-visible { border-color: var(--rule-strong); }
.blocks strong { display: block; font-size: var(--fs-md); font-weight: 600; }
.blocks span { display: block; margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--ink-muted); }

/* --- Forms (converter) --------------------------------------------------- */

.field { margin-bottom: var(--sp-4); max-width: 22rem; }
.field label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--sp-1);
}
input[type="date"], input[type="number"], select {
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  width: 100%;
  max-width: 100%;
  padding: var(--sp-2);
  border: 1px solid var(--field-border);
  border-radius: 2px;
  background-color: var(--paper-raised);
  color: var(--ink);
}
input:disabled, select:disabled { color: var(--ink-muted); background-color: var(--paper); }
.check { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); }
.check input { width: auto; }
/* Left alone, a checked box paints the platform accent: a bright blue, and the
   only colour on the page from outside the palette. Ink rather than gold: gold
   is the celebration colour and its budget is spent on holydays, and a checkbox
   is not a celebration. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--ink); }
.check label {
  font-family: var(--font-serif);
  font-size: var(--fs-base);
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
  margin: 0;
}

.result {
  border-left: 2px solid var(--rule-strong);
  padding-left: var(--sp-4);
  margin-block: var(--sp-6);
}
/* A live region has to stay in the tree to be announced, so an empty result
   collapses rather than disappearing. */
.result:empty, .result.is-empty {
  border-left-color: transparent;
  padding-left: 0;
  margin-block: 0;
}
.result p { margin-bottom: var(--sp-2); }
.result p:empty { display: none; }
.result-long { font-size: var(--fs-md); }
.result-short, .permalink-row { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-muted); }
.permalink-row a { color: var(--ink); }

/* Gold is the celebration colour and its budget is spent on holydays; an error
   gets its own restrained treatment instead. */
.error {
  color: var(--ink);
  border-left: 2px solid var(--caution);
  padding-left: var(--sp-4);
  margin-block: var(--sp-6);
  font-size: var(--fs-md);
}
.error[data-eyebrow]::before {
  content: attr(data-eyebrow);
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--caution);
  margin-bottom: var(--sp-1);
}
.error:empty { display: none; }
/* An empty field is not a failure, so it does not get "CANNOT CONVERT" over a
   caution rule. Same slot, quieter register. */
.error.is-prompt { border-left-color: var(--rule-strong); color: var(--ink-muted); }

/* Not an error. A correction the reader should see, e.g. "that isn't a year
   this calendar covers; showing 2026 instead". Named for the page rather than
   given the bare `.note` it once had: `.tibs-cell .note` is a different thing
   at a different scale, and inherited a stray rule and a hanging indent from
   it. */
.page-note {
  border-left: 2px solid var(--rule-strong);
  padding-left: var(--sp-4);
  margin-block: var(--sp-6);
  color: var(--ink-muted);
  max-width: var(--measure);
}
.page-note:empty { display: none; }

/* The two directions are two halves of the page, not two more field labels:
   they get serif headings with a rule under them, and a place in the heading
   list. */
.section-heading {
  font-size: var(--fs-lg);
  color: var(--ink);
  margin: 0 0 var(--sp-4);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--rule);
}

.converter-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-16);
}
@media (min-width: 60rem) {
  .converter-columns { grid-template-columns: 1fr 1fr; gap: var(--sp-12); }
}
.converter-columns > section { min-width: 0; }

/* --- Date page ----------------------------------------------------------- */

.date-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  margin-top: var(--sp-8);
}
.date-nav a { color: var(--ink-muted); }
.date-nav a:hover, .date-nav a:focus-visible { color: var(--ink); }

/* --- Year view ----------------------------------------------------------- */

.year-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-4);
  margin-bottom: var(--sp-8);
}
.year-head h1 { margin: 0; margin-right: auto; }
.year-nav { display: flex; gap: var(--sp-4); font-family: var(--font-mono); font-size: var(--fs-sm); }

.season { margin-bottom: var(--sp-16); min-width: 0; }
.season-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.season-head h2 { font-size: var(--fs-lg); margin: 0; }
.season-head .span { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-muted); letter-spacing: 0.08em; }

.week-grid {
  table-layout: fixed;
  border-collapse: separate;
  /* The cell gap is border-spacing, pulled back at the edges so the grid still
     aligns flush with the season heading above it. */
  border-spacing: var(--sp-1);
  width: calc(100% + 2 * var(--sp-1));
  margin-inline: calc(-1 * var(--sp-1));
  font-size: inherit;
}
.week-grid + .tibs-cell, .tibs-cell + .week-grid { margin-top: var(--sp-2); }
/* Column widths belong to the <colgroup>, not to the header row, so the
   continuation grid can hide its headers without the columns moving. */
.week-grid col { width: 20%; }
/* The half of a leap-year Chaos that resumes after St. Tib's Day keeps its
   column headers for assistive tech and hides them from sight: five seasons
   must not show six header rows, and a repeated SWEETMORN … SETTING ORANGE
   under the band reads as a new season rather than the same one continuing. */
.week-grid.is-continuation thead {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.week-head {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: left;
  color: var(--ink-muted);
  padding: 0 0 var(--sp-1);
  border-bottom: 1px solid var(--rule);
  overflow: hidden;
  white-space: nowrap;
}
/* The uppercase treatment is for the eye only. Chrome applies text-transform
   when it computes an accessible name, so letting it reach the sr-only span
   handed screen readers "SWEETMORN". An all-caps string is what turns a
   weekday back into the abbreviation the span exists to replace. */
.week-head .visually-hidden {
  text-transform: none;
  letter-spacing: normal;
}
.day-blank { padding: 0; border: 0; }
.week-head .long { display: none; }
.week-head .short { display: inline; }
@media (min-width: 40rem) {
  .week-head .long { display: inline; }
  .week-head .short { display: none; }
}

.day-cell {
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  background-color: var(--paper-raised);
  vertical-align: top;
  overflow: hidden;
}
/* One aria-hidden face carries everything drawn, and the mouse tooltip with
   it; the cell's own text is the visually-hidden reading and nothing else. */
.day-cell .face { display: block; }
.day-cell .n { display: block; color: var(--ink); }
.day-cell .label {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-xs);
  color: var(--ink-muted);
  hyphens: auto;
}
.day-cell.is-holyday { background-color: var(--accent-wash); border-color: var(--rule-strong); }
.day-cell.is-holyday .label { color: var(--accent); }
.day-cell.is-holyday .n::after {
  content: "";
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  margin-left: var(--sp-1);
  background-color: var(--accent-mark);
  transform: rotate(45deg);
}
.day-cell.is-today, .tibs-cell.is-today { border: 2px solid var(--accent); }

.tibs-cell {
  grid-column: 1 / -1;
  border: 1px dashed var(--rule-strong);
  border-radius: 2px;
  background-color: var(--accent-wash);
  padding: var(--sp-3);
  margin-block: var(--sp-2);
  min-width: 0;
}
.tibs-cell .name { font-family: var(--font-serif); font-size: var(--fs-md); color: var(--accent); }
.tibs-cell .note { display: block; font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-muted); margin-top: var(--sp-1); }

/* The two holydays of the season, named in full. Redundant while the cells are
   wide enough to carry their own labels; the only place they are named once the
   cells are not. */
.season-legend {
  display: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}
.season-legend li { margin: 0 0 var(--sp-1); }
.season-legend .name { color: var(--accent); }
.season-legend .name::before {
  content: "";
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  margin-right: var(--sp-2);
  background-color: var(--accent-mark);
  transform: rotate(45deg);
}

@media (max-width: 40rem) {
  .day-cell { font-size: var(--fs-sm); padding: var(--sp-1); }
  .day-cell .label { font-size: 0.7rem; }
}

/* Below about 30rem a cell is ~46px of content box: every holyday name breaks
   mid-word. The diamond keeps marking the day; the legend carries the name. */
@media (max-width: 30rem) {
  .day-cell .label { display: none; }
  .season-legend { display: block; }
}

/* --- Tables (reference) --------------------------------------------------- */

.table-scroll { overflow-x: auto; margin-bottom: var(--sp-6); }
table { border-collapse: collapse; font-size: var(--fs-sm); }
th, td { text-align: left; padding: var(--sp-2) var(--sp-4) var(--sp-2) 0; border-bottom: 1px solid var(--rule); }
th {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-weight: 400;
  white-space: nowrap;
}

code, .mono { font-family: var(--font-mono); font-size: 0.92em; }
/* Inline code is mostly paths and URLs, which have no break opportunities. */
code { overflow-wrap: anywhere; }

noscript { display: block; }
