/*
 * dokocal — one stylesheet for all three screens.
 *
 * Palette 02 "Navy", locked by Ariel. The two ramps below are lifted verbatim
 * from the palette artifact: --l-* is the light ramp and --d-* is the dark one,
 * and they are two independent sets of literal colours. Neither is derived from
 * the other by a filter or a hue rotation, because a dark mode built that way
 * turns the alert colour into something that no longer reads as alarm.
 *
 * The mapping below runs one direction only. The ramps never read from the
 * mapped names, so there is no cycle to trip over.
 *
 *   html[data-app="light|dark"]   the phone and admin screens
 *   html[data-wall="light|dark"]  the wall, whose mode is an admin setting
 *
 * Two colour rules that carry meaning and are not decoration:
 *
 *   Alert (red/orange) means NOBODY IS COVERING THIS. It is used for a day with
 *   no one on it and for a staffed day with nobody opening. Nothing else.
 *
 *   Absent is grey and struck through. If absences were also red the wall would
 *   have two kinds of red on it and would stop meaning anything.
 *
 * No inline styles anywhere. The Content-Security-Policy the worker sends has
 * no 'unsafe-inline', so a style attribute would simply not apply.
 */

/* ---------------------------------------------------------------------------
 * Heebo, self-hosted.
 *
 * Heebo is the Hebrew extension of Roboto and ships Roboto as its Latin, so one
 * family covers both languages without the halves disagreeing. Both files are
 * the variable font, weight 300 to 800, taken from Google Fonts (SIL Open Font
 * License; the licence sits next to them in public/fonts/OFL.txt).
 *
 * Self-hosted rather than linked, so the CSP needs no third-party origin at all:
 * style-src 'self' and font-src 'self' are enough, and the wall keeps its type
 * when Google Fonts is unreachable.
 * ------------------------------------------------------------------------- */
