/* ==========================================================================
   Butler — base
   Tokens, reset, typography, and the handful of components every page uses.
   Plain CSS on purpose: no build step, no framework, no utility classes.

   The look is "stationery": warm paper, a serif for names and headings,
   hairline rules, small corners, no shadows, and one colour. That colour is a
   yellow, used two ways: butter as a fill (the main button, a chosen option,
   the small mark under a name) and ochre where yellow has to be a line or a
   glyph (icons, focus rings, the current page). Yellow never carries text on
   paper, because it cannot be read there; text on butter is near-black.

   Dark mode follows the device. There is no switch, because it is not a
   decision anybody should have to make.
   ========================================================================== */

/* Newsreader (headings) and Instrument Sans (everything else), both SIL OFL,
   vendored in assets/vendor/ with their licences so no page asks a third party
   for a font. Both files are variable: one file covers every weight used. */
@font-face {
  font-family: "Newsreader"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url(/assets/vendor/newsreader/newsreader-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Newsreader"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url(/assets/vendor/newsreader/newsreader-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Newsreader"; font-style: italic; font-weight: 400; font-display: swap;
  src: url(/assets/vendor/newsreader/newsreader-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Newsreader"; font-style: italic; font-weight: 400; font-display: swap;
  src: url(/assets/vendor/newsreader/newsreader-italic-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Sans"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url(/assets/vendor/instrument-sans/instrument-sans-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url(/assets/vendor/instrument-sans/instrument-sans-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Paper. The ground is a warm off-white, a card is one step lighter, a
     sunken area (a rail, a note, a table head) one step darker. */
  --paper:        #f6f3ec;
  --paper-raised: #fcfaf5;
  --paper-field:  #fffefb;                               /* inputs, so they read as blank */
  --paper-sunken: #efebe2;
  --paper-veil:   rgba(246, 243, 236, .88);             /* sticky bars, over blur */
  --ink:          #1d1c1a;
  --ink-soft:     #6b675f;
  --ink-faint:    #8d887e;
  /* A select's arrow, in --ink-soft. A data URI cannot read a token, so it is spelled out. */
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b675f' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  --rule:         #d9d3c6;
  --rule-strong:  #c4bdae;

  /* The one colour. `--brand` is ochre: every line, icon and ring that has to be
     yellow on paper (3:1 or better against it). `--brand-text` is the same hue
     dark enough for words (4.5:1). `--brand-fill` is butter, for surfaces, and
     carries --brand-ink (near-black) on it. */
  --brand:        #b08500;
  --brand-text:   #7d5c00;
  --brand-dark:   #5f4600;
  --brand-tint:   #fbf0cc;
  --brand-fill:   #f0cf62;
  --brand-fill-hover: #ebc443;
  --brand-edge:   #caa53a;
  --brand-ink:    #1d1c1a;
  --mark:         #f3d77a;                               /* the short bar under a name */

  /* Checklister had a second, violet voice for the chrome. This product has one
     colour, so the accent tokens point at the same yellow. They stay as names
     because the console styles (and the plan page) use them for "this frames the
     work": the current page, a region's icon, the plan we recommend. */
  --accent:       var(--brand);
  --accent-dark:  var(--brand-text);
  --accent-lift:  var(--brand-edge);
  --accent-tint:  var(--brand-tint);
  --accent-ink:   var(--brand-ink);
  --accent-row:   rgba(156, 115, 0, .05);               /* table hover, barely there */

  --done:         #3b7a4c;
  --done-tint:    #e4eee1;
  --warn:         #a0561a;
  --warn-tint:    #f7e7d5;
  --danger:       #b3372b;
  --danger-tint:  #f7e3df;

  --focus:        var(--brand);
  --ring:         0 0 0 3px rgba(156, 115, 0, .22);

  /* Small corners, and only on things that are objects or controls. */
  --radius:       3px;
  --radius-lg:    4px;
  --radius-pill:  999px;
  /* Flat. A hairline around a surface already says "this is a thing". The large
     shadow is only for what floats over the page: a popover, a menu. */
  --shadow:       none;
  --shadow-lg:    0 2px 4px rgba(29, 28, 26, .06), 0 18px 36px -20px rgba(29, 28, 26, .38);
  --measure:      68ch;

  --font-body:  "Instrument Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-serif: "Newsreader", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-mono:  ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:        #161513;
    --paper-raised: #1e1c19;
    --paper-field:  #22201c;
    --paper-sunken: #11100e;
    --paper-veil:   rgba(22, 21, 19, .88);
    --ink:          #ece8df;
    --ink-soft:     #aaa396;
    --ink-faint:    #7f796d;
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aaa396' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    --rule:         #34312b;
    --rule-strong:  #48443b;

    --brand:        #d9ad3f;
    --brand-text:   #e6c46a;
    --brand-dark:   #f0d68f;
    --brand-tint:   #342b14;
    --brand-fill:   #e3c255;
    --brand-fill-hover: #ecd06c;
    --brand-edge:   #b8952f;
    --brand-ink:    #1d1c1a;
    --mark:         #c9a642;

    --accent-row:   rgba(217, 173, 63, .07);

    --done:         #7cc58f;
    --done-tint:    #1b2c20;
    --warn:         #e79a5c;
    --warn-tint:    #36251a;
    --danger:       #ef8d82;
    --danger-tint:  #37201c;

    --ring:         0 0 0 3px rgba(217, 173, 63, .28);
    --shadow-lg:    0 2px 6px rgba(0, 0, 0, .5), 0 24px 48px -22px rgba(0, 0, 0, .9);
  }
}

/* --- Reset (light touch) ------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 16px/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased;
}

/* Headings are the serif, at its regular weight: the size does the work, and a
   bold serif at these sizes reads as a newspaper rather than as a letterhead. */
h1, h2, h3, h4 { line-height: 1.15; margin: 0 0 .5em; font-weight: 400; letter-spacing: -.01em; }
h1, h2 { font-family: var(--font-serif); }
h1 { font-size: 2.4rem; }
h2 { font-size: 1.7rem; }
/* The small headings stay in the sans: a 17px serif is a caption, not a title. */
h3, h4 { font-weight: 600; letter-spacing: 0; }
h3 { font-size: 1.05rem; }
p, ul, ol { margin: 0 0 1em; }
p { max-width: var(--measure); }

a { color: var(--brand-text); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--ink); }

img, svg, video { max-width: 100%; height: auto; }

small, .small { font-size: .875rem; }
.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); }
.mono  { font-family: var(--font-mono); }

