/* home.css — the command center's morning (and, after dark, evening) screen.
   The scene is in docs/design-baselines.md §6: their home, at the time of day
   it is. One real material, a linen swatch, lit by the hour (home.js): sun
   through the blinds in the morning, lamplight after dark. The light stays
   behind the day, never in front of it (Conner, 2026-09-24). Every screen
   in the app is built on it; the retired press sheet is gone. */

/* ── Type ──────────────────────────────────────────────────────────────── */

@font-face {
  font-family: 'Alegreya';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/alegreya-roman.woff2') format('woff2');
}
@font-face {
  font-family: 'Alegreya';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/alegreya-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/alegreya-sans-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/alegreya-sans-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/alegreya-sans-700.woff2') format('woff2');
}

/* ── Light ─────────────────────────────────────────────────────────────────
   home.js sets --night (0 by day, 1 with the lamps on), --warm (how far the
   day's light has warmed, 0 at breakfast, 1 at sunset) and --sun (how much
   sun comes through the blinds). Everything that changes with the hour reads
   from those. */

:root {
  --night: 0;
  --warm: 0;
  --sun: 1;
  /* Where the one light comes from (home.js, lightAt): toward it, right and
     down, scaled by how long its shadows are. A shadow falls the other way,
     so something raised n px casts calc(var(--cast-x) * n). */
  --lx: 0.3;
  --ly: -0.85;
  --light-deg: 200deg;
  --cast-x: calc(var(--lx) * -1px);
  --cast-y: calc(var(--ly) * -1px);
  /* Film grain: a still tile of fine noise, dark specks only. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .16 0 0 0 0 .11 0 0 0 0 .07 .5 0 0 0 -.2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");

  /* ── The look, in the studio's names ─────────────────────────────────
     Every look value is one of these, so the design studio (/studio,
     design/studio/options.js) can try a palette or a pair of typefaces on
     the real page just by setting them. The names are the kit's
     (design-persona studio/kit/guardrails.js). Everything else below is
     worked out from them, so change these, never the derived ones.

     Two palettes, because the room has two lights: the kit's names are the
     day (sunlit linen), and --dark-* are the same room with the lamps on.
     body picks one by the hour (below). */

  /* Type: the voice (the day's name, titles, the sentence) and the facts
     (times, places, whose). --fs is one pixel at the default body size, so
     every size in the app is a multiple of it and follows --body-size. */
  --font-display: 'Alegreya', 'Iowan Old Style', Georgia, serif;
  --font-body: 'Alegreya Sans', -apple-system, 'Segoe UI', sans-serif;
  --display-weight: 500;
  --display-size: 48px;
  --body-size: 16px;
  --fs: calc(var(--body-size) / 16);

  /* Spacing and corners, in the kit's names. --s is the base unit; --gap-in
     is the space between lines inside a group (a row's own lines, the rows
     of a list) and --gap-out the space between groups (sections, the
     header, the sheet's edges). Every spacing in the app is a multiple of
     --sp-in or --sp-out, one pixel each at these defaults, so a density
     picked in the studio moves them all in proportion. Controls keep their
     own padding, so every tap area stays at least 44px. Every rounded
     corner is a multiple of --radius (pills and circles stay as they are). */
  --s: 8px;
  --gap-in: calc(var(--s) * 1.5);
  --gap-out: calc(var(--gap-in) * 4);
  --sp-in: calc(var(--gap-in) / 12);
  --sp-out: calc(var(--gap-out) / 48);
  --radius: 12px;

  /* Day: walnut ink on sunlit linen, saddle-leather for what you can tap. */
  --bg: #ebe1d5;            /* the day's sheet, as a solid */
  --surface: #fbf6ee;       /* the lighter linen: cards, the field, the slip */
  --ink: #2b2017;
  --ink-2: #6c6258;         /* the softer voice: places, whose, times */
  --accent: #8b4a1c;
  --line: rgba(43, 32, 23, 0.12);
  /* Delete: the leather's darker, redder side, never a signal red. */
  --brick: #963a20;
  /* Whose it is, at a glance: each of them in their own colour (Conner
     chose it, 2026-09-24). The his-and-hers time blocks will want these. */
  --conner: #46627f;
  --chloe: #5d6c3c;
  /* The tint laid over the cloth photo (half strength by day). */
  --world: #e2d0b6;

  /* Lamps on: the same room after dark. */
  --dark-bg: #37281b;
  --dark-surface: #2a1e15;
  --dark-ink: #f2e5d0;
  --dark-ink-2: #b2a592;
  --dark-accent: #e8a95c;
  --dark-line: rgba(242, 229, 208, 0.12);
  --dark-brick: #cf7150;
  --dark-conner: #a3bcd6;
  --dark-chloe: #bccb91;
  --dark-world: #100a06;   /* laid over the cloth at 80% */

  --serif: var(--font-display);
  --sans: var(--font-body);

  color-scheme: light;
}

/* Lamps on: every colour reads the night palette. It's swapped on body, not
   :root, so the studio (which sets the palette on :root) can try both. */
:root[data-light="night"] { color-scheme: dark; }
:root[data-light="night"] body {
  --bg: var(--dark-bg);
  --surface: var(--dark-surface);
  --ink: var(--dark-ink);
  --ink-2: var(--dark-ink-2);
  --accent: var(--dark-accent);
  --line: var(--dark-line);
  --brick: var(--dark-brick);
  --conner: var(--dark-conner);
  --chloe: var(--dark-chloe);
}