@font-face {
  font-family: 'Heebo';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/fonts/heebo-hebrew.woff2') format('woff2');
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
@font-face {
  font-family: 'Heebo';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/fonts/heebo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

/* ---------------------------------------------------------------------------
 * Palette 02 Navy — the two literal ramps
 * ------------------------------------------------------------------------- */
:root {
  --l-bg:#eff3f7;--l-surface:#fff;--l-surface2:#dfeaf4;--l-rule:#d0dce7;
  --l-ink:#0e2136;--l-muted:#5d7085;--l-chipink:#1a4c78;--l-chiprule:#bfd4e6;
  --l-alert:#b3382c;--l-hol:#1a4c78;--l-open:#0b5567;--l-openbg:#d6edf2;
  --l-openborder:#a8d5df;--l-openink:#08404f;--l-opentext:#fff;--l-absent:#7d8d9c;
  --d-bg:#0c1b2b;--d-surface:#14293d;--d-surface2:#1e3a54;--d-rule:#1e3346;
  --d-ink:#e9f1f8;--d-muted:#6b8299;--d-chipink:#e9f1f8;--d-chiprule:#2a4560;
  --d-alert:#f0663f;--d-hol:#e4b048;--d-open:#6fd4e2;--d-openbg:#0f3e4a;
  --d-openborder:#2b6d7a;--d-openink:#d9f4f8;--d-opentext:#06222b;--d-absent:#708aa1;

  --sans: 'Heebo', 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* ---- mode mapping: one direction only, no cycles ---- */
html[data-app='light'] {
  --appbg:var(--l-bg);--appcard:var(--l-surface);--apprule:var(--l-rule);
  --appink:var(--l-ink);--appmuted:var(--l-muted);
  --slipbg:var(--l-surface2);--sliptext:var(--l-chipink);--slipborder:var(--l-chiprule);
  --appalert:var(--l-alert);--apphol:var(--l-hol);--appopen:var(--l-open);
  --openbg:var(--l-openbg);--openborder:var(--l-openborder);--opentext:var(--l-opentext);
  --appabsent:var(--l-absent);--appshadow:0 1px 2px rgba(0,0,0,.06);
  color-scheme: light;
}
html[data-app='dark'] {
  --appbg:var(--d-bg);--appcard:var(--d-surface);--apprule:var(--d-rule);
  --appink:var(--d-ink);--appmuted:var(--d-muted);
  --slipbg:var(--d-surface2);--sliptext:var(--d-chipink);--slipborder:var(--d-chiprule);
  --appalert:var(--d-alert);--apphol:var(--d-hol);--appopen:var(--d-open);
  --openbg:var(--d-openbg);--openborder:var(--d-openborder);--opentext:var(--d-opentext);
  --appabsent:var(--d-absent);--appshadow:none;
  color-scheme: dark;
}
html[data-wall='light'] {
  --wbg:var(--l-bg);--wcell:var(--l-surface);--wtoday:var(--l-surface2);--wrule:var(--l-rule);
  --wtext:var(--l-ink);--wdim:var(--l-muted);--whol:var(--l-hol);--walert:var(--l-alert);
  --wopen:var(--l-open);--wopenbg:var(--l-openbg);--wopenborder:var(--l-openborder);
  --wopenink:var(--l-openink);--wabsent:var(--l-absent);
  color-scheme: light;
}
html[data-wall='dark'] {
  --wbg:var(--d-bg);--wcell:var(--d-surface);--wtoday:var(--d-surface2);--wrule:var(--d-rule);
  --wtext:var(--d-ink);--wdim:var(--d-muted);--whol:var(--d-hol);--walert:var(--d-alert);
  --wopen:var(--d-open);--wopenbg:var(--d-openbg);--wopenborder:var(--d-openborder);
  --wopenink:var(--d-openink);--wabsent:var(--d-absent);
  color-scheme: dark;
}

/* ---------------------------------------------------------------------------
 * Base
 * ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  font-family: var(--sans);
  font-weight: 400;
  letter-spacing: .01em;
  -webkit-text-size-adjust: 100%;
}
html[data-app] body { background: var(--appbg); color: var(--appink); }
html[data-wall] body { background: var(--wbg); color: var(--wtext); }

:focus-visible { outline: 2px solid var(--appopen, var(--wopen)); outline-offset: 2px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---------------------------------------------------------------------------
 * The phone screen: shell
 * ------------------------------------------------------------------------- */
.shell { max-width: 560px; margin: 0 auto; padding: 0 0 40px; }

.topbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 12px 14px 10px;
}
.topbar .brand { font-weight: 500; font-size: 18px; color: var(--appink); }
.topbar .who { font-size: 12px; color: var(--appmuted); margin-inline-start: auto; }

/*
 * The mark, inline in the document rather than an <img>. app.js builds it; see
 * mark() there for why it cannot be an image.
 *
 * Two fills. The block is currentColor, so it takes the ink of whatever it sits
 * beside and needs no per-mode rule. The cells are holes rather than white
 * shapes, so they carry the page behind them — which is why the same fallback
 * chain :focus-visible uses appears here: the phone and admin screens define
 * --appbg, the wall defines --wbg, and neither defines the other.
 */
.mark { flex: none; width: 20px; height: 20px; }
.mark .mk-b { fill: currentColor; }
.mark .mk-c { fill: var(--appbg, var(--wbg)); }
.topbar .mark { color: var(--appink); }

.pill {
  appearance: none; font-family: var(--sans); font-size: 12px; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase; line-height: 1.5;
  border: 1px solid var(--apprule); border-radius: 20px; background: none;
  color: var(--appmuted); padding: 7px 13px; cursor: pointer;
}
.pill:hover { color: var(--appink); border-color: var(--appmuted); }
.pill[aria-pressed='true'] {
  background: var(--appopen); border-color: var(--appopen); color: var(--opentext);
}
.pill.quiet { border-color: transparent; }
a.pill { text-decoration: none; display: inline-block; }
.pill:disabled { opacity: .5; cursor: default; }

.toolbar { display: flex; gap: 6px; flex-wrap: wrap; padding: 0 14px 12px; }

/* ---------------------------------------------------------------------------
 * Sign in / sign up
 * ------------------------------------------------------------------------- */
.auth { padding: 48px 22px 40px; max-width: 420px; margin: 0 auto; }
.auth h1 { font-weight: 700; font-size: 30px; margin: 0 0 4px; color: var(--appink); }
.auth .tagline {
  font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--appopen); margin: 0 0 34px;
}
.auth h2 { font-weight: 500; font-size: 17px; margin: 0 0 16px; color: var(--appink); }

.field { margin: 0 0 14px; }
.field label { display: block; font-size: 12px; color: var(--appmuted); margin: 0 0 5px; }
.field input, .field select {
  width: 100%; font-family: var(--sans); font-size: 16px; font-weight: 400;
  color: var(--appink); background: var(--appcard);
  border: 1px solid var(--apprule); border-radius: 8px; padding: 11px 12px;
}
.hint { display: block; font-size: 11.5px; color: var(--appmuted); margin: 5px 0 0; line-height: 1.5; }

.btn {
  width: 100%; appearance: none; border: 0; border-radius: 8px; cursor: pointer;
  background: var(--appopen); color: var(--opentext);
  font-family: var(--sans); font-size: 15px; font-weight: 500;
  padding: 13px; margin-top: 8px;
}
.btn:disabled { opacity: .55; cursor: default; }
.linkbtn {
  appearance: none; border: 0; background: none; cursor: pointer; padding: 12px 0 0;
  font-family: var(--sans); font-size: 13px; color: var(--appopen); text-decoration: underline;
}
.auth .foot { font-size: 12px; color: var(--appmuted); line-height: 1.6; margin: 26px 0 0; }

.notice {
  border-radius: 8px; padding: 10px 12px; margin: 0 0 14px;
  font-size: 13px; line-height: 1.5;
  border: 1px solid var(--openborder); background: var(--openbg); color: var(--appink);
}
.notice.bad { border-color: var(--appalert); background: transparent; color: var(--appalert); }

/* ---------------------------------------------------------------------------
 * The week
 * ------------------------------------------------------------------------- */
.weekhead { display: flex; align-items: baseline; gap: 8px; padding: 6px 14px 8px; }
.weekhead h2 { font-weight: 500; font-size: 14px; color: var(--appink); margin: 0; }
.weekhead .range { font-size: 11.5px; color: var(--appmuted); }
.weekhead .rule { flex: 1; height: 1px; background: var(--apprule); }

.day {
  background: var(--appcard); border: 1px solid var(--apprule); border-radius: 12px;
  overflow: hidden; margin: 0 12px 8px; padding: 10px 12px;
  border-inline-start: 4px solid transparent; box-shadow: var(--appshadow, none);
}
.day.today { border-inline-start-color: var(--appalert); }
.day.hollow {
  border-color: color-mix(in srgb, var(--appalert) 35%, var(--apprule));
  background:
    repeating-linear-gradient(135deg, transparent 0 7px,
      color-mix(in srgb, var(--appalert) 7%, transparent) 7px 14px),
    var(--appcard);
}
.drow { display: flex; align-items: baseline; gap: 7px; margin: 0 0 8px; }
.dname { font-weight: 500; font-size: 16px; color: var(--appink); }
.day.rest .dname { color: var(--apphol); }
.dnum { font-size: 11px; color: var(--appmuted); }
.dchag {
  font-size: 12px; color: var(--apphol); margin-inline-start: auto;
  text-align: end; line-height: 1.25; max-width: 56%;
}

/* פתיחה — a filled band that bleeds to both edges of the card, so the openers
   sit in a zone rather than at an indent. */
.opener {
  background: var(--openbg); margin: 0 -12px 9px; padding: 6px 12px 8px;
  border-top: 1px solid var(--openborder); border-bottom: 1px solid var(--openborder);
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center;
}
.opener.gap {
  background: color-mix(in srgb, var(--appalert) 10%, transparent);
  border-color: color-mix(in srgb, var(--appalert) 32%, transparent);
}
.openlab {
  font-size: 10px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--appopen); width: 100%; line-height: 1.7;
}
.opener.gap .openlab { color: var(--appalert); }
.noopen { font-size: 12.5px; color: var(--appalert); font-weight: 500; }

