/* ==========================================================================
   Overlays: sheets, the item form, the PIN keypad, settings.
   ========================================================================== */

.layer { position: fixed; inset: 0; z-index: 120; pointer-events: none; }
.layer:empty { display: none; }

.scrim {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .62);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  pointer-events: auto;
  animation: fade-in .18s var(--ease);
}
@keyframes fade-in { from { opacity: 0; } }

.sheet {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 32px));
  max-height: min(88vh, 880px);
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: var(--panel);
  border: 1px solid var(--ink);
  border-radius: 0;
  box-shadow: var(--shadow);
  pointer-events: auto;
  overflow: hidden;
  animation: sheet-in .24s var(--ease);
}
@keyframes sheet-in {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 18px)) scale(.97); }
}
.sheet.is-wide { width: min(720px, calc(100vw - 32px)); }

.sheet-head {
  display: flex; align-items: center; gap: 12px;
  padding: 20px 20px 16px 24px;
  border-bottom: 1px solid var(--line);
}
.sheet-head h2 {
  font-size: 24px; font-weight: 400;
  font-variant: small-caps; letter-spacing: .05em;
}
.sheet-close {
  margin-left: auto;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--panel); color: var(--ink-2);
  cursor: pointer; font-size: 20px; line-height: 1;
}
.sheet-close:hover { background: var(--panel-3); color: var(--ink); }

.sheet-body {
  padding: 22px 24px;
  overflow-y: auto;
  display: grid; gap: 18px;
  align-content: start;
}
.sheet-foot {
  display: flex; gap: 10px;
  padding: 16px 24px calc(18px + var(--safe-b));
  border-top: 1px solid var(--line);
  background: var(--panel-2);
}
.sheet-foot .grow { flex: 1; }

/* On a phone a sheet is the screen.
   It used to slide up from the bottom and stop wherever its content ran out,
   which left a strip of calendar showing above it that nobody could use, and
   put the buttons hard against the bottom edge of the glass. Now every sheet
   fills the screen and its content sits in the middle of it; only the keypad
   still lives down where the thumb is, and even that is lifted clear of the
   edge. See the block at the end of this file, which is where the phone rules
   live. */
@media (max-width: 620px) {
  @keyframes sheet-up { from { opacity: 0; transform: translateY(16px); } }
}

/* --- Field groupings ------------------------------------------------------ */
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 480px) { .pair { grid-template-columns: 1fr; } }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }

/* Points stepper — big targets, no keyboard needed on a tablet. */
.stepper { display: flex; align-items: stretch; gap: 8px; }
.stepper button {
  width: var(--tap); flex: none;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--panel-2); color: var(--ink);
  font-size: 24px; font-weight: 600; line-height: 1;
  cursor: pointer;
}
.stepper button:active { background: var(--panel-3); }
.stepper input {
  flex: 1; min-width: 0;
  text-align: center;
  font-family: var(--sans); font-variant-numeric: tabular-nums;
  font-size: 22px; font-weight: 700;
}

/* Weekday toggles for a weekly repeat. */
.days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.days button {
  min-height: 46px;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--panel); color: var(--ink-3);
  font-family: var(--sans);
  font-size: 11.5px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; cursor: pointer;
  transition: background .13s var(--ease), color .13s var(--ease);
}
.days button[aria-pressed="true"] {
  background: var(--ink); color: var(--bg); border-color: var(--ink);
}

.hint { font-size: 13.5px; color: var(--ink-3); line-height: 1.55; font-style: italic; }
.sub  { display: grid; gap: 14px; padding: 15px; background: var(--panel-2);
        border: 1px solid var(--line); border-radius: var(--r); }

/* --- PIN keypad -----------------------------------------------------------
   Four digits, one hand, no keyboard. The dots fill left to right and the
   whole thing shakes on a wrong PIN rather than showing a message nobody
   reads. */
.pin { display: grid; gap: 22px; justify-items: center; padding: 6px 0 2px; }
.pin-who, .pin-hint { display: flex; align-items: center; gap: 10px; font-size: 16px; color: var(--ink-2); }