/* Worked out from the palette, in whichever light it is. */
body {
  --ink-soft: var(--ink-2);
  --ink-faint: color-mix(in srgb, var(--ink) 40%, transparent);
  --rule: var(--line);
  --on-accent: var(--surface);
  --on-brick: var(--surface);
  --card: var(--surface);
  --sheet-solid: var(--bg);
  /* The lighter linen the day is laid on. */
  --linen-veil: color-mix(in srgb, var(--surface) 87%, transparent);
  --field: color-mix(in srgb, var(--surface) 94%, transparent);
  --head-ink: var(--ink);
  --head-soft: color-mix(in srgb, var(--ink) 70%, transparent);
  --glass: color-mix(in srgb, var(--surface) 80%, transparent);
  --glass-line: color-mix(in srgb, var(--ink) 14%, transparent);
  /* The cloth's colour where the world meets the bottom of the screen. */
  --world-floor: color-mix(in srgb, var(--world) 50%, #8f684a);
  /* The sections header once something scrolls under it: frosted cloth. */
  --nav-frost: color-mix(in srgb, color-mix(in srgb, var(--world-floor) 85%, var(--surface)) 80%, transparent);
}
:root[data-light="night"] body {
  --world-floor: color-mix(in srgb, var(--dark-world) 80%, #8f684a);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  background: #140d08;
  color: var(--ink);
  font-family: var(--serif);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

/* iOS 26 in the home-screen app (WebKit bug 301108): with the see-through
   status bar, the page is drawn from the top of the screen but the viewport
   is short by the status bar's height, leaving a strip at the bottom no CSS
   can reach. iOS fills it with the page's background, so that background is
   whatever sits just above the strip: the day's linen, or on the lock screen
   the cloth. */
html { background-color: var(--bg); }
html.locked { background-color: color-mix(in srgb, var(--world) 50%, #8f684a); }
html[data-light="night"] { background-color: var(--dark-bg); }
html.locked[data-light="night"] { background-color: color-mix(in srgb, var(--dark-world) 80%, #8f684a); }
body { background: transparent; }

button, input { font: inherit; color: inherit; }

/* Alegreya Sans sets its word space tight (about 0.17em). A touch more for
   reading addresses at arm's length on a phone. */
.monthday, .item-time, .item-place, .item-who, .item-drive, .note-clear, .toast-act, .stale,
.proposal-meta, .proposal-yes, .proposal-no, .add-send,
.toast, .lock-step-sub, .lock-btn, .lock-hint, .lock-recover, .lock-input-wrap input {
  word-spacing: 0.06em;
}
a { color: inherit; }

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

/* ── The world behind everything ───────────────────────────────────────────
   One material, close up: a linen swatch (public/img/home/cloth.jpg, a
   seamless tile at 3x, so 500px across). The hour's light falls on it. */

.world {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: #8f684a url('/img/home/cloth.jpg') 0 0 / 500px 500px;
}
.world > * { position: absolute; inset: 0; }

/* The cloth in the room's light: sunlit linen by day, lamplit after dark,
   crossing over as the lamps come on. */
/* With a photo on the background in the studio, the studio's tint does this
   job, and the studio quiets these itself (they're tints over the surface). */
.world-veil { background: color-mix(in srgb, var(--world) 50%, transparent); opacity: calc(1 - var(--night)); }
.world-dusk { background: color-mix(in srgb, var(--dark-world) 80%, transparent); opacity: var(--night); }

/* Morning sun through the blinds, falling across the cloth. Only the light
   is taken from the photo (window-light-wood-1), none of the room. It lies
   behind the date, faint, and softens as the day goes on; by the time the
   lamps come on it's gone. */
.world-sun, .world-dust {
  inset: auto;
  top: calc(env(safe-area-inset-top) - 70px);
  right: -150px;
  width: 620px;
  height: 509px;
  transform: translateY(calc(var(--warm) * 60px));
}
.world-sun {
  background: url('/img/home/sun.jpg') center / 100% 100% no-repeat;
  mix-blend-mode: screen;
  opacity: calc(var(--sun) * 0.34);
}
/* Dust drifting in that light (home.js, startDust): specks drawn only where
   the photo is bright, lit as the light is. */
.world-dust { pointer-events: none; mix-blend-mode: screen; }

/* Film grain over the cloth: fine and still, like the stock the day is shot
   on. Still, because moving grain would be motion that says nothing. */
.world::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--grain) 0 0 / 160px 160px;
  opacity: calc(0.55 - 0.2 * var(--night));
  pointer-events: none;
}

/* The hour's grade: late light warms the cloth. Soft-light, so the weave
   stays real rather than tinted flat. */
.world-grade {
  background: linear-gradient(180deg,
    rgba(255, 176, 92, calc(var(--warm) * 0.40)) 0%,
    rgba(214, 120, 52, calc(var(--warm) * 0.26)) 70%,
    rgba(214, 120, 52, calc(var(--warm) * 0.18)) 100%);
  mix-blend-mode: soft-light;
  opacity: calc(1 - var(--night));
}

/* After dark: a lamp's warm pool on the cloth, from somewhere above. */
.world-lamp {
  background:
    radial-gradient(110% 58% at 14% -4%, rgba(255, 170, 88, 0.36), rgba(232, 140, 64, 0.12) 46%, transparent 72%);
  mix-blend-mode: screen;
  opacity: var(--night);
}

/* Enough shade at the very top for the phone's own clock and battery,
   which are always drawn in white in the home-screen app. */
.world-top {
  bottom: auto;
  height: calc(env(safe-area-inset-top) + 64px);
  background: linear-gradient(180deg, rgba(34, 22, 13, 0.34), rgba(34, 22, 13, 0));
}

/* The opening shot (home.js, rollShot): a breath in and out to start the
   day (Conner, 2026-09-24: "like a big breathe in and out"). Breathing in,
   the room comes into focus and its light comes up: a dim, soft copy of the
   cloth (.world-haze, blurred once and never again) lifts off it while the
   frame eases back. Then, one at a time, the date, the month, the weather
   and the sentence. Breathing out, the day's sheet rises and settles. About
   three seconds. Only opacity and transform move, which the phone's
   compositor runs smoothly even while the day is being laid out. */
.world-haze { display: none; }
html.shot .world-haze {
  display: block;
  inset: -48px;
  background:
    linear-gradient(rgba(22, 13, 7, 0.34), rgba(22, 13, 7, 0.34)),
    linear-gradient(color-mix(in srgb, var(--world) calc(50% * (1 - var(--night))), transparent), color-mix(in srgb, var(--world) calc(50% * (1 - var(--night))), transparent)),
    linear-gradient(color-mix(in srgb, var(--dark-world) calc(80% * var(--night)), transparent), color-mix(in srgb, var(--dark-world) calc(80% * var(--night)), transparent)),
    #8f684a url('/img/home/cloth.jpg') 0 0 / 500px 500px;
  filter: blur(16px);
  will-change: opacity;
  animation: haze-lift 1900ms cubic-bezier(.45, .05, .35, 1) both;
}
@keyframes haze-lift { to { opacity: 0; } }
html.shot .world { will-change: transform; animation: breathe-in 2600ms cubic-bezier(.45, .05, .35, 1) both; }
@keyframes breathe-in { from { transform: scale(1.04); } }
/* The sections header fades up with the light instead of appearing the
   moment sign-in is confirmed. It fades; it never moves. */
html.shot .sections { animation: nav-in 1200ms cubic-bezier(.45, .05, .35, 1) both; }
@keyframes nav-in { from { opacity: 0; } }
html.shot:not(.shot-go) .head > * { opacity: 0; }
html.shot-go .head > * { animation: rise-in 950ms cubic-bezier(.22, .8, .3, 1) both; }
html.shot-go .head > :nth-child(2) { animation-delay: 200ms; }
html.shot-go .head > :nth-child(3) { animation-delay: 370ms; }
html.shot-go .head > :nth-child(4) { animation-delay: 560ms; animation-duration: 1100ms; }
@keyframes rise-in { from { opacity: 0; transform: translateY(16px); } }
html.shot:not(.shot-go) .sheet { opacity: 0; transform: translateY(34px); }
html.shot-go .sheet { transition: transform 1200ms cubic-bezier(.16, .84, .3, 1) 1050ms, opacity 900ms ease 1050ms; }
/* The dust comes into the light once the breath is over. */
.world-dust { transition: opacity 1600ms ease; }
html.shot .world-dust { opacity: 0; }

/* Arriving: the room's light comes up. */
html.arriving .world { opacity: 0; }
.world { transition: opacity 900ms ease-out; }
/* The light moves only when the hour moves it (home.js adds .lit after the
   first paint), never just because the app opened. */
html.lit .world-veil, html.lit .world-dusk, html.lit .world-sun, html.lit .world-grade, html.lit .world-lamp {
  transition: opacity 2400ms ease, transform 2400ms ease;
}

/* ── Lock (the way in) ─────────────────────────────────────────────────── */

/* The same cloth in the same light as the day behind it: the way in is
   the room you're about to be in, not a different one. */

#lock {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100dvh;
  padding: calc(env(safe-area-inset-top) + 24px) 24px calc(env(safe-area-inset-bottom) + 32px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: var(--head-ink);
}

.lock-name {
  margin: 0 0 28px;
  font-weight: 500;
  font-size: calc(40 * var(--fs));
  line-height: 1.05;
}

.lock-input-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 360px;
  padding: 20px;
  border-radius: calc(var(--radius) * 18 / 12);
  background: var(--glass);
  border: 1px solid var(--glass-line);
  box-shadow: calc(var(--cast-x) * 12) calc(var(--cast-y) * 12) 40px rgba(12, 7, 3, 0.16);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  backdrop-filter: blur(14px) saturate(1.1);
  color: var(--ink);
}
.lock-step-label { font-size: calc(21 * var(--fs)); font-weight: 500; }
.lock-step-sub { margin-top: -6px; font-family: var(--sans); font-size: calc(15 * var(--fs)); color: var(--ink-soft); line-height: 1.4; }
.lock-input-wrap input {
  width: 100%;
  padding: 13px 16px;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 12 / 12);
  background: var(--field);
  color: var(--ink);
  font-size: calc(17 * var(--fs));
  font-family: var(--sans);
}
.lock-input-wrap input::placeholder { color: var(--ink-faint); }
.lock-input-wrap input:focus { outline: none; border-color: var(--accent); }
.lock-btn {
  padding: 13px 16px;
  border: none;
  border-radius: calc(var(--radius) * 12 / 12);
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(16 * var(--fs));
  cursor: pointer;
}
.lock-hint { min-height: 18px; font-family: var(--sans); font-size: calc(14 * var(--fs)); color: var(--accent); }
.lock-recover {
  align-self: flex-start;
  font-family: var(--sans);
  font-size: calc(14 * var(--fs));
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  padding: 6px 0;
}
#qrContainer img { border-radius: calc(var(--radius) * 8 / 12); }
#totpSecretDisplay { font-family: var(--sans); font-size: calc(13 * var(--fs)); word-break: break-all; color: var(--ink-soft); }

/* ── The day ───────────────────────────────────────────────────────────── */

#app {
  display: none;
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100dvh;
}

/* The date sits straight on the cloth, in the light. Shorter than a hero:
   the day below is what she came for. */
.head {
  position: relative;
  min-height: 28vh;
  min-height: 28svh;
  padding: calc(18 * var(--sp-out)) 24px calc(26 * var(--sp-out));
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: var(--head-ink);
}

/* ── Sections: Schedule, Calendar, References, Admin ───────────────────────
   The same header on every screen, in exactly the same place, with the
   current one underlined. It sits in the cloth at the top of a page and
   frosts over only once something scrolls under it (html.scrolled, set in
   home.js). Moving between sections crossfades the page, never the header
   (view-transition-name). */

/* The design studio's slots (design/studio/options.js): wrappers only, so
   they never change the layout. */
[data-slot="nav"], [data-slot="filters"] { display: contents; }

/* The kit's navigation contract (data-k="nav"); this is its house skin. */
.sections { view-transition-name: sections; }
.sections:where([data-skin="house"]) {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  padding: calc(env(safe-area-inset-top) + 2px) 16px 0;
  background: transparent;
  transition: background-color 200ms ease, box-shadow 200ms ease;
}
html.scrolled .sections:where([data-skin="house"]) {
  background: var(--nav-frost);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  backdrop-filter: blur(16px) saturate(1.1);
  box-shadow: 0 1px 0 var(--glass-line);
}
.sections:where([data-skin="house"]) a {
  position: relative;
  padding: 12px 1px 13px;
  font-family: var(--sans);
  font-weight: 500;
  font-size: calc(15 * var(--fs));
  color: var(--head-soft);
  text-decoration: none;
  word-spacing: 0.06em;
  -webkit-tap-highlight-color: transparent;
}
.sections:where([data-skin="house"]) a[aria-current="page"] { color: var(--head-ink); }
.sections:where([data-skin="house"]) a[aria-current="page"]::after {
  content: '';
  position: absolute;
  left: 1px;
  right: 1px;
  bottom: 7px;
  height: 2px;
  border-radius: 1px;
  background: var(--accent);
}

@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 180ms; }

.weekday { margin: 0; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--display-size); line-height: 1; letter-spacing: -0.005em; }
.monthday { margin: calc(6 * var(--sp-in)) 0 0; font-family: var(--sans); font-weight: 500; font-size: calc(16 * var(--fs)); color: var(--head-soft); }
.weather { margin: calc(3 * var(--sp-in)) 0 0; font-family: var(--sans); font-size: calc(16 * var(--fs)); color: var(--head-soft); word-spacing: 0.06em; }
.summary { margin: calc(18 * var(--sp-out)) 0 0; max-width: 21em; font-style: italic; font-size: calc(21 * var(--fs)); line-height: 1.35; text-wrap: pretty; }

