/*
 * Sessions: the portal's look. Two colours and their tints, the system font, one column.
 *
 * Ink (#1e1d22) on ground (#f3f2ec). Every other shade is ink laid over ground at a set
 * strength: muted text, faint text, a hairline, a fill, a pressed fill. States are said in
 * words and weight, never in colour. Nothing is wider than a 320px screen; the column
 * simply centres on a wider one. Lists are inset groups, buttons are full width, the
 * floating pill at the bottom is the only thing fixed to the screen.
 */
:root {
  --ink: #1e1d22;
  --ground: #f3f2ec;
  /* 66%: clears 4.5:1 on the list fill as well as the bare ground (review, 2026-10-04). */
  --muted: rgba(30, 29, 34, 0.66);
  --faint: rgba(30, 29, 34, 0.45);
  --hair: rgba(30, 29, 34, 0.12);
  --fill: rgba(30, 29, 34, 0.06);
  --pressed: rgba(30, 29, 34, 0.10);
  --radius: 16px;
  --radius-btn: 14px;
  --tap: 44px;
  --pill-h: 60px;
  --pill-gap: 12px;
  /* The pill and its gap: content ends above this, and the sticky Book button sits on it. */
  --pill-room: calc(var(--pill-h) + var(--pill-gap) + var(--pill-gap));
  --ease: 160ms ease;
  color-scheme: light;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.45;
  /* clip, not hidden: a hidden overflow on the body makes the sticky Book button stop sticking */
  overflow-x: clip;
  overflow-wrap: anywhere;
  -webkit-font-smoothing: antialiased;
}

body.in { padding-bottom: calc(var(--pill-room) + 24px + env(safe-area-inset-bottom)); }
/* An answer scrolled into view stops above the pill, not under it. */
#ab-plan, #ab-flash, #ab-change, #chg-plan { scroll-margin-top: 16px; scroll-margin-bottom: calc(var(--pill-room) + env(safe-area-inset-bottom)); }

h1 {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 12px 0 20px;
}
h2.sh, p.sh {
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 24px 0 8px 16px;
}
/* The week headers on Book keep their case, "This week", "w/c Mon 20 Oct", in the header style otherwise (the date reads as every other date). */
h2.sh.wk { text-transform: none; }
p.sh { margin: 0 0 4px; }
p { margin: 0 0 12px; }
a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--hair); text-underline-offset: 2px; }
b { font-weight: 600; }
ul { list-style: none; margin: 0; padding: 0; }

.app {
  max-width: 560px;
  margin: 0 auto;
  padding: calc(16px + env(safe-area-inset-top)) 20px 0;
}
.pad { padding: 16px 0; }

.muted, .sec { color: var(--muted); }
.sec { font-size: 15px; }
.fine { font-size: 13px; color: var(--muted); }
.lead { margin-bottom: 24px; }
.group { margin-bottom: 24px; }
.flash { font-weight: 600; margin: 0 0 16px; }
.flash[hidden] { display: none; }
.msg { min-height: 1.2em; margin: 8px 0 0; font-size: 15px; }
/* The sentence above the Book list keeps its line when its words go, so the first tick does not move the list. */
p.hint { min-height: 22px; }
.msg:empty { min-height: 0; margin: 0; }
.err { font-weight: 600; color: var(--ink); }
.ok { color: var(--ink); }
.empty { color: var(--muted); padding: 14px 16px; }
.big { font-size: 28px; font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; }
.back { margin: 4px 0 0 -8px; }