.slips { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.slip {
  font-size: 13px; font-weight: 400; color: var(--sliptext);
  background: var(--slipbg); border: 1px solid var(--slipborder);
  border-radius: 8px; padding: 3px 10px; line-height: 1.5;
  max-width: 100%; overflow-wrap: anywhere;
}
.slip.open {
  color: var(--opentext); background: var(--appopen);
  border-color: var(--appopen); font-weight: 500;
}
/* Absent is grey and struck through, never the alert colour. */
.slip.off {
  color: var(--appabsent); background: transparent; border-color: var(--appabsent);
  font-weight: 300; text-decoration: line-through;
  text-decoration-color: var(--appabsent);
}
.slip.me { box-shadow: inset 0 0 0 1px var(--appopen); }
.nobody { font-size: 12.5px; color: var(--appalert); font-weight: 500; }

.actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.actions .pill { padding: 7px 12px; }

/* ---------------------------------------------------------------------------
 * Admin
 * ------------------------------------------------------------------------- */
.admin { max-width: 720px; margin: 0 auto; padding: 0 14px 48px; }
.card {
  background: var(--appcard); border: 1px solid var(--apprule); border-radius: 12px;
  padding: 14px; margin: 0 0 14px; box-shadow: var(--appshadow, none);
}
.card h2 { font-weight: 500; font-size: 16px; margin: 0 0 10px; color: var(--appink); }
.card .btn { width: auto; padding: 10px 18px; }

.people { list-style: none; margin: 0; padding: 0; }
.person {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 0; border-bottom: 1px solid var(--apprule);
}
.person:last-child { border-bottom: 0; }
.person .pname { font-size: 14px; color: var(--appink); }
.person .puser { font-size: 11.5px; color: var(--appmuted); }
.person .ptag {
  font-size: 10px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--appopen);
}
.person.off .pname { color: var(--appabsent); text-decoration: line-through; }
.person .grow { margin-inline-start: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.resetform { flex-basis: 100%; margin: 8px 0 2px; }

.wallpath {
  display: block; width: 100%; font-family: var(--sans); font-size: 13px;
  color: var(--appink); background: var(--slipbg); border: 1px solid var(--slipborder);
  border-radius: 8px; padding: 10px 12px; overflow-wrap: anywhere;
}
.rowbtns { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.warn { font-size: 12px; color: var(--appmuted); margin: 8px 0 0; line-height: 1.5; }

/* ---------------------------------------------------------------------------
 * The wall
 *
 * Every length on this screen is a multiple of one unit, --u, so the whole
 * board scales from a single declaration. The unit is a share of the screen
 * rather than a pixel count, which is what lets one stylesheet read at 1080p on
 * a monitor and at 4K on a bigger one with no breakpoint per screen.
 *
 * `min()` of the two axes, because four weeks of cells is a height problem as
 * much as a width one. On a 16:9 screen the two terms are equal and --u is the
 * width share it has always been; on anything shorter the height term wins and
 * the board shrinks rather than running off the bottom.
 *
 * The .fit-N classes are a density ladder, 3% apart, and app.js binary-searches
 * it for the largest rung the screen still holds. A quiet week is printed large
 * and a week with everybody on it is printed small. A fixed size cannot do
 * that: it is either too big for the busiest week of the year or too small for
 * all the others. The rungs are close together because a coarse ladder
 * undershoots, leaving the board small with dead space under it. Nothing here
 * clips. Past the last rung the page scrolls, which is at least visible, rather
 * than swallowing a name inside a cell, which is not.
 * ------------------------------------------------------------------------- */
.wall {
  --u: min(1cqi, 1.7778dvh);
  container-type: inline-size;
  min-height: 100dvh; background: var(--wbg); color: var(--wtext);
  padding: calc(2.2 * var(--u)) calc(2.4 * var(--u)); display: flex; flex-direction: column;
}
.wall.fit-1 { --u: min(0.9700cqi, 1.7245dvh); }
.wall.fit-2 { --u: min(0.9409cqi, 1.6727dvh); }
.wall.fit-3 { --u: min(0.9127cqi, 1.6226dvh); }
.wall.fit-4 { --u: min(0.8853cqi, 1.5739dvh); }
.wall.fit-5 { --u: min(0.8587cqi, 1.5267dvh); }
.wall.fit-6 { --u: min(0.8330cqi, 1.4809dvh); }
.wall.fit-7 { --u: min(0.8080cqi, 1.4364dvh); }
.wall.fit-8 { --u: min(0.7837cqi, 1.3933dvh); }
.wall.fit-9 { --u: min(0.7602cqi, 1.3515dvh); }
.wall.fit-10 { --u: min(0.7374cqi, 1.3110dvh); }
.wall.fit-11 { --u: min(0.7153cqi, 1.2717dvh); }
.wall.fit-12 { --u: min(0.6938cqi, 1.2335dvh); }
.wall.fit-13 { --u: min(0.6730cqi, 1.1965dvh); }
.wall.fit-14 { --u: min(0.6528cqi, 1.1606dvh); }
.wall.fit-15 { --u: min(0.6333cqi, 1.1258dvh); }
.wall.fit-16 { --u: min(0.6143cqi, 1.0920dvh); }
.wall.fit-17 { --u: min(0.5958cqi, 1.0593dvh); }
.wall.fit-18 { --u: min(0.5780cqi, 1.0275dvh); }
.wall.fit-19 { --u: min(0.5606cqi, 0.9967dvh); }
.wall.fit-20 { --u: min(0.5438cqi, 0.9668dvh); }
.wall.fit-21 { --u: min(0.5275cqi, 0.9378dvh); }
.wall.fit-22 { --u: min(0.5117cqi, 0.9096dvh); }
.wall.fit-23 { --u: min(0.4963cqi, 0.8823dvh); }
.wall.fit-24 { --u: min(0.4814cqi, 0.8559dvh); }
.wall.fit-25 { --u: min(0.4670cqi, 0.8302dvh); }
.wall.fit-26 { --u: min(0.4530cqi, 0.8053dvh); }
.wall.fit-27 { --u: min(0.4394cqi, 0.7811dvh); }
.wall.fit-28 { --u: min(0.4262cqi, 0.7577dvh); }
.wall.fit-29 { --u: min(0.4134cqi, 0.7350dvh); }
.wall.fit-30 { --u: min(0.4010cqi, 0.7129dvh); }
.wall.fit-31 { --u: min(0.3890cqi, 0.6915dvh); }
.wall.fit-32 { --u: min(0.3773cqi, 0.6708dvh); }
.wall.fit-33 { --u: min(0.3660cqi, 0.6507dvh); }
.wall.fit-34 { --u: min(0.3550cqi, 0.6311dvh); }
.wall.fit-35 { --u: min(0.3444cqi, 0.6122dvh); }
.wall.fit-36 { --u: min(0.3340cqi, 0.5938dvh); }
.wall.fit-37 { --u: min(0.3240cqi, 0.5760dvh); }
.wall.fit-38 { --u: min(0.3143cqi, 0.5587dvh); }
.wall.fit-39 { --u: min(0.3049cqi, 0.5420dvh); }
.wall.fit-40 { --u: min(0.2957cqi, 0.5257dvh); }
.wbar {
  display: flex; align-items: baseline; gap: calc(1.8 * var(--u));
  padding-bottom: calc(1.4 * var(--u)); border-bottom: 1px solid var(--wrule); margin-bottom: calc(1.6 * var(--u));
}
/*
 * Sized in --u like everything else on the wall, or the density ladder would
 * shrink the type around a mark that stayed put. align-self because .wbar lays
 * its children out on a baseline and an svg has no useful one.
 */
.wmark { width: calc(3.2 * var(--u)); height: calc(3.2 * var(--u)); align-self: center; color: var(--wtext); }
.wb { font-weight: 500; font-size: calc(2.6 * var(--u)); color: var(--wtext); }
.wd { font-size: calc(1.5 * var(--u)); color: var(--wdim); }
.wclock {
  margin-inline-start: auto; display: flex; align-items: center; gap: calc(1 * var(--u));
  font-size: calc(1.5 * var(--u)); color: var(--wdim);
}
.pulse {
  width: calc(.7 * var(--u)); height: calc(.7 * var(--u)); border-radius: 50%; background: var(--whol);
  animation: beat 3.4s ease-in-out infinite;
}
@keyframes beat { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }

/* The four weeks run one under the other, this week at the top. Ariel's call,
   made after seeing them two across and two down: a week is a row on this wall
   and the eye goes down the weeks, not around them. It costs type size, because
   four rows of cells share the height two used to have. The density ladder
   above is what pays for it. */
.wboard { display: flex; flex-direction: column; }
.wweek { margin-bottom: calc(1.2 * var(--u)); }
.wlabel {
  font-size: calc(1.2 * var(--u)); letter-spacing: .16em; text-transform: uppercase;
  color: var(--wdim); margin-bottom: calc(.5 * var(--u));
}
/* Four rows shared by all seven cells: the day, the holiday line, the opening
   band, and the names. The cells are subgrids of those rows, so each part
   starts at the same height right across the week no matter how long one day's
   holiday name is or how many lines "nobody is opening" takes to say. That is
   what the register is: a reader's eye finds the openers on one line across the
   whole wall. A row nobody uses — a week with no holiday in it — costs nothing,
   because an empty row is zero pixels tall. */
.wgrid {
  display: grid; grid-template-columns: repeat(7, 1fr);
  grid-template-rows: auto auto auto 1fr; gap: calc(1 * var(--u));
}
.wcell {
  display: grid; grid-template-rows: subgrid; grid-row: span 4;
  background: var(--wcell); border-radius: calc(.7 * var(--u)); overflow: hidden;
  padding: calc(1.1 * var(--u)) calc(1.1 * var(--u)) calc(1.4 * var(--u)); min-height: calc(18 * var(--u)); border: 1px solid transparent;
}
.wcell.today { background: var(--wtoday); box-shadow: inset 0 0 0 1px var(--wrule); }
.wcell.hollow {
  border-color: var(--walert);
  background:
    repeating-linear-gradient(135deg, transparent 0 8px,
      color-mix(in srgb, var(--walert) 12%, transparent) 8px 16px),
    var(--wcell);
}
/* Wraps rather than clips: "Wednesday" does not fit beside a date in a column
   this narrow, and a day name cut off mid-word is worse than one on two lines.
   Hebrew never wraps here — ראשון is four letters. */
.wtop {
  display: flex; align-items: baseline; flex-wrap: wrap; column-gap: calc(.45 * var(--u));
  margin-bottom: calc(.6 * var(--u));
}
.wdow { font-weight: 500; font-size: calc(2 * var(--u)); color: var(--wtext); }
/* "Wednesday" is nine letters where ראשון is four, and the column is the same
   width in both languages. Printed at the Hebrew size it runs past the edge of
   the cell and loses its last letter to overflow: hidden, so English gets its
   own size. Nothing else on the wall is set per language. */
html[lang='en'] .wdow { font-size: calc(1.6 * var(--u)); }
.wcell.rest .wdow { color: var(--whol); }
.wnum { font-size: calc(1.15 * var(--u)); color: var(--wdim); }
/* No min-height. The row is as tall as the longest holiday name in the week and
   nothing when there is none, which is what the subgrid above is for. */
.wchag {
  font-weight: 400; font-size: calc(1.5 * var(--u)); color: var(--whol); line-height: 1.25;
  margin-bottom: calc(.8 * var(--u));
}
.wchag:empty { margin-bottom: 0; }

/* The same band as the phone, in the same place in all seven cells, so the
   openers read as one register straight across the wall. */
.wopen {
  background: var(--wopenbg); margin: 0 calc(-1.1 * var(--u)) calc(1 * var(--u)); padding: calc(.7 * var(--u)) calc(1.1 * var(--u)) calc(.9 * var(--u));
  border-top: 1px solid var(--wopenborder); border-bottom: 1px solid var(--wopenborder);
}
.wopen.gap {
  background: color-mix(in srgb, var(--walert) 20%, var(--wcell));
  border-color: color-mix(in srgb, var(--walert) 50%, transparent);
}
.wopenlab {
  font-size: calc(1.2 * var(--u)); font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--wopen); margin-bottom: calc(.3 * var(--u));
}
.wopen.gap .wopenlab { color: var(--walert); }
.wopen .wname { color: var(--wopenink); font-weight: 500; border-bottom: 0; line-height: 1.45; }
.wnoopen { font-size: calc(1.5 * var(--u)); color: var(--walert); font-weight: 500; line-height: 1.45; }

.wname {
  font-size: calc(1.9 * var(--u)); font-weight: 400; color: var(--wtext); line-height: 1.7;
  border-bottom: 1px solid var(--wrule); padding-bottom: calc(.15 * var(--u));
}
.wname:last-child { border-bottom: 0; }
.wname.off {
  color: var(--wabsent); font-weight: 300; text-decoration: line-through;
  text-decoration-color: var(--wabsent); text-decoration-thickness: calc(.12 * var(--u));
}
.wempty { font-size: calc(1.5 * var(--u)); color: var(--walert); font-weight: 500; }
.wfoot {
  display: flex; align-items: center; gap: calc(1.6 * var(--u)); margin-top: auto;
  padding-top: calc(1.4 * var(--u)); border-top: 1px solid var(--wrule);
  font-size: calc(1.3 * var(--u)); color: var(--wdim);
}
.wfail { font-size: calc(1.5 * var(--u)); color: var(--walert); margin-inline-start: auto; }

/* ---------------------------------------------------------------------------
 * Narrow screens. The phone screen is the default; this only trims padding.
 * ------------------------------------------------------------------------- */
@media (max-width: 420px) {
  .auth { padding: 40px 16px 32px; }
  .day { margin: 0 10px 8px; padding: 10px; }
  .opener { margin: 0 -10px 9px; padding: 6px 10px 8px; }
  .topbar, .toolbar { padding-inline: 10px; }
  .weekhead { padding-inline: 10px; }
  .admin { padding-inline: 10px; }
}

/* A wall in portrait, or a phone opening the wall URL: seven columns stop
   working long before the text becomes unreadable, so fall back to two. */
@media (max-width: 700px) {
  .wgrid { grid-template-columns: repeat(2, 1fr); }
  .wall { padding: 14px; }
  .wb { font-size: 20px } .wd, .wclock, .wfoot, .wlabel { font-size: 12px }
  .wdow { font-size: 16px } .wnum, .wopenlab { font-size: 11px }
  .wchag { font-size: 12px; min-height: 0 }
  .wname, .wnoopen, .wempty { font-size: 14px }
  .wcell { min-height: 0; padding: 10px; border-radius: 8px }
  .wopen { margin: 0 -10px 8px; padding: 6px 10px 7px }
  .wgrid { gap: 8px } .wweek { margin-bottom: 10px }
}

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