/* A lighter linen laid over the cloth: the same weave, in front of it. */
.sheet {
  position: relative;
  padding: calc(26 * var(--sp-out)) 24px calc(env(safe-area-inset-bottom) + 112px);
  min-height: 58vh;
  min-height: 58svh;
  background-color: var(--sheet-solid);
  background-image: var(--grain), linear-gradient(var(--linen-veil), var(--linen-veil)), url('/img/home/cloth.jpg');
  background-size: 160px 160px, auto, 500px 500px;
  border-radius: calc(var(--radius) * 22 / 12) calc(var(--radius) * 22 / 12) 0 0;
  /* Laid on the cloth: its shadow falls away from the room's light, and the
     light catches the edge that faces it. */
  box-shadow:
    inset calc(var(--lx) * -1.5px) calc(var(--ly) * -1.5px) 0 rgba(255, 248, 236, calc(0.4 - 0.28 * var(--night))),
    calc(var(--cast-x) * 14) calc(var(--cast-y) * 4 - 8px) 34px rgba(12, 7, 3, 0.22);
}

/* The day is laid out once it's known, not before: no empty sheet rising. */
.sheet:not([data-ready]) { transform: translateY(14px); opacity: 0; }
.sheet { transition: transform 700ms cubic-bezier(.2, .7, .2, 1) 250ms, opacity 700ms ease 250ms; }
/* A row swiped sideways goes past the edge, not into a sideways scroll. */
.sheet { overflow-x: clip; }

.section-title:where([data-skin="house"]) {
  margin: calc(30 * var(--sp-out)) 0 calc(4 * var(--sp-in));
  font-style: italic;
  font-weight: 400;
  font-size: calc(19 * var(--fs));
  color: var(--ink-soft);
}
.section-title:first-child { margin-top: 0; }
/* No line left holding one word: headings balance, reading text wraps well. */
.section-title, .proposal-title { text-wrap: balance; }
.item-title, .item-note, .note-body, .quiet { text-wrap: pretty; }

.list { list-style: none; margin: 0; padding: 0; }

/* One stop in the day, in four columns that are the same in every list, so
   names line up whether a row has a mark to tap or not (Conner,
   2026-09-24): when, the mark that says what kind of thing it is, the
   lines about it, and Drive, on the title's line, always in the same
   place, so the eye (and thumb) finds it without looking. */
/* The time column is as wide as its widest label ("Yesterday", 58px) and
   sits 4.4px from the circle, 60% closer than the 11px between the other
   columns (Conner, 2026-09-24): its track is 6.6px narrower, and a label
   that long runs into the first of the gap. */