/* Offered where it is actually wanted: at the keypad, by the person who has
   just proved who they are. The same standing arrangement as the switch in
   Settings, which is where it can be withdrawn. */
.pin-keep {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 2px;
  font-size: 15px; color: var(--ink-2);
  cursor: pointer;
}
.pin-keep input { width: 20px; height: 20px; accent-color: var(--ink); }
.pin-dots { display: flex; gap: 16px; }
.pin-dot {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2.5px solid var(--line-2);
  transition: background .14s var(--ease), border-color .14s var(--ease), transform .14s var(--ease);
}
.pin-dot.is-on { background: var(--ink); border-color: var(--ink); transform: scale(1.14); }
.pin.is-wrong { animation: shake .4s var(--ease); }
.pin.is-wrong .pin-dot { border-color: var(--bad); background: transparent; }

.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  width: min(320px, 100%);
}
.keypad button {
  height: 72px;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--panel-2); color: var(--ink);
  font-family: var(--mono);
  font-size: 27px; font-weight: 650;
  cursor: pointer;
  transition: background .1s var(--ease), transform .08s var(--ease);
}
.keypad button:active { background: var(--panel-3); transform: scale(.95); }
.keypad button.is-quiet { background: transparent; border-color: transparent; font-size: 17px; font-family: var(--sans); color: var(--ink-2); }

/* --- "Who did it?" picker -------------------------------------------------- */
.picker { display: grid; gap: 10px; }
.picker button {
  display: flex; align-items: center; gap: 14px;
  min-height: 68px; padding: 0 18px;
  border: 1px solid var(--line-2); border-left: 4px solid var(--dot);
  border-radius: var(--r);
  background: var(--panel-2); color: var(--ink);
  font-size: 19px;
  cursor: pointer; text-align: left;
}
.picker button:active { background: var(--panel-3); }
.picker .credits {
  margin-left: auto;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  color: var(--ink-3); font-size: 16px;
}

/* --- Settings rows -------------------------------------------------------- */
.setting {
  display: flex; align-items: center; gap: 14px;
  padding: 15px 0;
  border-bottom: 1px solid var(--line);
}
.setting:last-child { border-bottom: 0; }
.setting-text { flex: 1; min-width: 0; display: grid; gap: 3px; }
.setting-text b {
  font-size: 12px; font-weight: 600; font-family: var(--sans);
  letter-spacing: .2em; text-transform: uppercase; color: var(--ink-2);
}
.setting-text span { font-size: 14px; color: var(--ink-3); line-height: 1.5; font-style: italic; }

/* A row whose control is too big to sit beside its label. */
.setting.is-stacked { display: block; }
.setting.is-stacked .setting-text { margin-bottom: 12px; }

/* A stacked row that still wants a button up on the title line. */
.setting-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 12px; }
.setting-head .setting-text { margin-bottom: 0; }
.setting-head .btn { flex: none; }

/* --- Settings, in groups --------------------------------------------------
   A rule and a standing head, the way a section of a newspaper is separated
   from the one above it: enough to stop the eye, not enough to shout.        */
.sgroup + .sgroup { margin-top: 30px; }
.sgroup-head {
  margin-bottom: 4px;
  padding-bottom: 8px;
  border-bottom: 3px double var(--line-2);
}
/* The section head is set in the body face, big enough to be read as a head
   rather than as another row label — the row labels are the small caps. */
.sgroup-head h3 {
  margin: 0;
  font-family: var(--serif); font-size: 21px; font-weight: 400;
  letter-spacing: .01em; color: var(--ink-1);
}
.sgroup-head p {
  margin: 3px 0 0;
  font-size: 13px; font-style: italic; color: var(--ink-3); line-height: 1.5;
}
/* The last row of a group keeps its rule; the group's own border is the
   separator, so a doubled line at the seam would be one too many. */
.sgroup-body .setting:last-child { border-bottom: 0; }

