/* The wall. A fixed stage (1080 x 1920 portrait or 1920 x 1080 landscape, scaled to fit whatever is
   viewing) holding tiles placed on a grid by the household's layout (shared/layout.js). Colours are
   the scheme's custom properties (shared/palettes.js), set by wall.js. Target hardware includes a
   Raspberry Pi 3 and a Chromecast, so motion is limited to the photo crossfade, the tile slide and a
   slow fade when colours change. */
:root {
  --bg: #f7f1e8; --ink: #3a2f26; --mut: #8d8073;
  --t1: #e8d6bf; --t1i: #6b4a1e; --t2: #e6cfc6; --t2i: #6b3a30; --t3: #d9d4c6; --t3i: #3f3d30;
  --today: #3a2f26; --todayi: #fff; --other: #efe8dd; --otheri: #b4a99a; --cell: #fff; --celli: #3a2f26;
  --chip: #e8e8e8; --chip-ink: #3a2f26; --today-chip: #534a42; --today-chip-ink: #fff; --other-chip: #dad3c9; --other-chip-ink: #b4a99a;
  --tile-shadow: 0 2px 4px rgba(45,35,25,.06), 0 16px 36px rgba(45,35,25,.13);
  --cell-shadow: 0 1px 2px rgba(45,35,25,.05), 0 7px 16px rgba(45,35,25,.11);
  --r: 43px;
  --ease: cubic-bezier(.4, 0, .2, 1);
}
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; background: #000; }
html.kiosk, html.kiosk * { cursor: none !important; }
body { overflow: hidden; font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "DejaVu Sans", sans-serif; }
body.editing { background: #15120f; }

/* --shift-x/y is the pixel shift wall.js applies against LCD image retention: the whole stage wanders a screen
   pixel at a time within a few pixels of center, so edges never sit on the same pixels all day. */
#app {
  position: absolute; left: 50%; top: 50%; width: 1080px; height: 1920px; overflow: hidden;
  transform: translate(calc(-50% + var(--shift-x, 0px)), calc(-50% + var(--shift-y, 0px))) scale(var(--scale, 1));
  transform-origin: center;
  background: var(--bg); color: var(--ink);
  transition: background-color 1.2s ease, color 1.2s ease;
}
body.editing #app { left: calc(50% - 170px); }
@media (max-width: 760px) { body.editing #app { left: 50%; top: calc(50% - 150px); } }
#app.no-anim, #app.no-anim * { transition: none !important; }
.corners { position: absolute; inset: 0; border-radius: 67px; box-shadow: 0 0 0 140px #000; pointer-events: none; z-index: 50; }
#app.square-corners .corners { display: none; }

/* ---------- Tiles ---------- */
#tiles { position: absolute; inset: 0; }
.tile {
  position: absolute; border-radius: var(--r); box-shadow: var(--tile-shadow); overflow: hidden;
  --k: 1; padding: calc(26px * var(--k)) calc(30px * var(--k));
  transition: background-color 1.2s ease, color 1.2s ease, box-shadow 1.2s ease, left .6s var(--ease), top .6s var(--ease), width .6s var(--ease), height .6s var(--ease);
}
.tile.c1 { background: var(--t1); color: var(--t1i); }
.tile.c2 { background: var(--t2); color: var(--t2i); }
.tile.c3 { background: var(--t3); color: var(--t3i); }
.tile.plain { background: transparent; box-shadow: none; padding: 0; overflow: visible; }
/* A tile in the owner's own colour (layout editor) for the look on screen, with text that reads on it. */
.tile.own { background: var(--tbg); color: var(--tink); }
.tile.plain.own { box-shadow: var(--tile-shadow); }
.tile.gone { opacity: 0; pointer-events: none; }
.lbl { font-size: calc(18px * var(--k)); letter-spacing: .1em; text-transform: uppercase; opacity: .75; margin-bottom: calc(6px * var(--k)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.none { opacity: .6; }

/* ---------- Photo ---------- */
.t-photo { padding: 0; background: var(--other); }
.photo { position: absolute; left: 0; top: 0; opacity: 0; transition: opacity 1.2s ease; will-change: opacity; }
.photo.show { opacity: 1; }
.photo canvas { display: block; }
.photo-date { position: absolute; right: 22px; bottom: 16px; z-index: 3; font-size: 19px; color: #fff; text-shadow: 0 1px 6px rgba(0,0,0,.7); }
.photo-date:empty { display: none; }
.photo-empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; text-align: center; padding: 40px; font-size: 26px; color: var(--otheri); }
.photo-empty:empty { display: none; }
.photo-ctl { position: absolute; inset: 0; z-index: 5; touch-action: none; cursor: grab; }
.photo-ctl:active { cursor: grabbing; }
#app.readonly .photo-ctl { cursor: default; }
.menu-item { opacity: 0; transition: opacity .25s; pointer-events: none; }
.t-photo:hover .menu-item, .t-photo.menu .menu-item { opacity: 1; }
.t-photo:hover .nav, .t-photo.menu .nav, .t-photo:hover .zoom-meter, .t-photo.menu .zoom-meter, .t-photo:hover .tool, .t-photo.menu .tool { pointer-events: auto; }
#app.readonly .menu-item, #app.no-photos .menu-item { display: none; }
.cross { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }
.cross::before, .cross::after { content: ''; position: absolute; background: rgba(255,255,255,.9); box-shadow: 0 0 3px rgba(0,0,0,.8); }
.cross::before { left: -1px; top: -70px; width: 2px; height: 140px; }
.cross::after { top: -1px; left: -70px; height: 2px; width: 140px; }
.nav {
  position: absolute; top: 50%; width: 76px; height: 76px; margin-top: -38px; border: 0; border-radius: 50%;
  background: rgba(0,0,0,.45); color: #fff; font: 600 44px/76px Inter, system-ui, sans-serif; text-align: center; padding: 0 0 6px;
  box-shadow: 0 2px 10px rgba(0,0,0,.4); cursor: pointer;
}
.nav.prev { left: 22px; }
.nav.next { right: 92px; }
.nav:active { background: rgba(0,0,0,.7); }
.zoom-meter { position: absolute; right: 18px; top: 16%; bottom: 16%; width: 48px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.zoom-meter .track { position: relative; flex: 1; width: 8px; border-radius: 4px; background: rgba(255,255,255,.3); box-shadow: 0 0 0 1px rgba(0,0,0,.25); }
.zoom-meter .fill { position: absolute; left: 0; right: 0; bottom: 0; border-radius: 4px; background: rgba(255,255,255,.85); }
.zoom-meter .thumb { position: absolute; left: 50%; width: 26px; height: 26px; margin: -13px 0 0 -13px; border-radius: 50%; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.5); }
.zoom-meter .label { font-size: 18px; color: #fff; text-shadow: 0 1px 6px rgba(0,0,0,.7); font-variant-numeric: tabular-nums; }
.live-msg {
  position: absolute; left: 50%; top: 24px; transform: translateX(-50%); padding: .4em 1em; border-radius: 999px;
  background: rgba(0,0,0,.55); color: #fff; font-size: 20px; opacity: 0; transition: opacity .25s; pointer-events: none; white-space: nowrap;
}
.live-msg.show { opacity: 1; }

/* ---------- Clock ---------- */
.t-clock .time { font-size: calc(80px * var(--k)); font-weight: 600; line-height: 1; letter-spacing: -.03em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.t-clock .time .ampm { font-size: calc(26px * var(--k)); font-weight: 600; letter-spacing: 0; vertical-align: top; margin-left: 6px; }
.t-clock .weekday { margin-top: calc(10px * var(--k)); font-size: calc(26px * var(--k)); font-weight: 600; }
.t-clock .agenda { list-style: none; margin: calc(10px * var(--k)) 0 0; padding: 0; font-size: calc(20px * var(--k)); line-height: 1.55; }
.t-clock .agenda li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.t-clock .agenda li b { font-weight: 600; margin-right: .35em; font-variant-numeric: tabular-nums; }

/* ---------- Weather now ---------- */
.t-weather { display: flex; flex-direction: column; padding: calc(24px * var(--k)) calc(30px * var(--k)); }
.t-weather .now { display: flex; align-items: flex-start; justify-content: space-between; }
.t-weather .temp { font-size: calc(78px * var(--k)); font-weight: 600; line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.t-weather .temp .unit { font-size: .45em; vertical-align: top; margin-left: 2px; }
.t-weather .cond { display: flex; flex-direction: column; align-items: center; margin: -6px -4px 0 0; }
.t-weather .icon { width: calc(64px * var(--k)); height: calc(64px * var(--k)); opacity: .9; }
.t-weather .icon svg { width: 100%; height: 100%; display: block; }
.t-weather .label { font-size: calc(19px * var(--k)); line-height: 1.2; white-space: nowrap; }
.t-weather .sub { margin-top: calc(8px * var(--k)); font-size: calc(22px * var(--k)); line-height: 1.3; white-space: nowrap; }
.t-weather .stats { margin: auto 0 0; font-size: calc(21px * var(--k)); line-height: 1.57; }
.t-weather .stats div { display: flex; justify-content: space-between; gap: 10px; font-variant-numeric: tabular-nums; }
.t-weather .stats dt { opacity: .75; }
.t-weather .stats dd { margin: 0; font-weight: 600; white-space: nowrap; }
.t-weather .place { font-size: calc(17px * var(--k)); opacity: .7; margin-top: calc(4px * var(--k)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- Weekly forecast ---------- */
.t-forecast ol { list-style: none; margin: 0; padding: 0; }
.t-forecast li { display: grid; grid-template-columns: calc(64px * var(--k)) 1fr auto; align-items: center; font-size: calc(22px * var(--k)); line-height: 1.5; font-variant-numeric: tabular-nums; }
.t-forecast li .d { opacity: .8; }
.t-forecast li svg { width: calc(26px * var(--k)); height: calc(26px * var(--k)); justify-self: center; opacity: .85; }
.t-forecast li b { font-weight: 600; }
.t-forecast li.none { display: block; font-size: calc(20px * var(--k)); }

/* ---------- Month ---------- */
.t-month { display: flex; flex-direction: column; gap: calc(14px * var(--k)); }
.t-month .head { display: flex; align-items: baseline; gap: calc(14px * var(--k)); line-height: 1; }
.t-month .name { font-size: calc(53px * var(--k)); font-weight: 700; letter-spacing: -.01em; }
.t-month .year { font-size: calc(29px * var(--k)); color: var(--mut); }
.t-month .status { margin-left: auto; font-size: calc(19px * var(--k)); color: var(--mut); white-space: nowrap; }
.t-month .status:empty { display: none; }
.t-month .weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 12px; padding: 0 14px; font-size: calc(19px * var(--k)); letter-spacing: .08em; color: var(--mut); text-transform: uppercase; }
/* Refresh: a quiet glyph at the right end of the weekday row, in the room left of SAT's column. The
   glyph stays small; ::before widens the tap area to 44 screen pixels whatever the stage's scale. */
.t-month .weekrow { position: relative; }
.t-month .refresh {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  width: calc(30px * var(--k)); height: calc(30px * var(--k)); padding: 0; border: 0; background: none;
  color: var(--mut); opacity: .55; cursor: pointer; transition: opacity .2s;
}
.t-month .refresh[hidden] { display: none; }
.t-month .refresh::before { content: ''; position: absolute; left: 50%; top: 50%; width: max(100%, calc(44px / var(--scale, 1))); height: max(100%, calc(44px / var(--scale, 1))); transform: translate(-50%, -50%); }
.t-month .refresh:hover, .t-month .refresh:focus-visible { opacity: 1; outline: none; }
.t-month .refresh svg { width: 100%; height: 100%; display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.t-month .refresh.spin svg { animation: wall-spin .8s linear infinite; }
@keyframes wall-spin { to { transform: rotate(360deg); } }
body.editing .t-month .refresh { display: none; }
/* The sync result: a small pill right above the sync icon, over the empty right end of the month's
   heading row, fading in and out. */
.t-month .synced {
  position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 2; pointer-events: none; white-space: nowrap;
  padding: calc(6px * var(--k)) calc(14px * var(--k)); border-radius: 999px; font-size: calc(18px * var(--k)); font-weight: 600;
  background: var(--cell); color: var(--celli); box-shadow: var(--cell-shadow);
  opacity: 0; transform: translateY(4px); transition: opacity .25s, transform .25s;
}
.t-month .synced.show { opacity: 1; transform: none; }
.t-month .grid { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: minmax(0, 1fr); gap: 12px; }
.day {
  --px: calc(12px * var(--k)); --py: calc(7px * var(--k));
  position: relative; min-height: 0; overflow: hidden; padding: var(--py) var(--px) 0; border-radius: 24px; cursor: pointer;
  background: var(--cell); color: var(--celli); box-shadow: var(--cell-shadow); display: flex; flex-direction: column;
  transition: background-color 1.2s ease, color 1.2s ease, box-shadow 1.2s ease;
}
#app.readonly .day { cursor: default; }
.day.other { background: var(--other); color: var(--otheri); box-shadow: none; }
.day.today { background: var(--today); color: var(--todayi); }
.day .num { flex: none; font-size: calc(24px * var(--k)); font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
/* The family wall's month squares: a day with events gets a header band, a shade of its own colour
   (--chip), and its events are written plainly under it, each with a dot in its colour. Today's square
   is the scheme's opposite and keeps one solid colour. */
.day.has-events .num { margin: calc(-1 * var(--py)) calc(-1 * var(--px)) 0; padding: var(--py) var(--px) calc(5px * var(--k)); background: var(--chip); }
.day.other.has-events .num { background: var(--other-chip); }
.day.today.has-events .num { background: var(--today); }
/* Titles wrap, up to four lines; fitEvents() keeps the events that fit whole and adds "+N more". */
.day .events { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; gap: 2px; margin: calc(5px * var(--k)) calc(-1 * var(--px)) 0; }
.ev {
  flex: none; font-size: calc(13px * var(--k)); line-height: 1.2; padding: 1px var(--px) 2px; color: var(--celli);
  white-space: normal; overflow-wrap: break-word; overflow: hidden;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4;
}
.ev .lead { white-space: nowrap; }
.ev .t { font-weight: 600; font-variant-numeric: tabular-nums; }
.ev i, .t-agenda .item i { display: inline-block; width: .6em; height: .6em; border-radius: 50%; margin-right: .35em; vertical-align: .02em; }
.ev.cont { opacity: .8; }
.day.today .ev, .day.today .more { color: var(--todayi); }
.day.other .ev, .day.other .more { color: var(--other-chip-ink); }
.more { flex: none; font-size: calc(13px * var(--k)); line-height: 1.2; padding: 1px var(--px) 2px; color: var(--celli); opacity: .7; }

/* ---------- Coming up (agenda list) ---------- */
.t-agenda ol { list-style: none; margin: 0; padding: 0; font-size: calc(21px * var(--k)); line-height: 1.5; overflow: hidden; }
.t-agenda .dayhead { margin-top: calc(10px * var(--k)); font-weight: 700; opacity: .85; white-space: nowrap; }
.t-agenda .dayhead:first-child { margin-top: 0; }
.t-agenda .item { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.t-agenda .item b { font-weight: 600; margin-right: .35em; font-variant-numeric: tabular-nums; }

/* ---------- To-do, meals, countdown, note, QR ---------- */
.t-todo ul { list-style: none; margin: 0; padding: 0; font-size: calc(22px * var(--k)); line-height: 1.55; }
.t-todo li { display: flex; align-items: baseline; gap: .5em; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app.readonly .t-todo li { cursor: default; }
.t-todo li::before { content: ''; flex: none; width: .75em; height: .75em; border: 2px solid currentColor; border-radius: 6px; opacity: .7; transform: translateY(.05em); }
.t-todo li.done { opacity: .5; text-decoration: line-through; }
.t-todo li.done::before { background: currentColor; }
.t-meals ol { list-style: none; margin: 0; padding: 0; font-size: calc(21px * var(--k)); line-height: 1.6; }
.t-meals li { display: grid; grid-template-columns: calc(58px * var(--k)) 1fr; gap: .5em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.t-meals li .d { opacity: .7; font-weight: 600; }
.t-meals li.today { font-weight: 700; }
.t-meals li.today .d { opacity: 1; }
.t-countdown { display: flex; flex-direction: column; justify-content: center; }
.t-countdown .big { font-size: calc(84px * var(--k)); font-weight: 700; line-height: 1; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.t-countdown .big small { font-size: .32em; font-weight: 600; letter-spacing: 0; margin-left: .25em; }
.t-countdown .title { font-size: calc(24px * var(--k)); font-weight: 600; margin-top: calc(10px * var(--k)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.t-countdown .when { font-size: calc(18px * var(--k)); opacity: .7; margin-top: 4px; }
.t-note { display: flex; align-items: center; }
.t-note .text { font-size: calc(30px * var(--k)); font-weight: 600; line-height: 1.3; white-space: pre-wrap; overflow: hidden; }
.t-note .text.long { font-size: calc(22px * var(--k)); font-weight: 500; }
.t-qr { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(8px * var(--k)); padding: calc(18px * var(--k)); }
.t-qr img { width: 100%; height: auto; max-height: 78%; object-fit: contain; }
.t-qr .label { font-size: calc(16px * var(--k)); text-align: center; opacity: .8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.t-spacer { background: transparent !important; box-shadow: none !important; }
body.editing .t-spacer { outline: 2px dashed rgba(255,255,255,.35); outline-offset: -2px; }

/* ---------- Every size a tile may take (layout.js) ----------
   wall.js tags each tile with its size: .row is one cell tall (102px), .short two (216px), .narrow
   two cells wide or less, .roomy five or more, .wide at least twice as wide as tall. One-row tiles are
   always 102px tall, so their type is set in pixels; taller ones scale with --k. Small text never
   drops below a size readable across a room. */
.lbl { font-size: max(15px, calc(18px * var(--k))); }
.tile.row { display: flex; align-items: center; gap: 18px; padding: 0 28px; white-space: nowrap; }
.tile.row .lbl { margin: 0; flex: none; font-size: 17px; }
.tile.row ol, .tile.row ul { margin: 0; min-width: 0; }
.tile.row.narrow { padding: 0 20px; gap: 12px; }

/* Clock: one row is the time and the weekday (and the next event when roomy); two rows wide put
   today's events beside the time. */
.t-clock.row .time { font-size: 52px; }
.t-clock.row .time .ampm { font-size: 18px; }
.t-clock.row .weekday { margin: 0; font-size: 24px; opacity: .8; }
.t-clock.row.narrow .weekday { display: none; }
.t-clock.row .agenda { display: none; }
.t-clock.row.roomy .agenda { display: block; margin: 0 0 0 auto; min-width: 0; font-size: 22px; line-height: 1.3; text-align: right; }
.t-clock.row.roomy .agenda li:not(:first-child) { display: none; }
.t-clock.short.wide:not(.narrow) { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto 1fr; column-gap: calc(34px * var(--k)); align-content: start; }
.t-clock.short.wide:not(.narrow) .time { grid-column: 1; grid-row: 1; }
.t-clock.short.wide:not(.narrow) .weekday { grid-column: 1; grid-row: 2; }
.t-clock.short.wide:not(.narrow) .agenda { grid-column: 2; grid-row: 1 / span 2; margin: 0; align-self: center; font-size: 20px; line-height: 1.5; }
.t-clock.short.roomy .agenda { font-size: 23px; }
.t-clock.short.wide:not(.narrow) { align-content: center; }
.t-clock .agenda li.more { opacity: .6; }
.t-clock.narrow .weekday { font-size: max(17px, calc(26px * var(--k))); }
.t-clock .agenda { font-size: max(16px, calc(20px * var(--k))); }
/* Taller than wide: the time and today's plans sit in the middle rather than at the top. */
.t-clock.tall { display: flex; flex-direction: column; justify-content: center; }
.t-clock.short:not(.wide) { display: flex; flex-direction: column; justify-content: center; }

/* Weather: one row is the icon, temperature and conditions (and high/low when there is room); two
   rows drop the details, unless roomy, which puts them beside. */
.t-weather.row { flex-direction: row; }
.t-weather.row .now { display: contents; }
.t-weather.row .temp { order: 2; font-size: 52px; }
.t-weather.row .cond { display: contents; }
.t-weather.row .icon { order: 1; width: 50px; height: 50px; }
.t-weather.row .label { order: 3; font-size: 22px; }
.t-weather.row .sub { order: 4; margin: 0; font-size: 22px; opacity: .8; }
.t-weather.row .stats, .t-weather.row .place { display: none; }
.t-weather.row.narrow .sub, .t-weather.row.narrow .label { display: none; }
.t-weather.row:not(.roomy) .sub { display: none; }
.t-weather.short .stats, .t-weather.short .place { display: none; }
.t-weather.short { justify-content: center; }
.t-weather.short.roomy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); grid-template-rows: auto 1fr; column-gap: calc(40px * var(--k)); }
.t-weather.short.roomy .now { grid-column: 1; }
.t-weather.short.roomy .sub { grid-column: 1; }
.t-weather.short.roomy .stats { display: block; grid-column: 2; grid-row: 1 / span 2; margin: 0; align-self: center; font-size: 20px; line-height: 1.45; }
.t-weather.short.roomy { align-content: center; }
.t-weather.narrow:not(.row) .stats { font-size: 17px; }
.t-weather.narrow .stats div:nth-child(2), .t-weather.narrow .stats div:nth-child(4) { display: none; }
/* Taller than wide: everything gathers in the middle instead of leaving a gap above the details. */
.t-weather.tall { justify-content: center; }
.t-weather.tall .stats { margin-top: calc(22px * var(--k)); }

/* Forecast: one row lays the seven days out in a line; two rows give each day a column. */
.t-forecast.row .lbl, .t-forecast.short .lbl { display: none; }
.t-forecast.row ol { flex: 1; display: flex; justify-content: space-between; gap: 8px; }
.t-forecast.row li { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 16px; line-height: 1; }
.t-forecast.row li svg { width: 26px; height: 26px; }
.t-forecast.row li b { font-size: 21px; }
.t-forecast.short { display: flex; align-items: center; }
.t-forecast.short ol { flex: 1; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.t-forecast.short li { display: flex; flex-direction: column; align-items: center; gap: 10px; font-size: 21px; line-height: 1; }
.t-forecast.short li svg { width: 36px; height: 36px; }
.t-forecast.short li b { font-size: 24px; }
.t-forecast.narrow:not(.short):not(.row) li { grid-template-columns: 2.6em 1fr auto; font-size: 19px; }
.t-forecast.narrow:not(.short):not(.row) li svg { width: 22px; height: 22px; }
/* Clearly wider than tall: each day gets a column, like the two-row version but larger. */
.t-forecast.broad:not(.row):not(.short) { display: flex; flex-direction: column; container-type: inline-size; }
.t-forecast.broad:not(.row):not(.short) ol { flex: 1; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); align-content: center; gap: 8px; }
/* Seven columns share the width, so type is sized by the tile's width (cqw) as well as its scale. */
.t-forecast.broad:not(.row):not(.short) li { display: flex; flex-direction: column; align-items: center; gap: min(calc(14px * var(--k)), 2.6cqw); font-size: min(calc(24px * var(--k)), 4.3cqw); line-height: 1; }
.t-forecast.broad:not(.row):not(.short) li svg { width: min(calc(48px * var(--k)), 7.5cqw); height: min(calc(48px * var(--k)), 7.5cqw); }
.t-forecast.broad:not(.row):not(.short) li b { font-size: min(calc(30px * var(--k)), 5.4cqw); }
/* Taller than wide: the seven days spread down the tile. */
.t-forecast.tall { display: flex; flex-direction: column; }
.t-forecast.tall ol { flex: 1; display: flex; flex-direction: column; justify-content: space-evenly; }

/* Coming up: one row shows only what is next. */
.t-agenda.row .lbl { display: none; }
.t-agenda.row ol { flex: 1; font-size: 26px; line-height: 1.2; }
.t-agenda.row .item { display: flex; align-items: center; gap: 10px; }
.t-agenda.row .item .when { flex: none; font-weight: 700; opacity: .75; margin-right: 6px; }
.t-agenda .item i { flex: none; }
.t-agenda ol { font-size: max(15px, calc(21px * var(--k))); }

/* To-do: smaller tiles keep the list readable and let "+N more" say the rest. */
.t-todo ul { font-size: max(15px, calc(22px * var(--k))); }
.t-todo.narrow ul { font-size: 18px; }

/* Meals: one row is tonight's dinner; two rows are tonight and tomorrow. */
.t-meals ol { font-size: max(15px, calc(21px * var(--k))); }
.t-meals.row .lbl { display: none; }
.t-meals.row ol { flex: 1; font-size: 28px; line-height: 1.2; }
.t-meals.row li { display: flex; align-items: baseline; gap: 14px; }
.t-meals.row li .d { font-size: 20px; text-transform: uppercase; letter-spacing: .08em; opacity: .7; }
.t-meals.row li .m { overflow: hidden; text-overflow: ellipsis; }
.t-meals.short li, .t-meals.row li { grid-template-columns: auto 1fr; font-weight: 400; }
.t-meals.short { display: flex; flex-direction: column; }
.t-meals.short ol { flex: 1; display: flex; flex-direction: column; justify-content: center; font-size: 28px; line-height: 1.45; }
.t-meals.narrow:not(.short):not(.row) ol { font-size: 18px; }
/* Taller than wide: the week spreads down the tile. Clearly wider than tall: two columns. */
.t-meals.tall { display: flex; flex-direction: column; }
.t-meals.tall ol { flex: 1; display: flex; flex-direction: column; justify-content: space-evenly; }
.t-meals.broad:not(.short):not(.row) { display: flex; flex-direction: column; }
.t-meals.broad:not(.short):not(.row) ol { margin: auto 0; column-count: 2; column-gap: calc(40px * var(--k)); }
.t-meals.broad:not(.short):not(.row) li { break-inside: avoid; }
.t-meals.short li { gap: .7em; }
.t-meals.short li .d { min-width: 4.6em; }
.t-meals.short li.today .m { font-weight: 700; }

/* Countdown: one row puts it all on a line, the number first; two rows wide put the words beside it. */
.t-countdown.row { flex-direction: row; justify-content: flex-start; }
.t-countdown.row .big { font-size: 54px; flex: none; }
.t-countdown.row .big small { font-size: 20px; }
.t-countdown.row .title { margin: 0; font-size: 26px; min-width: 0; flex: 0 1 auto; }
.t-countdown.row .when { margin: 0 0 0 auto; font-size: 20px; flex: none; }
.t-countdown.row:not(.roomy) .when { display: none; }
.t-countdown.short.wide:not(.narrow) { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto; column-gap: calc(30px * var(--k)); align-content: center; }
.t-countdown.short.wide:not(.narrow) .big { grid-row: 1 / span 2; align-self: center; }
.t-countdown.short.wide:not(.narrow) .title { margin: 0; align-self: end; font-size: 26px; }
.t-countdown.short.wide:not(.narrow) .when { font-size: 19px; }
.t-countdown .when { font-size: max(15px, calc(18px * var(--k))); }

/* Note: the text shrinks to fit (wall.js); one row is a single line. */
.t-note .text { max-height: 100%; line-height: 1.2; }
.t-note.row .text { white-space: nowrap; text-overflow: ellipsis; font-size: 30px; line-height: 1.2; }

/* QR: one row puts the label beside the code; a one-cell-wide tile is the code alone. */
.t-qr.row { flex-direction: row; justify-content: flex-start; padding: 10px 24px 10px 12px; }
.t-qr.row img { width: auto; height: 100%; max-height: none; flex: none; }
.t-qr.row .label { font-size: 20px; text-align: left; white-space: normal; line-height: 1.25; }
.t-qr.row.narrow { justify-content: center; padding: 10px; }
.t-qr.row.narrow .label { display: none; }
/* Clearly wider than tall: the label sits beside the code, larger. */
.t-qr.broad:not(.row) { flex-direction: row; justify-content: center; gap: calc(30px * var(--k)); }
.t-qr.broad:not(.row) img { width: auto; height: 100%; max-height: 100%; flex: none; }
.t-qr.broad:not(.row) .label { font-size: max(20px, calc(26px * var(--k))); text-align: left; white-space: normal; max-width: 45%; line-height: 1.25; }
.t-qr[data-w="1"] { padding: 8px; }
.t-qr[data-w="1"] .label { display: none; }
.t-qr[data-w="1"] img { max-height: 100%; }

/* ---------- The tile gallery (/demo?gallery=1): every tile at every size, at half size ---------- */
body.gallery { overflow: auto; background: #1b1714; }
body.gallery #app, body.gallery #demo-banner, body.gallery #demo-rotate { display: none; }
#gallery { padding: 30px; font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; background: var(--bg); }
#gallery > section { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 22px; margin-bottom: 30px; }
#gallery h2 { flex-basis: 100%; margin: 0; color: var(--ink); font-size: 22px; }
#gallery figure { margin: 0; zoom: .5; }
#gallery figure .tile { position: relative; transition: none; }
#gallery figcaption { margin-top: 10px; color: var(--mut); font-size: 30px; }

/* ---------- Adding an event: tap a day ---------- */
#sheet { position: absolute; inset: 0; z-index: 40; background: rgba(0,0,0,.42); display: flex; align-items: flex-end; justify-content: center; padding: 38px; }
#sheet[hidden] { display: none; }
.sheet-card { width: 100%; max-width: 1004px; background: var(--cell); color: var(--celli); border-radius: 36px; padding: 30px 36px 34px; box-shadow: 0 24px 60px rgba(0,0,0,.35); font-size: 26px; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; font-size: 34px; font-weight: 700; margin-bottom: 20px; }
.sheet-head button { font: inherit; font-size: 28px; width: 64px; height: 64px; border: 0; border-radius: 50%; background: var(--other); color: var(--celli); }
#sheet-not-connected { margin: 0; font-size: 26px; line-height: 1.45; color: var(--mut); }
.sheet-input { display: flex; gap: 12px; }
#sheet-title { flex: 1; min-width: 0; font: inherit; font-size: 32px; padding: 16px 22px; border-radius: 18px; border: 2px solid var(--other); background: var(--bg); color: var(--ink); outline: none; }
#sheet-title:focus { border-color: var(--mut); }
.sheet-row { display: flex; align-items: center; gap: 16px; margin-top: 18px; flex-wrap: wrap; }
.sheet-row button { font: inherit; font-size: 24px; padding: 12px 20px; border-radius: 16px; border: 2px solid var(--other); background: var(--bg); color: var(--ink); }
.sheet-row button.on { background: var(--today); color: var(--todayi); border-color: var(--today); }
.timebox, .durbox { display: flex; align-items: center; gap: 10px; }
.timebox span { min-width: 160px; text-align: center; font-weight: 600; font-variant-numeric: tabular-nums; }
.durbox span, .repeatbox span { color: var(--mut); }
.repeatbox { gap: 10px; }
.repeatbox button { font-size: 22px; padding: 10px 16px; }
.timebox.off, .timebox.off ~ .durbox { opacity: .35; pointer-events: none; }
.sheet-actions { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 22px; }
#sheet-msg { font-size: 24px; color: var(--mut); }
.primary { font: inherit; font-size: 26px; font-weight: 600; padding: 16px 28px; border-radius: 18px; border: 0; background: var(--today); color: var(--todayi); }
.primary:disabled { opacity: .45; }

/* A short message over the wall (offline, saved, errors). */
#notice { position: absolute; left: 50%; bottom: 60px; transform: translateX(-50%); z-index: 45; padding: 14px 26px; border-radius: 999px; background: rgba(0,0,0,.6); color: #fff; font-size: 24px; white-space: nowrap; }
#notice[hidden] { display: none; }

/* ---------- Screen chrome: fullscreen, cast, edit, settings (hidden on a display) ---------- */
#chrome { position: fixed; right: 14px; bottom: 14px; z-index: 60; display: flex; gap: 8px; opacity: 0; transition: opacity .3s; }
#chrome[hidden] { display: none; }
#chrome.show { opacity: 1; }
.cbtn { width: 44px; height: 44px; border-radius: 50%; border: 0; background: rgba(0,0,0,.55); color: #fff; font: 20px/44px system-ui, sans-serif; text-align: center; text-decoration: none; cursor: pointer; box-shadow: 0 2px 10px rgba(0,0,0,.4); }
.cbtn:hover { background: rgba(0,0,0,.8); }
.cbtn[hidden] { display: none; }

/* ---------- Editor (owner only; loaded on demand) ---------- */
#editor { position: fixed; top: 0; right: 0; bottom: 0; width: 340px; z-index: 70; overflow: auto; background: #1b1714; color: #f1ebe4; font: 14px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; padding: 14px 16px 30px; box-shadow: -10px 0 40px rgba(0,0,0,.4); }
#editor[hidden] { display: none; }
@media (max-width: 760px) { #editor { top: auto; left: 0; width: auto; height: 300px; box-shadow: 0 -10px 40px rgba(0,0,0,.4); } }
#editor h2 { font-size: 15px; margin: 14px 0 6px; letter-spacing: .04em; text-transform: uppercase; color: #b7ab9f; }
#editor h2:first-child { margin-top: 0; }
#editor .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
#editor button, #editor select, #editor input, #editor textarea { font: inherit; color: inherit; background: #2a241f; border: 1px solid #3f372f; border-radius: 8px; padding: 6px 10px; }
#editor button { cursor: pointer; }
#editor button:hover { background: #352e27; }
#editor button.on { background: #e6cfa6; color: #2a2016; border-color: #e6cfa6; font-weight: 600; }
#editor button.primary { background: #cfae7b; color: #22190f; border-color: #cfae7b; font-weight: 600; }
#editor button.danger { color: #ffb3a7; border-color: #6a3a32; }
#editor input, #editor textarea, #editor select { width: 100%; }
#editor label { display: block; margin: 8px 0 4px; color: #d8cfc4; }
#editor label.keep { display: flex; align-items: center; gap: 8px; margin: 10px 0 0; cursor: pointer; }
#editor label.keep input { width: auto; margin: 0; accent-color: #cfae7b; }
#editor .pal { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
#editor .pal button { display: flex; flex-direction: column; align-items: stretch; gap: 3px; padding: 7px; text-align: left; cursor: grab; }
#editor .pal button:disabled { cursor: not-allowed; opacity: .45; }
#editor .pal button b { font-weight: 600; font-size: 13px; }
#editor .pal button small { display: block; color: #a89c8f; font-weight: 400; font-size: 12px; }
@media (pointer: fine) { #editor .pal button { touch-action: none; } }
/* Each tile type as it looks on the wall, scaled down (editor.js sizes --pw / --ph). */
#editor .pal .slot { display: grid; place-items: center; height: 92px; border-radius: 7px; background: #2a241f; overflow: hidden; }
.pv { position: relative; width: var(--pw); height: var(--ph); pointer-events: none; }
.pv .tile.preview { position: absolute; left: 0; top: 0; transform-origin: 0 0; transition: none; outline: none; cursor: inherit; }
.pv .tile.preview.t-photo { background: #5a4d42 center / cover no-repeat; }
.pv .tile.preview.t-spacer { border: 10px dashed rgba(128,118,108,.6); }
.pv.ghost { position: fixed; z-index: 90; transform: translate(-50%, -50%) scale(1.6); opacity: .92; filter: drop-shadow(0 10px 22px rgba(0,0,0,.5)); }
/* Colours: the look's own swatches, then a board of every hue, then any colour. */
#editor h3 { font-size: 13px; font-weight: 600; margin: 14px 0 6px; color: #d8cfc4; }
#editor .rl { flex: none; width: 84px; color: #b7ab9f; font-size: 13px; }
#editor .seg { display: inline-flex; }
#editor .seg button { border-radius: 0; margin-left: -1px; }
#editor .seg button:first-child { border-radius: 8px 0 0 8px; margin-left: 0; }
#editor .seg button:last-child { border-radius: 0 8px 8px 0; }
#editor .sw-row { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
#editor .sw .none { padding: 3px 9px; font-size: 12px; }
#editor .sw .c { width: 24px; height: 24px; padding: 0; border-radius: 6px; border: 1px solid rgba(255,255,255,.2); }
#editor .sw .c.on { outline: 2px solid #e6cfa6; outline-offset: 2px; }
#editor .board { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 3px; margin-top: 8px; }
#editor .board .c { width: auto; height: auto; aspect-ratio: 1; border-radius: 4px; }
#editor label.any { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; font-size: 13px; color: #b7ab9f; }
#editor label.any input { width: 46px; height: 28px; padding: 1px; cursor: pointer; }
#editor .msg { margin-top: 10px; color: #ffd28f; min-height: 1.4em; }
#editor .items li { display: flex; gap: 6px; margin-bottom: 4px; }
#editor .items { list-style: none; padding: 0; margin: 0; }
#editor .hint { color: #a89c8f; font-size: 13px; }
body.editing .tile { outline: 2px dashed rgba(255,255,255,.45); outline-offset: -2px; cursor: move; transition: none; }
body.editing .tile.sel { outline: 3px solid #e6cfa6; }
body.editing .tile * { pointer-events: none; }
body.editing .grip { position: absolute; right: 0; bottom: 0; width: 56px; height: 56px; cursor: nwse-resize; pointer-events: auto !important; z-index: 9; }
body.editing .grip::after { content: ''; position: absolute; right: 14px; bottom: 14px; width: 22px; height: 22px; border-right: 4px solid rgba(255,255,255,.9); border-bottom: 4px solid rgba(255,255,255,.9); border-radius: 0 0 6px 0; filter: drop-shadow(0 0 2px rgba(0,0,0,.8)); }
body.editing .tile.bad { outline-color: #ff6b6b; }
/* A remove button on every tile; a tile dragged off the wall; where a tile from the palette would land. */
.tile-x { display: none; }
body.editing .tile-x {
  position: absolute; right: 14px; top: 14px; z-index: 10; width: 56px; height: 56px; padding: 0; border: 0; border-radius: 50%;
  display: grid; place-items: center; background: rgba(20,16,12,.75); color: #fff; cursor: pointer; pointer-events: auto !important;
  box-shadow: 0 2px 10px rgba(0,0,0,.45);
}
body.editing .tile-x:hover { background: #b3382c; }
.tile-x svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2.8; stroke-linecap: round; }
body.editing .tile.leaving { opacity: .4; outline: 4px solid #ff6b6b; }
body.editing .tile.leaving::after {
  content: 'Let go to remove'; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 11;
  padding: 12px 22px; border-radius: 999px; background: #b3382c; color: #fff; font: 600 28px system-ui, sans-serif; white-space: nowrap;
}
#drop-target { position: absolute; z-index: 8; border-radius: var(--r); pointer-events: none; border: 5px dashed #e6cfa6; background: rgba(230,207,166,.2); }
#drop-target.bad { border-color: #ff6b6b; background: rgba(255,107,107,.15); }
#drop-target[hidden] { display: none; }
#gridlines { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
#gridlines div { position: absolute; border: 1px dashed rgba(255,255,255,.14); border-radius: 10px; }

/* The demo's invitation: a pill at the bottom of the screen, outside the stage. */
#demo-banner {
  position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 65; max-width: calc(100vw - 120px);
  padding: 9px 16px; border-radius: 999px; background: rgba(255,252,247,.94); color: #3a2f26; text-decoration: none;
  font: 14px/1.35 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; box-shadow: 0 6px 24px rgba(0,0,0,.35);
}
#demo-banner span { color: #8a5a2b; font-weight: 600; white-space: nowrap; }
body.editing #demo-banner { display: none; }

/* ---------- Removing a photo: a trash button in the photo's menu, then a question ---------- */
.tool {
  position: absolute; left: 22px; top: 22px; width: 64px; height: 64px; border: 0; border-radius: 50%; padding: 0;
  background: rgba(0,0,0,.45); color: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.4); cursor: pointer; display: grid; place-items: center;
}
.tool svg { width: 30px; height: 30px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.tool:active { background: rgba(0,0,0,.7); }
.t-photo.confirming .menu-item:not(.tool) { opacity: 0; pointer-events: none; }
.confirm {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 6; width: min(86%, 520px);
  padding: 30px 32px 28px; border-radius: 30px; text-align: center; color: #fff;
  background: rgba(24,19,15,.82); box-shadow: 0 20px 60px rgba(0,0,0,.45); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.confirm[hidden] { display: none; }
.confirm p { margin: 0 0 8px; font-size: 30px; font-weight: 700; line-height: 1.2; }
.confirm small { display: block; font-size: 19px; line-height: 1.4; opacity: .78; }
.confirm-actions { display: flex; justify-content: center; gap: 14px; margin-top: 22px; }
.confirm-actions button { font: 600 23px/1 Inter, system-ui, sans-serif; padding: 16px 28px; border-radius: 999px; cursor: pointer; }
.confirm-actions .no { background: transparent; color: #fff; border: 2px solid rgba(255,255,255,.5); }
.confirm-actions .yes { background: #b4493b; color: #fff; border: 2px solid #b4493b; }
.confirm-actions .yes:disabled { opacity: .6; }

/* Shown over the wall when its subscription has ended (wall.js showPaused). */
#paused { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; background: rgba(20,16,13,.88); color: #f3ede6; font: 18px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; text-align: center; padding: 24px; }
#paused b { display: block; font-size: 28px; margin-bottom: 8px; }
#paused span { display: block; max-width: 28em; opacity: .8; }

/* The demo's rotate button: always in reach at the top right, outside the stage. */
#demo-rotate {
  position: fixed; top: 14px; right: 14px; z-index: 65; display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 15px 9px 12px; border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255,252,247,.94); color: #3a2f26; font: 600 14px/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  box-shadow: 0 6px 24px rgba(0,0,0,.35);
}
#demo-rotate svg { width: 18px; height: 18px; fill: none; stroke: #8a5a2b; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
#demo-rotate:hover { background: #fff; }
body.editing #demo-rotate { display: none; }