/* The kit's row contract (data-k="row": lead, mark, lines, trail). In the
   house skin its wrappers step out of the way, so the four columns are the
   row's own. */
:where(.item[data-skin="house"]) :is(.k-mark, .k-lines, .k-trail) { display: contents; }
.item:where([data-skin="house"]) {
  display: grid;
  grid-template-columns: 51.4px 15px 1fr auto;
  column-gap: calc(11 * var(--sp-in));
  align-items: baseline;
  padding: calc(13 * var(--sp-in)) 0;
}
:where(.item[data-skin="house"]) .item-time {
  grid-column: 1;
  grid-row: 1;
  font-family: var(--sans);
  font-weight: 500;
  font-size: calc(15 * var(--fs));
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--ink-soft);
  white-space: nowrap;
}
/* What kind of thing it is, in the margin under its time: a note in a
   planner's margin. The column spans the item's lines, so the word never
   pushes the place away from the name. */
:where(.item[data-skin="house"]) .item-time.has-kind { grid-row: 1 / span 3; }
.kind-word:where([data-skin="house"]) {
  display: block;
  margin-top: calc(3 * var(--sp-in));
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: calc(14 * var(--fs));
  line-height: 1.2;
  color: var(--ink-soft);
}
:where(.item[data-skin="house"]) .item-title { grid-column: 3; grid-row: 1; font-weight: 500; font-size: calc(19 * var(--fs)); line-height: 1.28; }
/* Each property in its own voice, not its own box (Conner, 2026-09-24: "the
   lines aren't clearly differentiated"): where, with the place's name ahead
   of its address; whose, in that person's colour; then the notes, hung off
   a rule like something written in the margin. */
:where(.item[data-skin="house"]) .item-place { grid-column: 3; margin-top: calc(4 * var(--sp-in)); font-family: var(--sans); font-size: calc(15 * var(--fs)); line-height: 1.35; color: var(--ink-soft); }
.place-part { display: inline-block; }
.place-name { color: var(--ink); font-weight: 500; }
/* Whose it is, on its own line under where (and, for something to do,
   when it's due): a dot and the name in their colour. */
:where(.item[data-skin="house"]) .item-who { grid-column: 3; margin-top: calc(5 * var(--sp-in)); font-family: var(--sans); font-size: calc(14 * var(--fs)); line-height: 1.35; color: var(--ink-soft); }
.item-who[data-p="conner"] { --who: var(--conner); }
.item-who[data-p="chloe"] { --who: var(--chloe); }
.item-who[data-p]::before {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  margin: 0 calc(7 * var(--sp-in)) calc(1 * var(--sp-in)) calc(1 * var(--sp-in));
  border-radius: 50%;
  background: var(--who);
  vertical-align: middle;
}
.item-who[data-p] .who-name { color: var(--who); font-weight: 500; }
/* A note from when it was added, in the hand it was said in. Two lines at
   most: it's a reminder, not a document. */