/* A switch, sized for a thumb rather than a cursor. */
.switch {
  position: relative; flex: none;
  width: 62px; height: 36px;
  border: 0; border-radius: 999px;
  background: var(--panel-3);
  cursor: pointer;
  transition: background .2s var(--ease);
}
.switch::after {
  content: ""; position: absolute;
  top: 4px; left: 4px;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--ink-3);
  transition: transform .2s var(--ease), background .2s var(--ease);
}
.switch[aria-checked="true"] { background: var(--good); }
.switch[aria-checked="true"]::after { transform: translateX(26px); background: #fff; }

.mins { display: flex; align-items: center; gap: 10px; }
.mins-unit { color: var(--ink-3); font-size: 14px; font-style: italic; }

/* The compact stepper: same component as the points one, sized for a row
   rather than for a form, and always visible — the native number field's
   arrows appear on hover, which on a touchscreen means never. */
.stepper-sm { gap: 0; }
.stepper-sm button {
  width: 46px; min-height: 46px;
  font-size: 20px;
  border-radius: var(--r) 0 0 var(--r);
}
.stepper-sm button:last-child { border-radius: 0 var(--r) var(--r) 0; }
.stepper-sm input {
  width: 62px; min-height: 46px;
  border-left: 0; border-right: 0; border-radius: 0;
  font-size: 18px; font-weight: 700;
  padding: 0;
}
/* Both steppers: no browser spinners on top of our own buttons. */
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* --- Wall style picker -----------------------------------------------------
   Three options, each with a schematic of its own layout drawn in rules. The
   miniature is the honest kind: the proportions in it are the proportions the
   real screen uses, so what you pick is what you get. */
.styles { display: grid; gap: 10px; }
.style-opt {
  display: flex; align-items: center; gap: 16px;
  padding: 13px 15px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.style-opt:hover { border-color: var(--ink-3); }
.style-opt[aria-pressed="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  background: var(--panel-2);
}
.style-text { display: grid; gap: 3px; min-width: 0; }
.style-text b {
  font-size: 18px; font-weight: 400;
  font-variant: small-caps; letter-spacing: .05em;
}
.style-text span { font-size: 13.5px; color: var(--ink-3); line-height: 1.45; font-style: italic; }

.style-mini {
  flex: none;
  width: 74px; height: 52px;
  padding: 5px;
  border: 1px solid var(--line-2);
  background: var(--bg);
  display: flex; gap: 3px;
}
.style-mini i { background: var(--line); display: block; }
.style-opt[aria-pressed="true"] .style-mini i { background: var(--ink-3); }

.style-mini.is-broadsheet i { flex: 1; }
.style-mini.is-almanac {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
}
.style-mini.is-bulletin {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: 12px 1fr 1fr;
}
.style-mini.is-bulletin i.band { grid-column: 1 / -1; background: var(--line-2); }

/* --- Release notes ---------------------------------------------------------
   Set like the front matter of a book: the version in the margin, the headline
   in the serif, and the detail in plain sentences underneath. A changelog is
   read once and skimmed; anything that needs a legend to decode has failed. */
.notes { display: flex; flex-direction: column; gap: 0; }
.note {
  padding: 16px 0;
  border-bottom: 1px dotted var(--line);
}
.note:last-child { border-bottom: 0; }
.note:first-child { padding-top: 4px; }

.note-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 5px;
}
.note-v {
  font-family: var(--sans);
  font-size: 12.5px; font-weight: 700;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.note-kind {
  font-family: var(--sans);
  font-size: 9px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  padding: 2px 6px;
  border: 1px solid var(--line-2);
  color: var(--ink-3);
}
.note.is-feature .note-kind { border-color: var(--good); color: var(--good); }
.note.is-major .note-kind {
  border-color: var(--ink); color: var(--bg); background: var(--ink);
}
.note-date {
  margin-left: auto;
  font-size: 12px; font-style: italic; color: var(--ink-3);
}
.note-hd {
  font-size: 19px; font-weight: 400; line-height: 1.25;
  letter-spacing: -.005em;
  text-wrap: balance;
}
.note-lines { margin: 7px 0 0; display: grid; gap: 5px; }
.note-lines li {
  font-size: 14.5px; line-height: 1.5; color: var(--ink-2);
  padding-left: 14px; position: relative;
}
.note-lines li::before {
  content: "—";
  position: absolute; left: 0;
  color: var(--ink-3);
}

/* The version number in Settings, which is also the way in. */
.about { display: grid; gap: 8px; justify-items: start; }
.version {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 12px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase;
  cursor: pointer;
}
.version:hover { border-color: var(--ink); }
.version svg { color: var(--ink-3); }

/* ==========================================================================
   Two-step sign-in: the code to scan, the key to type, the codes to keep
   ========================================================================== */

.totp { display: grid; grid-template-columns: auto 1fr; gap: 22px; align-items: start; }
.totp-text { display: grid; gap: 10px; }
.totp-text p { margin: 0; font-size: 15px; line-height: 1.5; }

/* The code is drawn here, not fetched from anywhere: the key it carries is a
   secret and has no business being handed to a chart service. */
.qr {
  padding: 12px;
  background: #fff;                 /* a scanner wants white quiet zones, in either theme */
  border: 1px solid var(--line);
  line-height: 0;
}
.qr svg { display: block; }

.totp-secret {
  display: block;
  padding: 9px 11px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 14.5px; letter-spacing: .12em;
  word-break: break-all;
  user-select: all;                 /* one tap selects the lot */
}

.codes {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  padding: 14px;
  border: 1px solid var(--line);
  background: var(--panel-2);
}
.codes code {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 15px; letter-spacing: .06em;
  text-align: center;
  padding: 4px 0;
  user-select: all;
}

@media (max-width: 560px) {
  .totp { grid-template-columns: 1fr; justify-items: center; }
  .totp-text { width: 100%; }
}

/* ==========================================================================
   An event, read out loud (and closing by itself)
   ========================================================================== */

.ev { display: grid; gap: 14px; }
.ev-head { display: flex; align-items: center; gap: 8px; color: var(--ink-3); }
.ev-facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 12px 26px; margin: 0;
}
.ev-facts div { display: grid; gap: 3px; }
.ev-facts dt {
  font-family: var(--sans); font-size: 9.5px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3);
}
.ev-facts dd { margin: 0; font-size: 19px; line-height: 1.25; }
.ev-who { display: inline-flex; align-items: center; gap: 7px; }
.ev-notes {
  padding: 12px 14px;
  background: var(--panel-2);
  border-left: 3px solid var(--line-2);
  font-size: 17px; line-height: 1.5;
  white-space: pre-wrap;
}
.ev-foot { font-style: italic; }