/* ---------- inset grouped lists ---------- */
.list {
  background: var(--fill);
  border-radius: var(--radius);
  overflow: hidden;
}
.row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 12px 16px;
  margin: 0;
  background: none;
  border: 0;
  color: var(--ink);
  font: inherit;
  text-align: left;
  text-decoration: none;
}
/* A hairline above every row but the first, inset from the left; so the last row has none. */
.list > .row:not(:first-child)::before {
  content: "";
  position: absolute;
  left: 16px;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--hair);
}
label.pick {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 12px;
  min-height: 52px;
  margin: -12px -16px;
  padding: 12px 16px;
  font-size: 17px;
  font-weight: 400;
  cursor: pointer;
}
.row .main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row .label { font-size: 17px; }
.row .val { color: var(--muted); font-size: 15px; flex: none; max-width: 45%; text-align: right; }
.row .chev { flex: none; color: var(--faint); }
.row.off { color: var(--muted); }
button.row, a.row { cursor: pointer; transition: background var(--ease); }
button.row:active, a.row:active { background: var(--pressed); }
.row.next .label { font-size: 17px; font-weight: 600; }
.row.num .label { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
/* A row asking for a second tap: the outlined button takes its own line under the label, so the
   dates or the device name stay readable at 320px (review, 2026-10-04). */
.row.ask { flex-wrap: wrap; }
.row.ask .main { flex: 1 1 100%; }
.row.ask .btn.inline { width: 100%; }
.row .form { flex: 1; min-width: 0; }
/* A time-away entry: the dates, then Change (and I'm back or Remove). On a narrow phone the buttons
   take their own line under the dates, right-aligned, so the dates are never squeezed (5 October). */
.row.ab { flex-wrap: wrap; row-gap: 0; }
.row.ab .main { flex: 1 1 150px; }
.row.ab .acts { flex: none; flex-wrap: nowrap; gap: 0; margin: -8px -12px -8px auto; }
/* The change panel and its answer: the same rhythm as recording time away. */
.change { margin-top: 20px; }
.change form .btn { margin-top: 12px; }
.change .two { margin-top: 4px; }
h3.sh { font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 20px 0 8px 16px; }
.list.done { margin: 0 0 16px; }
.panel { padding: 4px 16px 16px; }
.panel:empty { display: none; }
.panel p { margin: 8px 0; }

/* ---------- buttons ---------- */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  padding: 12px 18px;
  margin: 12px 0 0;
  border-radius: var(--radius-btn);
  border: 0;
  background: var(--ink);
  color: var(--ground);
  font: inherit;
  font-size: 17px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: box-shadow var(--ease);
}
.btn.primary { background: var(--ink); color: var(--ground); }
.btn.secondary { background: var(--fill); color: var(--ink); }
.btn.outline { background: none; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.btn.tertiary { background: none; color: var(--ink); min-height: var(--tap); padding: 8px 12px; }
.btn.inline { width: auto; display: inline-flex; margin: 0; }
.btn:active { box-shadow: inset 0 0 0 999px var(--pressed); }
.btn.outline:active { box-shadow: inset 0 0 0 1px var(--ink), inset 0 0 0 999px var(--pressed); }
.btn[disabled] { opacity: 0.4; cursor: default; }
.btn[disabled]:active { box-shadow: none; }
/* The Book button waiting for a choice reads in full: ink on the fill, not a faded ink button. Faded while busy,
   as any other disabled primary is (Renew now while the secure page opens). */
.bar .btn.primary[disabled]:not(.busy) { opacity: 1; background: var(--fill); color: var(--ink); }
.acts { display: flex; flex-wrap: wrap; gap: 4px 8px; margin-top: 8px; }
.acts .btn { width: auto; margin: 0; }
.choices { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 8px 0; }
.chip {
  min-height: var(--tap);
  padding: 8px 10px;
  border-radius: var(--radius-btn);
  border: 0;
  background: var(--fill);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
}
.chip:active { background: var(--pressed); }
.links { display: flex; flex-wrap: wrap; align-items: center; gap: 0 8px; margin: 8px 0 0; }

/* ---------- inputs ---------- */
label { display: block; font-size: 15px; font-weight: 600; margin: 16px 0 6px; }
label.inline { display: inline; margin: 0; font-weight: 400; }
input[type="email"], input[type="text"], input[type="password"], input[type="date"], select {
  width: 100%;
  min-height: 52px;
  padding: 12px 16px;
  border: 0;
  border-radius: var(--radius-btn);
  background: var(--fill);
  color: var(--ink);
  font: inherit;
  font-size: 16px; /* 16px stops iOS zooming into the field */
  -webkit-appearance: none;
  appearance: none;
}
input[type="date"] { min-width: 0; }
/* The password field with Show or Hide inside it, on the right; the field leaves room for the word. */
.pwbox { position: relative; }
.pwbox input { padding-right: 76px; }
.pwbox .btn.tertiary.inline { position: absolute; top: 4px; right: 4px; min-height: var(--tap); padding: 8px 12px; font-size: 15px; }
.pw-rule { margin: 6px 0 0 16px; }
/* The password screen's username field: there for the keychain, never seen. Clipped, not display:none, which Safari's autofill ignores. */
input.vh, .vh { position: absolute; width: 1px; height: 1px; min-height: 0; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; opacity: 0; pointer-events: none; }
select { padding-right: 16px; }
.two { display: grid; grid-template-columns: 1fr; gap: 0 12px; }
form .btn { margin-top: 20px; }
input:focus-visible, select:focus-visible, button:focus-visible, a:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* The round check on a Book row: the input is the 44px tap, the ring is drawn beside it. */
.check { position: relative; flex: none; width: var(--tap); height: var(--tap); }
.check input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.check .tick {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid var(--faint);
  transition: background var(--ease), border-color var(--ease);
}
.check .tick::after {
  content: "";
  position: absolute;
  left: 9px;
  top: 4px;
  width: 6px;
  height: 12px;
  border: solid var(--ground);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0;
}
.check input:checked + .tick { background: var(--ink); border-color: var(--ink); }
.check input:checked + .tick::after { opacity: 1; }
.check input:focus-visible + .tick { outline: 2px solid var(--ink); outline-offset: 2px; }
.row.pick { cursor: pointer; }

/* The switch: ink when on, a hairline ring when off. The whole row is the tap. */
.switch {
  flex: none;
  position: relative;
  width: 51px;
  height: 31px;
  border-radius: 999px;
  background: var(--hair);
  transition: background var(--ease);
}
.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: var(--ground);
  box-shadow: 0 1px 2px var(--hair);
  transition: transform var(--ease);
}
[aria-checked="true"] .switch { background: var(--ink); }
[aria-checked="true"] .switch::after { transform: translateX(20px); }