:where(.item[data-skin="house"]) .item-note {
  grid-column: 3;
  margin-top: calc(10 * var(--sp-in));
  padding: 1px 0 1px 11px;
  border-left: 2px solid var(--rule);
  font-style: italic;
  font-size: calc(16 * var(--fs));
  line-height: 1.35;
  color: var(--ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Beside the name, spanning the lines under it, so its tap target never
   pushes the place further from the name on one item than on another. */
:where(.item[data-skin="house"]) .item-drive {
  grid-column: 4;
  grid-row: 1 / span 3;
  align-self: start;
  margin-top: calc(-9 * var(--sp-in));
  padding: 10px 0 10px 10px;
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  color: var(--accent);
  text-decoration: none;
}

/* Notes left on a thing since, each with who left it, like a text. A tap
   on the item opens it to take one; open, every note shows in full and can
   be cleared. */
.item.takes-notes .item-title { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.note-by { margin-left: calc(3 * var(--sp-in)); font-family: var(--sans); font-style: normal; font-size: calc(13 * var(--fs)); color: var(--ink-faint); white-space: nowrap; }
.note-acts { display: none; }
:where(.item[data-skin="house"]) .item-note + .item-note { margin-top: calc(4 * var(--sp-in)); }
.item.open .item-note { display: block; -webkit-line-clamp: unset; overflow: visible; }
.item.open .note-acts { display: inline; white-space: nowrap; }
.note-acts button {
  margin-left: calc(12 * var(--sp-in));
  padding: 4px 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-style: normal;
  font-size: calc(13 * var(--fs));
  color: var(--accent);
  cursor: pointer;
}
.note-editing { margin-top: calc(6 * var(--sp-in)); }
.note-add { grid-column: 3 / -1; display: flex; flex-wrap: wrap; gap: calc(8 * var(--sp-in)); align-items: center; margin-top: calc(10 * var(--sp-in)); }
.note-input {
  flex: 1;
  min-width: 0;
  padding: 9px 15px;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 20 / 12);
  background: var(--field);
  color: var(--ink);
  font-family: var(--serif);
  font-size: calc(17 * var(--fs));
}
.note-input::placeholder { color: var(--ink-faint); font-style: italic; }
.note-input:focus { outline: none; border-color: var(--accent); }
.note-save {
  height: 38px;
  padding: 0 15px;
  border: none;
  border-radius: calc(var(--radius) * 19 / 12);
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(14 * var(--fs));
  cursor: pointer;
}
.note-save[hidden] { display: none; }
.note-who { margin-right: calc(4 * var(--sp-in)); font-family: var(--sans); font-size: calc(14 * var(--fs)); color: var(--ink-soft); }

/* Done already: in shadow. What's next, or what's been waiting since an
   earlier day: in the light. */
.item.past { opacity: 0.5; }
.item.next .item-time, .item.late .item-time { color: var(--accent); }

/* Room to breathe, said plainly between two things. */
.gap {
  padding: calc(6 * var(--sp-in)) 0 calc(6 * var(--sp-in)) 88.4px;
  font-style: italic;
  font-size: calc(16 * var(--fs));
  color: var(--ink-faint);
}

/* The first heading under the date sits flush only when nothing has a time
   today; under the timeline it keeps its breath. */
#dayList[hidden] + .todo .section-title.lead { margin-top: 0; }

.quiet { margin: calc(6 * var(--sp-in)) 0 0; font-style: italic; font-size: calc(17 * var(--fs)); line-height: 1.45; color: var(--ink-soft); }
/* The next section's title is its section's first child, with no room above
   it, so the empty day's line keeps the room between them. */
#todoQuiet { margin-bottom: calc(30 * var(--sp-out)); }

/* ── The mark column ──
   Centred on the title's first line: an open circle for anything to do,
   filled with a tick when it's done; empty for an event. The tap reaches
   past it for a thumb, into the gaps either side, without growing the
   row. */

.mark, .check { color: var(--ink-soft); }
:where(.item[data-skin="house"]) :is(.mark, .check) { grid-column: 2; grid-row: 1; align-self: start; }
:where(.item[data-skin="house"]) .mark { display: block; margin-top: calc(5 * var(--sp-in)); }
.mark svg, .check svg { display: block; width: 15px; height: 15px; overflow: visible; }
.shape { fill: none; stroke: currentColor; stroke-width: 1.3; transition: fill 160ms ease, stroke 160ms ease; }
.tick { fill: none; stroke: var(--on-accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 9.5; stroke-dashoffset: 9.5; }
.shape { transition-duration: 110ms; }
.check {
  position: relative;
  z-index: 1;
  width: 44px;
  height: 44px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
:where(.item[data-skin="house"]) .check {
  margin: calc(-9.5 * var(--sp-in)) calc(-17 * var(--sp-out)) calc(-14.5 * var(--sp-in)) calc(-12 * var(--sp-in));
  padding: 0 17px 0 0;
  justify-content: flex-end;
}
.item.checking .shape, .item.done .shape { fill: var(--accent); stroke: var(--accent); }
.item.done .tick { stroke-dashoffset: 0; }
/* Checked: the circle fills, gives a small pop, and the tick draws itself. */
.item.checking .tick { stroke-dashoffset: 0; transition: stroke-dashoffset 150ms cubic-bezier(.3, .7, .3, 1) 30ms; }
.item.checking .check svg { animation: pop 240ms cubic-bezier(.3, 1.5, .5, 1); }
@keyframes pop { 40% { transform: scale(1.35); } }

/* The genie: the row, lifted off the page as a slip of the lighter linen,
   pouring down into Done today (checkOff and genie in home.js). */
.genie { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
.genie-band { position: absolute; overflow: hidden; background-color: transparent; transition: background-color 90ms ease; will-change: transform; }
.genie.lifted .genie-band { background-color: var(--card); }
/* Lifted off the page, the slip casts a shadow away from the room's light. */
.genie.lifted { filter: drop-shadow(calc(var(--cast-x) * 8) calc(var(--cast-y) * 8) 8px rgba(12, 7, 3, 0.2)); }
.item.done { opacity: 0.55; }
.item.done:where([data-skin="house"]) { padding: calc(8 * var(--sp-in)) 0; }
:where(.item[data-skin="house"]).done .check { margin-top: calc(-11 * var(--sp-in)); }
:where(.item[data-skin="house"]).done .item-title { font-size: calc(17 * var(--fs)); }
.item.leaving { opacity: 0.35; transition: opacity 300ms ease; }

/* ── Filters: what the linen shows (Conner, 2026-09-24) ──
   Three menus in one capsule, Who, What and When, and Done in its own beside
   them, holding what's been checked off (a check-off pours into it). A menu
   opens a panel of its options over the day, grown out of its button. Rows
   of pills broke as more was added; this stays one row.
   Liquid Glass made of fabric (he chose pills, "but I want to leverage the
   Liquid Glass style but make it fabric inspired"): each capsule is sheer
   linen laid on the page. The cloth under it softens through it, its own
   weave shows, the room's one light catches the rim that faces it (--lx,
   --ly, set by home.js), and its shadow falls away from that light. Picked,
   an option is dyed: the person's colour, ink for the rest, the accent for
   Done. Everything is at least 44px to tap, the dye's radius is the
   capsule's less its 3px inset, and a press gives to 0.98. */

.filters:where([data-skin="house"]) {
  --sheer: color-mix(in srgb, var(--surface) 46%, transparent);
  --sheer-panel: color-mix(in srgb, var(--surface) 86%, transparent);
  --sheer-light: rgba(255, 255, 255, 0.7);
  --sheer-rim: rgba(255, 255, 255, 0.34);
  --sheer-lift: color-mix(in srgb, var(--ink) 16%, transparent);
  --weave-blend: multiply;
  --weave: 0.2;
  max-width: 460px;
  margin: calc(-2 * var(--sp-in)) 0 calc(24 * var(--sp-out));
}
:root[data-light="night"] .filters:where([data-skin="house"]) {
  --sheer: color-mix(in srgb, color-mix(in srgb, var(--surface) 75%, var(--ink)) 34%, transparent);
  --sheer-panel: color-mix(in srgb, color-mix(in srgb, var(--surface) 90%, var(--ink)) 88%, transparent);
  --sheer-light: rgba(255, 236, 210, 0.2);
  --sheer-rim: rgba(255, 236, 210, 0.12);
  --sheer-lift: rgba(0, 0, 0, 0.4);
  --weave-blend: soft-light;
  --weave: 0.45;
}
.filters:where([data-skin="house"]):empty { display: none; }
/* The kit's filters contract (data-k="filters": groups, each a menu button
   and its options; Done beside them), laid out as the house skin: one grid,
   the three menus on the first row inside one glass capsule (.k-deco), Done
   in its own capsule at the end, and the open menu's panel on the row
   under them, across the whole width. */
.filters:where([data-skin="house"]) { display: grid; grid-template-columns: auto auto auto max-content; align-items: center; }
:where(.filters[data-skin="house"]) :is(.k-groups, .k-group) { display: contents; }
:where(.filters[data-skin="house"]) :is(.k-filters-open, .k-lead, .k-filters-done, .k-chev) { display: none; }
:where(.filters[data-skin="house"]) .k-deco { grid-area: 1 / 1 / 2 / 4; align-self: stretch; }
:where(.filters[data-skin="house"]) .k-group:nth-of-type(1) > .filter-open { grid-area: 1 / 1; }
:where(.filters[data-skin="house"]) .k-group:nth-of-type(2) > .filter-open { grid-area: 1 / 2; }
:where(.filters[data-skin="house"]) .k-group:nth-of-type(3) > .filter-open { grid-area: 1 / 3; }
:where(.filters[data-skin="house"]) .filter-done-set { grid-area: 1 / 4; margin-left: calc(10 * var(--sp-in)); }
:where(.filters[data-skin="house"]) .filter-panel { grid-row: 2; grid-column: 1 / -1; contain: inline-size; }
/* In another skin the capsule is the kit's to draw. */
.filters:not([data-skin="house"]) .k-deco { display: none; }
:where(.filters[data-skin="house"]) .filter-set { display: flex; flex: 1; min-width: 0; }
:where(.filters[data-skin="house"]) .filter-set.solo { flex: none; }

:where(.filters[data-skin="house"]) .glass {
  position: relative;
  isolation: isolate;
  border-radius: 999px;
  background: var(--sheer);
  -webkit-backdrop-filter: blur(6px) saturate(1.15);
  backdrop-filter: blur(6px) saturate(1.15);
  box-shadow:
    inset calc(var(--lx) * -1.4px) calc(var(--ly) * -1.4px) 0 var(--sheer-light),
    inset 0 0 0 1px var(--sheer-rim),
    calc(var(--cast-x) * 1) calc(var(--cast-y) * 1 + 1px) 2px var(--sheer-lift),
    calc(var(--cast-x) * 5) calc(var(--cast-y) * 5 + 2px) 16px -8px var(--sheer-lift);
}
/* Its weave: the same linen, finer, as if a sheer layer of it. */
:where(.filters[data-skin="house"]) .glass::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: url('/img/home/cloth.jpg') 0 0 / 250px 250px;
  mix-blend-mode: var(--weave-blend);
  /* The studio quiets it by itself while the glass has a photo. */
  opacity: var(--weave);
  pointer-events: none;
}
/* Where the light falls on it: the side facing the light, fading away. */
:where(.filters[data-skin="house"]) .glass::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(var(--light-deg), var(--sheer-light), rgba(255, 255, 255, 0) 58%);
  opacity: 0.55;
  pointer-events: none;
}

/* A menu's button and an option are the same shape: the whole 44px is the
   target, and the dye sits 3px in from the capsule's edge. */
:where(.filters[data-skin="house"]) .filter, :where(.filters[data-skin="house"]) .filter-open {
  position: relative;
  isolation: isolate;
  flex: 1;
  min-width: 0;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(6 * var(--sp-in));
  padding: 0 8px;
  border: none;
  border-radius: 999px;
  background: none;
  font-family: var(--sans);
  font-weight: 500;
  font-size: calc(15 * var(--fs));
  color: var(--ink-soft);
  white-space: nowrap;
  word-spacing: 0.06em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 180ms ease, transform 100ms ease-out;
}
:where(.filters[data-skin="house"]) .filter:active, :where(.filters[data-skin="house"]) .filter-open:active { transform: scale(0.98); }
/* The dye: it soaks in from the middle when picked, and drains out. */
:where(.filters[data-skin="house"]) .filter::before, :where(.filters[data-skin="house"]) .filter-open::before {
  content: '';
  position: absolute;
  inset: 3px;
  z-index: -1;
  border-radius: inherit;
  background: var(--tint, var(--ink));
  opacity: 0;
  transform: scale(0.7);
  transition: opacity 180ms ease, transform 240ms cubic-bezier(.2, .8, .2, 1);
}
:where(.filters[data-skin="house"]) .filter[aria-pressed="true"], :where(.filters[data-skin="house"]) .filter-open.set { color: var(--sheet-solid); }
:where(.filters[data-skin="house"]) .filter[aria-pressed="true"]::before, :where(.filters[data-skin="house"]) .filter-open.set::before { opacity: 1; transform: none; }
:where(.filters[data-skin="house"]) .filter[data-f="conner"], :where(.filters[data-skin="house"]) .filter-open[data-p="conner"] { --tint: var(--conner); }
:where(.filters[data-skin="house"]) .filter[data-f="chloe"], :where(.filters[data-skin="house"]) .filter-open[data-p="chloe"] { --tint: var(--chloe); }
:where(.filters[data-skin="house"]) .filter[data-f="conner"][aria-pressed="true"],
:where(.filters[data-skin="house"]) .filter[data-f="chloe"][aria-pressed="true"],
:where(.filters[data-skin="house"]) .filter-open.set[data-p] { color: var(--surface); }
:where(.filters[data-skin="house"]) .filter-done { --tint: var(--accent); padding: 0 14px; }
:where(.filters[data-skin="house"]) .filter-done[aria-pressed="true"] { color: var(--on-accent); }

/* The menus share the capsule by what they say, so "Errands +1" gets the
   room it needs from a menu that only says "When". */
:where(.filters[data-skin="house"]) .filter-open { flex: 1 1 auto; gap: calc(5 * var(--sp-in)); padding: 0 9px; }
:where(.filters[data-skin="house"]) .filter-open .menu-label { overflow: hidden; text-overflow: ellipsis; }
:where(.filters[data-skin="house"]) .menu-count { font-size: calc(14 * var(--fs)); font-variant-numeric: lining-nums tabular-nums; opacity: 0.8; }
:where(.filters[data-skin="house"]) .menu-count:empty { display: none; }
/* Open, the button is lit rather than dyed, and its chevron turns over. */
:where(.filters[data-skin="house"]) .filter-open[aria-expanded="true"] { color: var(--ink); }
:where(.filters[data-skin="house"]) .filter-open[aria-expanded="true"]::before { background: var(--sheer-light); opacity: 1; transform: none; }
:where(.filters[data-skin="house"]) .filter-open.set[aria-expanded="true"] { color: var(--ink); }
:where(.filters[data-skin="house"]) .chev {
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: calc(-3 * var(--sp-in));
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  opacity: 0.7;
  transform: rotate(45deg);
  transition: transform 220ms cubic-bezier(.2, .8, .2, 1), margin 220ms ease;
}
:where(.filters[data-skin="house"]) .filter-open[aria-expanded="true"] .chev { margin-top: calc(3 * var(--sp-in)); transform: rotate(-135deg); }

/* The options: a panel under the bar. The day glides down to make room
   (settle in home.js) rather than being covered. */
:where(.filters[data-skin="house"]) .filter-panel {
  margin-top: calc(8 * var(--sp-in));
  background: var(--sheer-panel);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
  backdrop-filter: blur(20px) saturate(1.15);
}
:where(.filters[data-skin="house"]) .filter-panel[hidden] { display: none; }

:where(.filters[data-skin="house"]) .filter-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--who); }
:where(.filters[data-skin="house"]) .filter-dot[data-p="conner"] { --who: var(--conner); }
:where(.filters[data-skin="house"]) .filter-dot[data-p="chloe"] { --who: var(--chloe); }
/* Together: half of each of them. */
:where(.filters[data-skin="house"]) .filter-dot[data-p="shared"] { background: linear-gradient(90deg, var(--chloe) 50%, var(--conner) 50%); }
:where(.filters[data-skin="house"]) .filter[aria-pressed="true"] .filter-dot { background: currentColor; }
:where(.filters[data-skin="house"]) .filter-count { font-size: calc(14 * var(--fs)); font-variant-numeric: lining-nums tabular-nums; color: var(--accent); }
:where(.filters[data-skin="house"]) .filter-done[aria-pressed="true"] .filter-count { color: inherit; }
:where(.filters[data-skin="house"]) .filter-count:empty { display: none; }

/* Done: what's been checked off this last week, instead of the day. */
.done-section { display: none; }
.sheet.done-view .done-section { display: block; }
.sheet.done-view > :not(.filters):not(.done-section):not(.stale) { display: none; }
.done-section .section-title.lead { margin-top: 0; }
.done-view .item.done { opacity: 1; }
.done-view .item.done .item-title { color: var(--ink-soft); }

/* ── Notes: what one of them told the other ── */

.notes .note {
  position: relative;
  padding: 12px 104px 12px 0;
}
.note-body { margin: 0; font-size: calc(18 * var(--fs)); line-height: 1.4; }
.note-meta { margin-top: calc(3 * var(--sp-in)); font-family: var(--sans); font-size: calc(14 * var(--fs)); color: var(--ink-soft); word-spacing: 0.06em; }
.note-side { position: absolute; top: 2px; right: 0; display: flex; gap: calc(16 * var(--sp-out)); }
.note-change, .note-clear {
  padding: 10px 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-size: calc(15 * var(--fs));
  color: var(--ink-soft);
  cursor: pointer;
}
.note.leaving { opacity: 0.35; transition: opacity 300ms ease; }

/* ── This week: a line a day, opening to the day ── */

.week { list-style: none; margin: 0; padding: 0; }
.day-row {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: calc(12 * var(--sp-in));
  align-items: baseline;
  padding: calc(11 * var(--sp-in)) 0;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
}
.day-row:disabled { cursor: default; }
.day-name { font-weight: 500; font-size: calc(18 * var(--fs)); }
.day-wx { font-family: var(--sans); font-size: calc(15 * var(--fs)); color: var(--ink-soft); font-variant-numeric: lining-nums tabular-nums; }
.day-sum {
  grid-column: 1 / -1;
  margin-top: calc(2 * var(--sp-in));
  font-family: var(--sans);
  font-size: calc(15 * var(--fs));
  line-height: 1.35;
  color: var(--ink-soft);
  word-spacing: 0.06em;
}
.day-sum.empty { font-family: var(--serif); font-style: italic; font-size: calc(16 * var(--fs)); color: var(--ink-faint); }
.day-items { padding: 0 0 calc(8 * var(--sp-in)); }
.day.open .day-name { color: var(--accent); }

.stale { margin: 0 0 calc(18 * var(--sp-out)); font-family: var(--sans); font-size: calc(14 * var(--fs)); color: var(--accent); }

/* Just arrived from the add field: lit for a moment. */
.item.arrived { animation: arrived 2200ms ease-out; }
@keyframes arrived {
  from { background: color-mix(in srgb, var(--accent) 28%, transparent); }
  to { background: transparent; }
}

/* ── Swiping: right to edit, left to delete (home.js) ─────────────────── */
/* The row follows the thumb. What letting go will do shows in the space it
   uncovers, pale until the row is far enough to do it, then full: the
   same accent as Save for Edit, the leather's red side for Delete. */

@property --dx { syntax: '<length>'; inherits: true; initial-value: 0px; }
.item.swipes {
  position: relative;
  touch-action: pan-y;
  transform: translateX(var(--dx));
  transition: --dx 240ms cubic-bezier(.2, .7, .2, 1);
}
.item.swipes.swiping { transition: none; -webkit-user-select: none; user-select: none; }
.item.swipes::before, .item.swipes::after {
  position: absolute;
  top: 3px;
  bottom: 3px;
  display: flex;
  align-items: center;
  overflow: hidden;
  white-space: nowrap;
  text-indent: 18px;
  border-radius: calc(var(--radius) * 12 / 12);
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 160ms ease;
}
.item.swipes::before { content: 'Edit'; right: 100%; width: max(0px, var(--dx)); background: var(--accent); color: var(--on-accent); }
/* Right to left, so the word sits at the edge it came from. */
.item.swipes::after { content: 'Delete'; left: 100%; width: max(0px, calc(0px - var(--dx))); direction: rtl; background: var(--brick); color: var(--on-brick); }
.item.arm-edit::before, .item.arm-delete::after, .item.gone::after { opacity: 1; }

/* Opened, the same two, in words. */
.item-more { grid-column: 3 / -1; display: flex; gap: calc(24 * var(--sp-out)); margin-top: calc(10 * var(--sp-in)); }
.item-more button {
  padding: 6px 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(14 * var(--fs));
  color: var(--accent);
  cursor: pointer;
}
.item-more .item-delete { color: var(--brick); }

/* ── The details, to edit ──────────────────────────────────────────────── */
/* A sheet of the same linen, over the day: the name as its heading, then
   when, where and whose. */

/* The kit's sheet contract; its house skin is drawn by the page, not the
   browser: no dialog chrome, its own shade, the sheet rising from the bottom. */
dialog.editor:where([data-skin="house"]) { position: fixed; inset: 0; z-index: 6; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: none; overflow: visible; color: inherit; }
dialog.editor:where([data-skin="house"])::backdrop { background: transparent; }
dialog.editor:where([data-skin="house"]) :is(.editor-head, .editor-body) { display: contents; }
dialog.editor:where([data-skin="house"]) .k-close { display: none; }
dialog.editor:not([data-skin="house"]) .editor-shade { display: none; }
.editor-shade { position: absolute; inset: 0; background: rgba(12, 7, 3, 0.38); opacity: 0; transition: opacity 240ms ease; }
.editor.open .editor-shade { opacity: 1; }
:where([data-skin="house"]) > .editor-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: calc(100% - 48px);
  overflow-y: auto;
  overscroll-behavior: contain;
  box-sizing: border-box;
  padding: 22px 22px calc(env(safe-area-inset-bottom) + 16px);
  border-radius: calc(var(--radius) * 22 / 12) calc(var(--radius) * 22 / 12) 0 0;
  background-color: var(--sheet-solid);
  background-image: linear-gradient(var(--linen-veil), var(--linen-veil)), url('/img/home/cloth.jpg');
  background-size: auto, 500px 500px;
  box-shadow: calc(var(--cast-x) * 14) calc(var(--cast-y) * 4 - 10px) 40px rgba(12, 7, 3, 0.30);
  color: var(--ink);
  transform: translateY(100%);
  transition: transform 260ms cubic-bezier(.2, .7, .2, 1);
  outline: none;
}
.editor.open:where([data-skin="house"]) > .editor-sheet { transform: none; }
.editor-title {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 2px 0 10px;
  border: none;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  background: none;
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 500;
  font-size: calc(24 * var(--fs));
}
.editor-title:focus { outline: none; border-bottom-color: var(--accent); }
.editor-sheet > .editor-seg { margin-top: calc(16 * var(--sp-out)); }
.editor-when { display: grid; grid-template-columns: 1.15fr 1fr 1fr; gap: calc(8 * var(--sp-in)); margin-top: calc(16 * var(--sp-out)); }
.editor-field { display: block; margin-top: calc(16 * var(--sp-out)); }
.editor-when .editor-field { margin-top: 0; min-width: 0; }
.editor-field > span { display: block; margin-bottom: calc(6 * var(--sp-in)); font-family: var(--sans); font-size: calc(14 * var(--fs)); color: var(--ink-soft); }
.editor-field input {
  display: block;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 12 / 12);
  background: var(--field);
  color: var(--ink);
  font-family: var(--sans);
  font-size: calc(16 * var(--fs));
  -webkit-appearance: none;
  appearance: none;
}
.editor-field input:focus { outline: none; border-color: var(--accent); }
.editor-field input:disabled { opacity: 0.5; }
.editor-field input::placeholder { color: var(--ink-faint); font-style: italic; }
.editor-hint { margin: calc(8 * var(--sp-in)) 0 0; font-family: var(--sans); font-size: calc(14 * var(--fs)); line-height: 1.4; color: var(--ink-soft); }
.editor-hint[hidden] { display: none; }
.editor-seg { display: flex; flex-wrap: wrap; gap: calc(6 * var(--sp-in)); }
.editor-seg button {
  height: 40px;
  padding: 0 15px;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 20 / 12);
  background: var(--field);
  color: var(--ink);
  font-family: var(--sans);
  font-size: calc(15 * var(--fs));
  cursor: pointer;
}
.editor-seg button[aria-checked="true"] { border-color: var(--accent); background: var(--accent); color: var(--on-accent); font-weight: 700; }
.editor-actions { display: flex; align-items: center; gap: calc(20 * var(--sp-out)); margin-top: calc(24 * var(--sp-out)); }
.editor-delete {
  margin-left: auto;
  padding: 11px 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  color: var(--brick);
  cursor: pointer;
}
html.editing, html.editing body { overflow: hidden; }