/* The card says how long it has left rather than vanishing without warning. */
.ev-timer {
  height: 3px; margin-top: 16px;
  background: var(--line);
  overflow: hidden;
}
.ev-bar {
  display: block; height: 100%;
  background: var(--ink-2);
  transform-origin: left center;
}

/* --- The rooms, managed ----------------------------------------------------
   .cat-row, not .cat: .cat is the category printed on a chore, and a layout
   rule with that name would land on every title in the app. One collision like
   that has already cost an afternoon. */
.cats { display: grid; gap: 8px; }
.cat-row { display: flex; align-items: center; gap: 8px; }
.cat-row .cat-name { flex: 1; min-width: 0; }

/* --- where an event is, as something to press ----------------------------- */
.ev-place {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 4px;
  padding: 8px 12px;
  border: 1px solid var(--line-2);
  background: var(--panel-2);
  color: var(--ink);
  font-size: 17px;
  text-decoration: none;
}
.ev-place:hover { border-color: var(--ink); }
.ev-place svg { color: var(--ink-3); flex: none; }

/* --- the handle a category is dragged by ---------------------------------- */
.cat-grip {
  flex: none;
  /* Without this a touch drag scrolls the sheet instead of moving the row. */
  touch-action: none;
  width: 40px; min-height: 44px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-3);
  font-size: 17px; line-height: 1;
  cursor: grab;
}
.cat-grip:hover { color: var(--ink); border-color: var(--line); }
.cat-grip:active { cursor: grabbing; }
/* The neighbours glide; the row under the finger does not, because it is
   already exactly where the finger is. */