/* ---------- You: adding Face ID, and Sign out ---------- */
/* A card of its own, so the name reads as a field (ground on the fill) and the button as a button (outlined). */
.addkey { margin-top: 8px; padding: 0 16px 16px; background: var(--fill); border-radius: var(--radius); }
.addkey label { margin-top: 0; padding-top: 16px; }
.addkey input[type="text"] { background: var(--ground); }
.addkey .btn { margin-top: 12px; }
/* The last thing on You, set apart from everything above it. */
.list.out { margin-top: 40px; }

/* ---------- Book ---------- */
/* The quick choice: its label on one line, then the number and Select side by side. */
.quick { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 12px 16px; background: var(--fill); border-radius: var(--radius); margin-bottom: 8px; }
.quick label { flex: 1 1 100%; margin: 0; }
.quick select { flex: 1; min-width: 0; width: auto; min-height: var(--tap); padding: 8px 12px; background: var(--ground); }
.quick .btn { flex: none; width: auto; margin: 0; }
/* Sticks to the bottom of the screen and its ground runs all the way down behind the pill, so the
   pill floats over the bar's own colour and no list row shows beside or under it (pre-deploy check,
   4 Oct: rows showed through in the strip around the pill). Its content still ends a gap above the
   pill. The negative margin gives that room back, so the page is no longer than before. */
.bar {
  position: sticky;
  bottom: 0;
  background: var(--ground);
  padding: 8px 0 calc(var(--pill-room) + env(safe-area-inset-bottom));
  margin-top: 16px;
  margin-bottom: calc(-1 * (var(--pill-room) + env(safe-area-inset-bottom)));
}
.bar .btn { margin-top: 8px; }
.running { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: var(--tap); }
.running p { margin: 0; font-weight: 600; }
.nudge { margin: 8px 0; }
.nudge p { margin: 0 0 4px; }

/* ---------- Packages: one block per package, its history open under it ---------- */
.list.pkg { margin-bottom: 12px; }
.pk-head .main .sec + .sec { font-size: 13px; }
.pk-head .top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.pk-head .top .label { flex: 1; min-width: 0; }
.pk-head .val { flex: none; color: var(--ink); font-size: 15px; font-weight: 600; white-space: nowrap; }
.pk-head .chev svg { transition: transform var(--ease); }
.pk-head[aria-expanded="true"] .chev svg { transform: rotate(90deg); }
.pk-log:empty { display: none; }
/* The history's lines sit under the head with the list's own hairline, a size down from it. */
.pk-log > .row::before, .pk-log > .pk-sum::before {
  content: "";
  position: absolute;
  left: 16px;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--hair);
}
.pk-sum { position: relative; margin: 0; padding: 12px 16px; font-size: 15px; font-weight: 600; }
.pk-log .row { min-height: 44px; padding-top: 10px; padding-bottom: 10px; }
.pk-log .row .label { font-size: 15px; }
.pk-log .row .sec { font-size: 13px; }
.pk-log .empty { position: relative; margin: 0; }
/* The credit each line moved, "-1" or "+1", in figures that line up down the history. */
.row .val.delta { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; min-width: 2.2em; max-width: none; }

/* ---------- the pill: three places, floating above the safe area ---------- */
.pill {
  position: fixed;
  left: 50%;
  bottom: calc(var(--pill-gap) + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  height: var(--pill-h);
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(30, 29, 34, 0.92);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
}
.pill[hidden] { display: none; }
.pill a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 72px;
  height: var(--pill-h);
  color: rgba(243, 242, 236, 0.55);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  transition: color var(--ease);
}
.pill a.on { color: var(--ground); }
.pill svg { width: 24px; height: 24px; }
.icon { width: 24px; height: 24px; flex: none; }

@media (min-width: 420px) {
  .two { grid-template-columns: 1fr 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; transition: none !important; }
}