/* The small uppercase label: a place's name over a heading, a rail card's title,
   a table's column heads. Tracked out, because capitals set tight are shouting. */
.caps {
  font-size: .78rem; font-weight: 500; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

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

.wrap      { width: 100%; max-width: 1140px; margin-inline: auto; padding-inline: 20px; }
.wrap-slim { width: 100%; max-width: 640px;  margin-inline: auto; padding-inline: 20px; }
.stack > * + * { margin-top: 1rem; }
.row { display: flex; gap: .75rem; align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: .75rem; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.grow { flex: 1 1 auto; min-width: 0; }
.hidden { display: none !important; }
/* Words for a screen reader only, such as a chart's values said in full. */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* --- The brand ------------------------------------------------------------
   The bee, then the name in the serif with the short butter bar that sits
   under a name on every guest page. The bee is yellow on a transparent
   ground, so it needs no dark-mode version.
   ------------------------------------------------------------------------ */

.brand {
  display: inline-flex; align-items: center; gap: 1rem;
  font-family: var(--font-serif); font-size: 1.45rem; line-height: 1; letter-spacing: -.01em;
  color: var(--ink); text-decoration: none;
}
.brand-logo { flex: none; width: auto; height: 1.6em; }
.brand-name { display: inline-flex; flex-direction: column; gap: .3rem; }
.brand-name::after {
  content: ""; display: block; width: 1.3em; height: 3px; border-radius: 2px;
  background: var(--mark);
}
.brand:hover { color: var(--ink); }

/* --- Buttons -------------------------------------------------------------
   The primary button is butter with near-black words. Everything else is a
   paper button with a rule, or a ghost with no edge at all.
   ------------------------------------------------------------------------ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  padding: .58em 1.05em;
  font: inherit; font-weight: 600; font-size: .95rem; line-height: 1.25;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition: background .14s, border-color .14s, color .14s, transform .06s;
}
.btn:hover { background: var(--paper-sunken); color: var(--ink); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; transform: none; }

.btn-primary {
  background: var(--brand-fill);
  border-color: var(--brand-edge);
  color: var(--brand-ink);
}
.btn-primary:hover { background: var(--brand-fill-hover); border-color: var(--brand-edge); color: var(--brand-ink); }

/* Kept as a name for the plan page; with one colour it is the primary button. */
.btn-accent { background: var(--brand-fill); border-color: var(--brand-edge); color: var(--brand-ink); }
.btn-accent:hover { background: var(--brand-fill-hover); color: var(--brand-ink); }

.btn-danger { color: var(--danger); border-color: var(--rule-strong); background: transparent; }
.btn-danger:hover { background: var(--danger-tint); color: var(--danger); border-color: var(--danger); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-soft); }
.btn-ghost:hover { background: var(--paper-sunken); color: var(--ink); }

.btn-lg { padding: .82em 1.5em; font-size: 1.03rem; }
.btn-sm { padding: .38em .72em; font-size: .875rem; }
.btn-block { display: flex; width: 100%; }

/* --- Forms --------------------------------------------------------------- */

label { display: block; font-weight: 600; font-size: .9rem; margin-bottom: .4em; }
.field + .field { margin-top: 1.1rem; }
.field-hint { font-size: .875rem; color: var(--ink-soft); margin: .4em 0 0; max-width: 62ch; }

/* --- The hint ------------------------------------------------------------
   A longer explanation folded behind a small i, using the platform's own
   popover: no JavaScript, Esc and a click outside close it, and it sits in the
   top layer so no card clips it. An i earns its place only where a reader has
   a real question the screen does not already answer.
   ------------------------------------------------------------------------ */

.hint {
  display: inline-flex; align-items: center;
  padding: 0; margin: 0 0 0 .1em;
  border: 0; background: none;
  color: var(--ink-faint);
  cursor: pointer;
  vertical-align: -.15em;
}
.hint:hover { color: var(--brand); }
.hint .ico::before { width: 1.05em; height: 1.05em; }
.picker-legend .hint, .rail-title .hint { margin-left: -.15em; }
.hint-host { display: flex; align-items: center; gap: .3rem; }

.hint-pop {
  width: min(30rem, calc(100vw - 2rem));
  max-height: min(24rem, calc(100vh - 2rem));
  overflow-y: auto;
  padding: .9rem 1rem;
  font-size: .875rem; line-height: 1.55; color: var(--ink-soft);
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}
.hint-pop p { margin: 0; max-width: none; }
.hint-pop p + p { margin-top: .7em; }
.hint-pop strong { color: var(--ink); }

@supports (position-area: block-end) {
  .hint-pop {
    inset: auto;
    position-area: block-end span-inline-end;
    position-try-fallbacks:
      block-end span-inline-start,
      block-start span-inline-end,
      block-start span-inline-start;
    margin: .4rem 0;
  }
}

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="search"], input[type="tel"], input[type="date"], input[type="time"],
select, textarea {
  width: 100%;
  padding: .6em .75em;
  font: inherit;
  color: var(--ink);
  background: var(--paper-field);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  transition: border-color .14s, box-shadow .14s;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none; border-color: var(--brand); box-shadow: var(--ring);
}
input[type="checkbox"], input[type="radio"] { accent-color: var(--brand); width: auto; }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px; box-shadow: none;
}
textarea { min-height: 5em; resize: vertical; }
input:disabled, select:disabled, textarea:disabled { background: var(--paper-sunken); color: var(--ink-faint); }
::placeholder { color: var(--ink-faint); opacity: 1; }
/* The browser's own arrow sits against the right edge; this one is inset like the text.
   After the disabled rule, whose `background` shorthand would otherwise wipe it. */