/* ── Add something ─────────────────────────────────────────────────────── */

.add {
  position: fixed;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: 0;
  /* --ios-gap (home.js) is that stranded strip, which already clears the
     home indicator, so the field doesn't float a strip-height above it. */
  padding: 18px 14px max(10px, calc(env(safe-area-inset-bottom) + 10px - var(--ios-gap, 0px)));
}
/* The list slides under the field and is gone, not ghosted through it. The
   field rests on the same linen as the list, so the weave doesn't stop. */
.add::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--sheet-solid);
  background-image: linear-gradient(var(--linen-veil), var(--linen-veil)), url('/img/home/cloth.jpg');
  background-size: auto, 500px 500px;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 18px);
  mask-image: linear-gradient(180deg, transparent 0, #000 18px);
}
/* The kit's field contract (data-k="field"); this is its house skin. */
.add-row:where([data-skin="house"]) { display: flex; gap: calc(8 * var(--sp-in)); align-items: center; }
:where([data-skin="house"]) > .add-input {
  flex: 1;
  min-width: 0;
  padding: 12px 18px;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 24 / 12);
  background: var(--field);
  color: var(--ink);
  font-family: var(--serif);
  font-size: calc(18 * var(--fs));
  box-shadow: calc(var(--cast-x) * 3) calc(var(--cast-y) * 3) 14px rgba(12, 7, 3, 0.10);
}
:where([data-skin="house"]) > .add-input::placeholder { color: var(--ink-faint); font-style: italic; }
:where([data-skin="house"]) > .add-input:focus { outline: none; border-color: var(--accent); }
.add-send {
  flex-shrink: 0;
  height: 44px;
  padding: 0 16px;
  border: none;
  border-radius: calc(var(--radius) * 22 / 12);
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  cursor: pointer;
}
.add-send[hidden] { display: none; }