.cats.is-sorting .cat-row { transition: transform .14s var(--ease); }
.cats.is-sorting .cat-row.is-dragging { transition: none; position: relative; z-index: 2; }
.cat-row.is-dragging { opacity: .75; box-shadow: var(--shadow); }

/* ==========================================================================
   Phones
   --------------------------------------------------------------------------
   A sheet on a phone is a bottom sheet (thumb reach beats symmetry), and the
   big ones — Settings, the item form, the release notes — take the whole
   screen rather than leaving a strip of calendar peeking out above them that
   nobody can use anyway.

   The keypad is the exception and stays exactly where it was: its whole point
   is being reachable without shifting your grip.
   ========================================================================== */
@media (max-width: 620px) {
  /* Every sheet, whatever its width class, is the whole screen. The classes are
     listed rather than relying on `.sheet` alone because `.is-wide` sets its own
     width and outranks a single-class rule — which is how a "wide" sheet stayed
     720px on a 390px screen and hung off the right-hand edge. */
  .sheet,
  .sheet.is-wide,
  .sheet.is-full {
    top: 0; bottom: 0; left: 0; right: 0;
    transform: none;
    width: 100%; max-width: none;
    height: 100dvh;
    max-height: 100dvh;
    border: 0;
    border-radius: 0;
    animation: sheet-up .24s var(--ease);
  }

  .sheet-head { padding: 16px 14px 13px 18px; }
  .sheet-head h2 { font-size: 21px; }

  /* `safe center` and not plain `center`: short content sits in the middle of
     the screen, which is what a half-empty sheet should do, but a long form
     still starts at the top and scrolls instead of having its first field
     pushed off above the scroll origin where it cannot be reached. */
  .sheet-body {
    padding: 18px 16px;
    gap: 16px;
    align-content: safe center;
  }

  /* The buttons are lifted well clear of the bottom edge. On a tall phone the
     very bottom of the glass is both the hardest place to reach and where the
     system's own gesture bar lives, so a row of buttons flush against it is
     both a stretch and a mis-tap. The foot keeps its own background all the
     way down, so the space reads as margin rather than as a gap. */
  .sheet-foot {
    padding: 14px 16px calc(34px + var(--safe-b));
    flex-wrap: wrap;
  }
  .sheet-foot .btn { min-height: 52px; }

  /* The keypad is the one thing that does not take the whole screen: its whole
     point is being reachable without shifting your grip, and stretched to full
     height it left a hand's width of empty page above the keys. A card, inset
     from three edges and standing clear of the bottom one — low enough to
     reach, far enough up that the bottom row is not on the gesture bar. */
  .sheet:has(.pin) {
    top: auto;
    bottom: calc(14px + var(--safe-b));
    left: 12px; right: 12px;
    width: auto;
    height: auto;
    max-height: 92dvh;
    border: 1px solid var(--ink);
  }
  .sheet:has(.pin) .sheet-body {
    align-content: end;
    padding-bottom: 22px;
  }

  /* Two 72px keys plus 22px gaps do not fit a 360px screen with room to spare
     for the dots above them. */
  .keypad { gap: 8px; width: min(300px, 100%); }
  .keypad button { height: 62px; font-size: 24px; }
  .pin { gap: 16px; }

  .totp { gap: 14px; }
  .codes { grid-template-columns: 1fr; }
}

/* Short and wide — a phone on its side, or a small tablet in landscape. The
   keypad has to fit above the fold or the last row is unreachable. */
@media (max-height: 560px) and (orientation: landscape) {
  .sheet { max-height: 98dvh; }
  .keypad button { height: 46px; font-size: 20px; }
  .pin { gap: 10px; }
  .pin-dot { width: 13px; height: 13px; }
}