select:not([multiple]), select:not([multiple]):disabled {
  appearance: none;
  padding-right: 2.4em;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right .75em center;
  background-size: 1em;
}

fieldset { border: 1px solid var(--rule); border-radius: var(--radius-lg); padding: 1rem; margin: 0 0 1rem; }
legend { font-weight: 600; padding-inline: .4em; }

/* --- Surfaces ------------------------------------------------------------ */

.card {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 1.35rem;
}
.card + .card { margin-top: 1rem; }
.card-flush { padding: 0; overflow: hidden; }

/* A sentence about the state of things. A tinted block and nothing else: no
   stripe down the side, no icon, no border shouting. */
.notice {
  background: var(--brand-tint);
  border-radius: var(--radius-lg);
  padding: .85rem 1.1rem;
  max-width: none;
}
.notice > :last-child { margin-bottom: 0; }
.notice-error { background: var(--danger-tint); }
.notice-warn  { background: var(--warn-tint); }
.notice-done  { background: var(--done-tint); }

/* "Saved", for a save that stays on the page (UI.toast): solid green at the top,
   over the sticky bars. Paper on --done reads in both modes, since the dark
   --done is light. It floats, so it is the one small thing with the large shadow. */
.toast {
  position: fixed; left: 50%; top: .75rem; z-index: 50;
  transform: translate(-50%, -.5rem);
  padding: .3rem .9rem .3rem .75rem;
  background: var(--done); color: var(--paper);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  font-size: .92rem; font-weight: 600;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .18s, transform .18s, visibility 0s .18s;
}
.toast-on {
  opacity: 1; visibility: visible; transform: translate(-50%, 0);
  transition: opacity .18s, transform .18s;
}