/* The proposal: exactly what would be added, and one tap to add it. */
.proposal {
  margin: 0 0 calc(10 * var(--sp-in));
  padding: 16px 18px;
  border-radius: calc(var(--radius) * 18 / 12);
  background: var(--card);
  border: 1px solid var(--rule);
  box-shadow: calc(var(--cast-x) * 10) calc(var(--cast-y) * 10) 30px rgba(12, 7, 3, 0.18);
}
.proposal[hidden] { display: none; }
.proposal-title { font-weight: 500; font-size: calc(20 * var(--fs)); line-height: 1.25; }
.proposal-meta { margin-top: calc(4 * var(--sp-in)); font-family: var(--sans); font-size: calc(15 * var(--fs)); line-height: 1.4; color: var(--ink-soft); }
.proposal-note { font-style: italic; font-size: calc(17 * var(--fs)); line-height: 1.4; color: var(--ink-soft); }
.proposal-actions { display: flex; gap: calc(20 * var(--sp-out)); align-items: center; margin-top: calc(12 * var(--sp-in)); }
.proposal-yes {
  padding: 11px 18px;
  border: none;
  border-radius: calc(var(--radius) * 22 / 12);
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  cursor: pointer;
}
.proposal-no {
  padding: 11px 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-size: calc(15 * var(--fs));
  color: var(--ink-soft);
  cursor: pointer;
}
.proposal { transition: transform 260ms ease, opacity 260ms ease; }
.proposal.entering { transform: translateY(10px); opacity: 0; }

/* The kit's toast contract (data-k="toast"); this is its house skin. */
.toast:where([data-skin="house"]) {
  position: fixed;
  z-index: 7;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom) + 84px);
  transform: translate(-50%, 8px);
  max-width: calc(100% - 48px);
  padding: 10px 16px;
  border-radius: calc(var(--radius) * 14 / 12);
  background: color-mix(in srgb, color-mix(in srgb, var(--dark-surface) 55%, #000) 92%, transparent);
  color: var(--dark-ink);
  font-family: var(--sans);
  font-size: calc(15 * var(--fs));
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
}
.toast:where([data-skin="house"]).show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast:where([data-skin="house"]).with-act { display: flex; align-items: center; gap: calc(14 * var(--sp-in)); }
:where([data-skin="house"]) > .toast-act {
  padding: 4px 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  color: var(--dark-accent);
  cursor: pointer;
}

/* ── The Assistant's answers ──────────────────────────────────────────── */
/* On the Assistant page, and above the add field when what was typed is a
   question or a change. The question, then its answer set as a sentence. */

.talk { list-style: none; margin: 0; padding: 0; }
.turn + .turn { margin-top: calc(34 * var(--sp-out)); }
.turn-q {
  margin: 0;
  font-family: var(--sans);
  font-weight: 500;
  font-size: calc(15 * var(--fs));
  line-height: 1.4;
  color: var(--ink-soft);
  word-spacing: 0.06em;
}
.turn-a {
  margin: calc(8 * var(--sp-in)) 0 0;
  font-size: calc(21 * var(--fs));
  line-height: 1.4;
  color: var(--ink);
}
.turn-a.working { font-style: italic; color: var(--ink-soft); font-size: calc(19 * var(--fs)); }
.turn-a.failed { font-style: italic; color: var(--ink-soft); font-size: calc(19 * var(--fs)); }
@media (prefers-reduced-motion: no-preference) {
  .turn-a.working { animation: breathe 1.8s ease-in-out infinite; }
}
@keyframes breathe { 50% { opacity: 0.55; } }

.turn-link {
  display: inline-block;
  margin-top: calc(10 * var(--sp-in));
  padding: 6px 0;
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  color: var(--accent);
  text-decoration: none;
}

/* A change, laid out as it will be made. */
.proposal.change { margin: calc(16 * var(--sp-out)) 0 0; box-shadow: none; }
.proposal-lines { margin: 0; padding: 0; list-style: none; }
.proposal-lines li { font-size: calc(18 * var(--fs)); line-height: 1.4; }
.proposal-lines li + li { margin-top: calc(6 * var(--sp-in)); }
.proposal-done { margin: calc(10 * var(--sp-in)) 0 0; font-family: var(--sans); font-size: calc(15 * var(--fs)); color: var(--ink-soft); }
.proposal-done a { color: var(--accent); font-weight: 700; text-decoration: none; }

.proposal-undo {
  padding: 0;
  border: none;
  background: none;
  font-family: var(--sans);
  font-weight: 700;
  font-size: calc(15 * var(--fs));
  color: var(--accent);
  cursor: pointer;
}

/* Above the add field an answer can run long: it scrolls, and the day stays
   in view above it. */
.proposal.talking { max-height: min(58vh, 540px); overflow-y: auto; overscroll-behavior: contain; }
.here-talk .turn + .turn { margin-top: calc(22 * var(--sp-out)); }
.here-talk .turn-a { font-size: calc(19 * var(--fs)); }
.here-talk .proposal.change { margin-top: calc(12 * var(--sp-in)); padding: 12px 14px; border-radius: calc(var(--radius) * 14 / 12); }
.here-talk .proposal-lines li { font-size: calc(17 * var(--fs)); }
.talk-end { justify-content: flex-end; margin-top: calc(8 * var(--sp-in)); }

/* ── Wide screens (secondary: the phone is the audience) ───────────────── */

@media (min-width: 760px) {
  #app { max-width: 480px; margin: 0 auto; }
  /* Wider light across a wider room. The blinds' ends stay off the right
     edge (they'd read as a picture of blinds), and 950px is the most the
     light map covers at 2x without being enlarged. */
  .world-sun { width: 950px; height: 780px; right: -250px; top: -110px; }
  .add { left: 50%; right: auto; width: 480px; transform: translateX(-50%); }
  :where([data-skin="house"]) > .editor-sheet { left: 50%; right: auto; width: 480px; transform: translate(-50%, 100%); }
  .editor.open:where([data-skin="house"]) > .editor-sheet { transform: translate(-50%, 0); }
  #lock { align-items: center; justify-content: center; }
  .lock-name { text-align: center; }
}

/* ── Stillness, for those who ask for it ───────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