.tag {
  display: inline-flex; align-items: center; gap: .35em;
  padding: .14em .55em;
  font-size: .78rem; font-weight: 600; letter-spacing: .02em;
  border-radius: var(--radius);
  background: var(--paper-sunken); color: var(--ink-soft);
  white-space: nowrap;
}
.tag + .tag { margin-left: .3rem; }
.tag-done   { background: var(--done-tint);   color: var(--done); }
.tag-open   { background: var(--warn-tint);   color: var(--warn); }
.tag-late   { background: var(--danger-tint); color: var(--danger); }
.tag-req    { background: var(--brand-tint);  color: var(--brand-text); }
.tag-accent { background: var(--brand-tint);  color: var(--brand-text); }
.tag-warn   { background: var(--warn-tint);   color: var(--warn); }
.tag-line   { background: transparent; color: var(--ink-soft); box-shadow: inset 0 0 0 1px var(--rule-strong); }

/* --- Tables -------------------------------------------------------------- */

.table-scroll { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: .95rem; }
table.data th, table.data td { padding: .75rem .9rem; text-align: left; border-bottom: 1px solid var(--rule); }
table.data thead th {
  padding-top: .85rem; padding-bottom: .6rem;
  font-size: .74rem; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--rule-strong);
}
table.data tbody tr { transition: background .12s; }
table.data tbody tr:hover { background: var(--accent-row); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* The row is the link: the name is a real anchor (Tab, middle-click, screen
   readers), and the rest of the row repeats it with a click handler. */
table.data tbody tr.row-link,
table.data tbody tr.row-link td { cursor: pointer; }
table.data .row-name { color: inherit; text-decoration: none; }

/* --- Utilities ----------------------------------------------------------- */

.skip-link {
  position: absolute; left: -9999px;
  background: var(--brand-fill); color: var(--brand-ink); padding: .6em 1em; border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; top: 0; z-index: 100; }

.spinner {
  width: 1em; height: 1em; border-radius: 50%; flex: none;
  border: 2px solid var(--rule-strong); border-top-color: var(--brand);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

[v-cloak] { display: none; }
