/* ═══════════════════════════════════════════════════════════════════════════
   Hotel Wiederkehr — shell and shared components
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── App shell ──────────────────────────────────────────────────────────────
   A top bar, not a sidebar. A 230px rail costs a whole column of room cards on
   an iPad in portrait, and the board is the app. */

.topbar{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:center; gap:var(--s5);
  height:var(--bar-h); padding:0 var(--s4);
  background:var(--paper); border-bottom:1px solid var(--rule);
}
.topbar__brand{
  font-family:var(--font-display); font-weight:600; font-size:15px;
  letter-spacing:.02em; color:var(--ink); white-space:nowrap;
}
.topbar__brand:hover{ text-decoration:none; }
.topbar__brand small{ display:block; font-family:var(--font-ui); font-size:var(--fs-3xs);
  font-weight:400; color:var(--ink-4); letter-spacing:.08em; text-transform:uppercase; line-height:1; }

.topnav{ display:flex; align-items:center; gap:var(--s1); height:100%; }
.topnav__link{
  display:flex; align-items:center; gap:6px; height:100%; padding:0 var(--s3);
  font-size:var(--fs-sm); font-weight:500; color:var(--ink-2);
  border-bottom:2px solid transparent; margin-bottom:-1px;
}
.topnav__link:hover{ color:var(--ink); text-decoration:none; }
.topnav__link--active{ color:var(--accent); border-bottom-color:var(--accent); }

/* ── Counts on the nav ─────────────────────────────────────────────────────
   A bare number beside a nav label is a riddle: "Board 1" says only that there
   is one of something. So the badge says what it counts, and the word is the
   default rather than the reward for hovering — the whole point of putting a
   count in the chrome is that it can be read without doing anything.

   Below the width where that stops fitting, the word folds away and the
   tooltip and screen-reader text carry it instead. */
.navbadge{
  display:inline-flex; align-items:center; gap:4px;
  height:19px; padding:0 7px; border-radius:var(--r-pill);
  font-size:var(--fs-2xs); font-weight:700; line-height:1;
  white-space:nowrap;
}
.navbadge__word{ font-weight:600; }

.navbadge--accent{ background:var(--accent-wash); color:var(--accent); }
.navbadge--warn  { background:var(--warn-wash);   color:var(--warn-ink); }
.navbadge--danger{ background:var(--danger-wash); color:var(--danger-ink); }

/* The nav has to hold eight items before it holds any words. */
@media (max-width:1220px){
  .navbadge{ gap:0; padding:0 6px; }
  .navbadge__word{ display:none; }
}

.topbar__right{ margin-left:auto; display:flex; align-items:center; gap:var(--s2); }

.menu{ position:relative; }
.menu__panel{
  position:absolute; right:0; top:calc(100% + 6px); min-width:190px; z-index:50;
  background:var(--paper); border:1px solid var(--rule); border-radius:var(--r-ctl);
  box-shadow:var(--shadow-pop); padding:var(--s1);
}
.menu__item{
  display:block; width:100%; padding:9px var(--s3); border-radius:var(--r-cell);
  font-size:var(--fs-sm); color:var(--ink-2);
}
.menu__item:hover{ background:var(--canvas); color:var(--ink); text-decoration:none; }
.menu__item--on{ color:var(--accent); font-weight:600; }
.menu__sep{ height:1px; background:var(--rule); margin:var(--s1) 0; }
.menu__label{ padding:6px var(--s3) 2px; font-size:var(--fs-2xs); color:var(--ink-4); }

.burger{ display:none; width:var(--tap); height:var(--tap); align-items:center; justify-content:center;
  border:1px solid var(--rule); border-radius:var(--r-ctl); }

@media (max-width: 900px){
  .topnav{
    display:none;
    position:fixed; inset:var(--bar-h) 0 auto 0; z-index:39;
    flex-direction:column; align-items:stretch; height:auto; gap:0;
    background:var(--paper); border-bottom:1px solid var(--rule);
    box-shadow:var(--shadow-pop); padding:var(--s2);
  }
  .topnav.is-open{ display:flex; }
  .topnav__link{ height:var(--tap); border-bottom:0; border-radius:var(--r-ctl); padding:0 var(--s3); }
  .topnav__link--active{ background:var(--accent-wash); }
  .burger{ display:flex; }
}

/* ── Page ───────────────────────────────────────────────────────────────── */

.page{ max-width:var(--content-max); margin:0 auto; padding:var(--s5) var(--s4) var(--s12); }
.page--wide{ max-width:none; }
.page__head{ display:flex; align-items:flex-start; gap:var(--s4); margin-bottom:var(--s5); flex-wrap:wrap; }
.page__title{ font-family:var(--font-display); font-size:var(--fs-xl); font-weight:600; }
.page__sub{ color:var(--ink-3); font-size:var(--fs-sm); margin-top:2px; }
.page__actions{ margin-left:auto; display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap; }

.card{ background:var(--paper); border:1px solid var(--rule); border-radius:var(--r-card); }
.card__head{ display:flex; align-items:center; gap:var(--s3); padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--rule); }
.card__title{ font-weight:600; font-size:var(--fs-md); }
.card__body{ padding:var(--s4); }
/* For a block that belongs on a page without competing with it — the rights
   footer on a guest, and anything else that is there to be found, not used. */
.card--quiet{ background:transparent; border-style:dashed; box-shadow:none; }
/* An empty state inside a card already has the card's frame; a second dashed
   box inside the first is a frame around a frame. */
.card > .empty, .card__body > .empty, .deskgroup .empty{
  border:0; border-radius:0; background:transparent; padding:var(--s8) var(--s5);
}

.toolbar{
  display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap;
  padding:var(--s3) var(--s4); background:var(--paper);
  border:1px solid var(--rule); border-radius:var(--r-card); margin-bottom:var(--s4);
  box-shadow:var(--shadow-sm);
}

/* Results being refetched mid-keystroke. Enough to say "working" without the
   flicker of emptying the table between one letter and the next. */
[aria-busy="true"]{ opacity:.55; transition:opacity .12s ease; }
@media (prefers-reduced-motion:reduce){ [aria-busy="true"]{ transition:none; } }

/* ── Buttons ────────────────────────────────────────────────────────────── */

.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  min-height:36px; padding:0 14px;
  border:1px solid var(--rule-strong); border-radius:8px;
  background:var(--paper); color:var(--ink);
  font-size:var(--fs-sm); font-weight:500; white-space:nowrap;
  transition:background var(--t), border-color var(--t);
}
.btn:hover{ background:var(--canvas); text-decoration:none; }
.btn:active{ background:var(--canvas-2); }
.btn[disabled],.btn[aria-disabled="true"]{ opacity:.45; pointer-events:none; }

.btn--primary{ background:var(--accent); border-color:var(--accent); color:var(--on-accent); }
.btn--primary:hover{ background:var(--accent-hi); border-color:var(--accent-hi); }
.btn--primary:active{ background:var(--accent-lo); }
.btn--danger{ background:var(--danger); border-color:var(--danger); color:var(--paper); }
.btn--danger:hover{ background:var(--danger-ink); border-color:var(--danger-ink); }
.btn--quiet{ border-color:transparent; background:transparent; color:var(--ink-2); }
.btn--quiet:hover{ background:var(--canvas-2); }
.btn--sm{ min-height:30px; padding:0 10px; font-size:var(--fs-2xs); }
.btn--lg{ min-height:var(--tap); padding:0 var(--s4); font-size:var(--fs-md); }
.btn--icon{ width:36px; padding:0; }
.btn--block{ width:100%; }

@media (pointer: coarse){
  .btn{ min-height:var(--tap); }
  .btn--sm{ min-height:36px; }
}

/* Segmented control — density, zoom, tabs. A sunken track with the chosen
   option lifted out of it, the same shape as the rooming sheet's switch. */
.seg{ display:inline-flex; flex-wrap:nowrap; gap:2px; padding:3px; border-radius:var(--r-ctl);
  background:var(--canvas-2); }
.seg__item{ display:inline-flex; align-items:center; padding:6px 12px; border-radius:8px;
  font-size:var(--fs-xs); font-weight:600; color:var(--ink-3); background:transparent; white-space:nowrap; }
.seg__item:hover{ color:var(--ink); text-decoration:none; }
.seg__item--on{ background:var(--paper); color:var(--ink); box-shadow:var(--shadow-sm); }

/* ── Forms ──────────────────────────────────────────────────────────────── */

.field{ display:block; margin-bottom:var(--s4); }
.field__label{ display:block; font-size:var(--fs-2xs); font-weight:600; color:var(--ink-2);
  margin-bottom:5px; }
.field__hint{ font-size:var(--fs-2xs); color:var(--ink-3); margin-top:5px; }
.field__error{ font-size:var(--fs-2xs); color:var(--danger-ink); margin-top:5px; }

.input,.select,.textarea{
  display:block; width:100%; min-height:38px; padding:7px 10px;
  background:var(--paper); color:var(--ink);
  border:1px solid var(--rule-strong); border-radius:var(--r-ctl);
  transition:border-color var(--t), box-shadow var(--t);
}
.input:hover,.select:hover,.textarea:hover{ border-color:var(--ink-4); }
.input:focus,.select:focus,.textarea:focus{ outline:none; border-color:var(--accent); box-shadow:var(--focus); }
.input[aria-invalid="true"]{ border-color:var(--danger); }
/* A control that waits on another one — say a date beside "arriving on" —
   should read as not yet applicable rather than merely unstyled. */
.input:disabled,.select:disabled,.textarea:disabled{
  background:var(--canvas-2); color:var(--ink-4); border-color:var(--rule); cursor:not-allowed;
}
.input:disabled:hover,.select:disabled:hover{ border-color:var(--rule); }
.textarea{ min-height:110px; resize:vertical; line-height:1.5; }
.select{ appearance:none; padding-right:30px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236B7A86' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center; }
.input--sm{ min-height:32px; padding:4px 8px; font-size:var(--fs-2xs); }

.grid-2{ display:grid; grid-template-columns:1fr 1fr; gap:0 var(--s4); }
.grid-3{ display:grid; grid-template-columns:repeat(3,1fr); gap:0 var(--s4); }
@media (max-width:640px){ .grid-2,.grid-3{ grid-template-columns:1fr; } }

.check{ display:inline-flex; align-items:center; gap:var(--s2); cursor:pointer; }
.check input{ width:18px; height:18px; accent-color:var(--accent); }

/* ── Tables ─────────────────────────────────────────────────────────────── */

.table{ background:var(--paper); }
.table th{
  padding:10px var(--s3); font-size:var(--fs-2xs); font-weight:600; color:var(--ink-3);
  border-bottom:1px solid var(--rule-strong); white-space:nowrap;
}
.table td{ padding:10px var(--s3); border-bottom:1px solid var(--rule); vertical-align:middle; }
.table tbody tr:hover{ background:var(--canvas); }
.table--dense td{ padding:6px var(--s3); }
.table__scroll{ overflow-x:auto; border:1px solid var(--rule); border-radius:var(--r-card);
  background:var(--paper); box-shadow:var(--shadow-sm); }
.table__actions{ text-align:right; white-space:nowrap; }
.table__empty{ padding:var(--s10) var(--s4); text-align:center; color:var(--ink-3); }

/* ── Badges, dots, meters ───────────────────────────────────────────────── */

.badge{
  display:inline-flex; align-items:center; gap:4px;
  padding:2px 8px; border-radius:var(--r-pill);
  font-size:var(--fs-2xs); font-weight:600; line-height:1.5;
  background:var(--canvas-2); color:var(--ink-2);
}
.badge--ok{ background:var(--ok-wash); color:var(--ok-ink); }
.badge--busy{ background:var(--busy-wash); color:var(--busy-ink); }
.badge--warn{ background:var(--warn-wash); color:var(--warn-ink); }
.badge--danger{ background:var(--danger-wash); color:var(--danger-ink); }
.badge--accent{ background:var(--accent-wash); color:var(--accent); }
.badge--solid{ background:var(--ink); color:var(--paper); }

.dot{ width:9px; height:9px; border-radius:50%; flex:none;
  box-shadow:0 0 0 1px var(--grade-ring) inset, 0 0 0 1px var(--grade-ring); }
.dot--green{ background:var(--grade-green); }
.dot--yellow{ background:var(--grade-yellow); }
.dot--red{ background:var(--grade-red); }

.meter{ height:6px; border-radius:var(--r-pill); background:var(--canvas-2); overflow:hidden; }
.meter__fill{ height:100%; background:var(--ink-3); border-radius:inherit; }
.meter__fill--danger{ background:var(--danger); }

.stat{ padding:var(--s4) var(--s5); background:var(--paper); border:1px solid var(--rule); border-radius:var(--r-card); }
.stat__label{ font-size:var(--fs-xs); color:var(--ink-3); }
.stat__value{ font-family:var(--font-display); font-size:var(--fs-xl); font-weight:750; letter-spacing:-.02em; margin-top:2px; }

/* ── Charts ───────────────────────────────────────────────────────────────
   Drawn on the server as inline SVG, so they print, they need no library and
   they do not wait on anything. Colour carries one meaning throughout: how
   full is it. Empty, in use, nearly full, and past the beds the house has —
   the same four bands on the night bars, the room meters and the ring, so a
   colour learned in one place is not relearned in the next. */

.statrow{
  display:grid; gap:var(--s3);
  grid-template-columns:repeat(auto-fit, minmax(170px, 1fr));
  margin-bottom:var(--s5);
}
.stat--ring{ display:flex; align-items:center; gap:var(--s4); }
.stat--ring .chart--donut{ flex:none; width:76px; height:76px; }

.chart{ display:block; width:100%; height:auto; }

.chart__track{ fill:none; stroke:var(--canvas-2); stroke-width:11; }
.chart__arc{ fill:none; stroke-width:11; stroke-linecap:round; }
.chart__arc--empty{ stroke:var(--rule-strong); }
.chart__arc--low  { stroke:var(--ink-4); }
.chart__arc--some { stroke:var(--accent); }
.chart__arc--full { stroke:var(--ok); }
.chart__arc--over { stroke:var(--danger); }
.chart__big{ font-family:var(--font-display); font-size:26px; font-weight:750; fill:var(--ink); }
.chart__sub{ font-size:11px; fill:var(--ink-3); }

.chart--nights{ height:auto; }
.chart__grid{ stroke:var(--rule); stroke-width:1; }
.chart__axis{ font-size:10px; fill:var(--ink-4); font-variant-numeric:tabular-nums; }
.chart__weekend{ fill:var(--ink); opacity:.035; }
.chart__bar{ transition:opacity var(--t); }
.chart__bar:hover{ opacity:.7; }
.chart__bar--empty{ fill:var(--rule-strong); }
.chart__bar--some { fill:var(--accent); }
.chart__bar--full { fill:var(--ok); }
.chart__bar--over { fill:var(--danger); }
/* The house's own bed count, over the bars it judges. */
.chart__capacity{ stroke:var(--ink); stroke-width:1.25; stroke-dasharray:5 4; opacity:.65; }

.meter__fill--empty{ background:var(--rule-strong); }
.meter__fill--low  { background:var(--ink-4); }
.meter__fill--some { background:var(--accent); }
.meter__fill--full { background:var(--ok); }
.meter__fill--over { background:var(--danger); }

/* One bar, split by share. Categorical colour here, not the fullness bands:
   a country is not more or less full than another one. */
.split{
  display:flex; height:12px; border-radius:var(--r-pill);
  overflow:hidden; background:var(--canvas-2);
}
.split__part{ height:100%; }
.split__part--rest{ background:var(--rule-strong); }
.split__keys{
  display:flex; flex-wrap:wrap; gap:4px var(--s3);
  margin-top:var(--s3); font-size:var(--fs-2xs); color:var(--ink-2);
}
.split__key{ display:inline-flex; align-items:center; gap:5px; }
.split__key b{ color:var(--ink-3); font-weight:600; }
.split__swatch{ width:9px; height:9px; border-radius:2px; flex:none; }
.split__swatch--rest{ background:var(--rule-strong); }

/* The legend that says what the colours mean, because a chart nobody can
   decode is a decoration. */
.chartkey{ display:flex; flex-wrap:wrap; gap:var(--s3); font-size:var(--fs-2xs); color:var(--ink-3); }
.chartkey__item{ display:inline-flex; align-items:center; gap:5px; }
.chartkey__dot{ width:9px; height:9px; border-radius:2px; flex:none; }
.chartkey__dot--full{ background:var(--ok); }
.chartkey__dot--some{ background:var(--accent); }
.chartkey__dot--over{ background:var(--danger); }
.chartkey__rule{ width:14px; height:0; border-top:1.5px dashed var(--ink); opacity:.65; flex:none; }

@media print{
  .chart__bar:hover{ opacity:1; }
}

/* ── Feedback ───────────────────────────────────────────────────────────── */

.alert{
  padding:11px var(--s4); border-radius:var(--r-ctl); margin-bottom:var(--s4);
  font-size:var(--fs-sm); border:1px solid transparent;
}
.alert--success{ background:var(--ok-wash); color:var(--ok-ink); border-color:color-mix(in oklab, var(--ok) 28%, var(--paper)); }
.alert--error{ background:var(--danger-wash); color:var(--danger-ink); border-color:color-mix(in oklab, var(--danger) 28%, var(--paper)); }
.alert--warn{ background:var(--warn-wash); color:var(--warn-ink); border-color:color-mix(in oklab, var(--warn) 30%, var(--paper)); }
.alert--info{ background:var(--accent-wash); color:var(--ink-2); border-color:var(--accent-line); }

.empty{ padding:var(--s12) var(--s4); text-align:center; color:var(--ink-3); }
.empty__title{ font-family:var(--font-display); font-size:var(--fs-lg); color:var(--ink-2); margin-bottom:var(--s2); }

.toaster{ position:fixed; left:50%; bottom:var(--s5); transform:translateX(-50%);
  z-index:80; display:flex; flex-direction:column; gap:var(--s2); align-items:center; }
.toast{
  display:flex; align-items:center; gap:var(--s3);
  padding:10px var(--s4); border-radius:var(--r-ctl);
  background:var(--ink); color:var(--paper); font-size:var(--fs-sm); box-shadow:var(--shadow-pop);
}
.toast--error{ background:var(--danger); }
.toast button{ color:inherit; font-weight:600; text-decoration:underline; }

/* ── Modal ──────────────────────────────────────────────────────────────── */

.modal{
  width:min(560px, calc(100vw - 32px)); max-height:calc(100vh - 64px);
  padding:0; border:1px solid var(--rule); border-radius:var(--r-modal);
  background:var(--paper); color:var(--ink); box-shadow:var(--shadow-modal);
}
.modal::backdrop{ background:rgba(8,14,24,.45); }
.modal--wide{ width:min(900px, calc(100vw - 32px)); }
.modal__head{ display:flex; align-items:center; gap:var(--s3); padding:var(--s4) var(--s5);
  border-bottom:1px solid var(--rule); }
.modal__title{ font-family:var(--font-display); font-size:var(--fs-lg); font-weight:700; letter-spacing:-.015em; }
.modal__close{ margin-left:auto; width:32px; height:32px; border-radius:var(--r-ctl); color:var(--ink-3);
  display:flex; align-items:center; justify-content:center; }
.modal__close:hover{ background:var(--canvas); color:var(--ink); }
.modal__body{ padding:var(--s5); overflow:auto; }
.modal__foot{ display:flex; justify-content:flex-end; gap:var(--s2);
  padding:var(--s3) var(--s5); border-top:1px solid var(--rule); background:var(--paper-2); }

.popover{
  position:absolute; z-index:60; width:300px; padding:var(--s4);
  background:var(--paper); border:1px solid var(--rule);
  border-radius:var(--r-card); box-shadow:var(--shadow-pop);
}

/* ── Login ──────────────────────────────────────────────────────────────── */

.auth{
  min-height:100vh; min-height:100dvh; display:flex; align-items:center; justify-content:center;
  padding:var(--s5);
  background:var(--ink) url('../img/hotel-winter.jpg') center/cover no-repeat;
}
.auth::before{ content:''; position:fixed; inset:0; background:linear-gradient(180deg,
  rgba(18,33,46,.30) 0%, rgba(18,33,46,.62) 100%); }
.auth__card{
  position:relative; width:min(390px,100%); padding:var(--s8) var(--s6) var(--s6);
  background:var(--paper); border-radius:var(--r-card); box-shadow:var(--shadow-modal);
}
.auth__brand{ font-family:var(--font-display); font-size:26px; font-weight:600; letter-spacing:.01em; }
.auth__tagline{ font-size:var(--fs-2xs); color:var(--ink-4); text-transform:uppercase;
  letter-spacing:.14em; margin-bottom:var(--s6); }
.auth__foot{ margin-top:var(--s5); padding-top:var(--s4); border-top:1px solid var(--rule);
  display:flex; align-items:center; gap:var(--s3); font-size:var(--fs-2xs); }
.auth__credit{ position:relative; margin-top:var(--s4); text-align:center;
  font-size:var(--fs-3xs); color:rgba(255,255,255,.55); }

/* ═══════════════════════════════════════════════════════════════════════════
   The front desk.

   Thirty children off a bus, one member of staff, an iPad on the counter.
   Hit areas are 44px; the visual weight is not, because a wall of big boxes is
   harder to read down than a tight list. The two are decoupled by padding an
   inner element rather than the row.
   ═══════════════════════════════════════════════════════════════════════════ */

.deskgroup{ margin-bottom:var(--s5); border:1px solid var(--rule); border-radius:var(--r-card);
  background:var(--paper); overflow:hidden; }
.deskgroup{ box-shadow:var(--shadow-sm); }
.deskgroup__bar{
  display:flex; align-items:center; gap:var(--s3); flex-wrap:wrap;
  padding:var(--s3) var(--s5); background:var(--paper-2); border-bottom:1px solid var(--rule);
}
.deskgroup__title{ font-family:var(--font-display); font-size:var(--fs-md); font-weight:700; letter-spacing:-.01em; color:var(--ink); }
.deskgroup__meta{ font-size:var(--fs-2xs); color:var(--ink-3); }

.arow td{ vertical-align:middle; }
.arow--arrived{ background:var(--ok-wash); }
.arow--failed{ box-shadow:inset 3px 0 0 var(--danger); }
.arow--noroom td{ background:var(--warn-wash); }
.rowstate{ font-size:var(--fs-2xs); color:var(--ink-3); white-space:nowrap; }
.rowstate--failed{ color:var(--danger-ink); font-weight:600; cursor:pointer; }
.rowstate--ok{ color:var(--ok-ink); }

/* Big target, small painted box. */
.tick{
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--tap); height:var(--tap); margin:-7px 0; touch-action:manipulation;
}
.tick::before{
  content:''; width:24px; height:24px; border-radius:var(--r-cell);
  border:2px solid var(--rule-strong); background:var(--paper);
  transition:background var(--t), border-color var(--t);
}
.tick[aria-checked="true"]::before{
  background:var(--ok); border-color:var(--ok);
  /* The tick itself, drawn rather than pulled from a font. */
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size:16px; background-repeat:no-repeat; background-position:center;
}
.tick:hover::before{ border-color:var(--ink-4); }

.keyfield{
  width:96px; min-height:38px; padding:6px 8px; text-align:center;
  border:1px solid var(--rule-strong); border-radius:var(--r-cell);
  background:var(--paper); color:var(--ink);
  font-variant-numeric:tabular-nums; letter-spacing:.04em;
}
.keyfield:focus{ outline:none; border-color:var(--accent); box-shadow:var(--focus); }
.keyfield.is-saving{ border-color:var(--accent); }
.keyfield.is-failed{ border-color:var(--danger); background:var(--danger-wash); }


/* ── Click-to-copy ──────────────────────────────────────────────────────────
   Reception retypes each of these into the guest-card system in the window
   next door, so the copied state has to be unmistakable and the button must
   not move under the cursor while they work down the list. */

.copy{
  /* Label above the value, not beside it: the value has to be readable in
     full while it is being retyped into the other window, and a phone number
     or an email truncated to "+43 660 2223…" is useless for that. */
  position:relative; display:block; width:100%; min-height:var(--tap);
  padding:4px 26px 5px 9px; border:1px solid var(--rule); border-radius:var(--r-ctl);
  background:var(--paper); font-size:var(--fs-sm); color:var(--ink);
  text-align:left; transition:background var(--t), border-color var(--t);
}
.copy:hover{ border-color:var(--accent-line); background:var(--accent-wash); }
.copy__label{ display:block; font-size:var(--fs-3xs); font-weight:600;
  color:var(--ink-3); line-height:1.4; }
.copy__value{ display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-variant-numeric:tabular-nums; line-height:1.3; }
.copy__value--empty{ color:var(--ink-4); font-style:italic; }
.copy::after{ content:'⧉'; position:absolute; right:8px; top:50%; transform:translateY(-50%);
  color:var(--ink-4); }
.copy.is-copied{ background:var(--ok-wash); border-color:var(--ok); color:var(--ok-ink); }
.copy.is-copied::after{ content:'✓'; color:var(--ok); }
.copy.is-copied .copy__label{ color:var(--ok-ink); }
.copy.is-failed{ background:var(--danger-wash); border-color:var(--danger); }
.copy[disabled]{ opacity:.5; pointer-events:none; }

.cardrow{ border-bottom:1px solid var(--rule); padding:var(--s4) var(--s5); }
.cardrow:last-child{ border-bottom:0; }
.cardrow--done{ background:var(--paper-2); }
.cardrow__head{ display:flex; align-items:center; gap:var(--s3); margin-bottom:var(--s2); }
.cardrow__name{ font-family:var(--font-display); font-size:var(--fs-md); font-weight:700; letter-spacing:-.01em; }
.cardrow__fields{ display:grid; gap:6px;
  grid-template-columns:repeat(auto-fill, minmax(215px, 1fr)); }

/* The copy view is made to sit beside another window, so it stays usable at
   about a third of a screen. */
@media (max-width: 620px){
  .cardrow__fields{ grid-template-columns:1fr; }
}

/* ── The bell ───────────────────────────────────────────────────────────────
   Housekeeping finishing a room is the one thing that happens away from the
   desk and blocks a guest checking in, so it gets a place in the chrome. */

.bell{
  position:relative; display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; border-radius:var(--r-ctl); color:var(--ink-3);
  transition:background var(--t), color var(--t);
}
.bell:hover{ background:var(--canvas); color:var(--ink); text-decoration:none; }
.bell--on{ color:var(--accent); }
.bell__count{
  position:absolute; top:3px; right:2px; min-width:17px; height:17px; padding:0 4px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-pill); background:var(--danger); color:#fff;
  font-size:10px; font-weight:700; font-variant-numeric:tabular-nums;
  box-shadow:0 0 0 2px var(--paper);
}

.notifrow{ display:flex; align-items:flex-start; gap:var(--s3);
  padding:var(--s4) var(--s5); border-bottom:1px solid var(--rule); }
.notifrow:last-child{ border-bottom:0; }
.notifrow__dot{ width:8px; height:8px; border-radius:50%; background:transparent; margin-top:6px; flex:none; }
.notifrow--unread{ background:var(--accent-wash); }
.notifrow--unread .notifrow__dot{ background:var(--accent); }
.notifrow__title{ font-weight:600; }

/* ── Today ──────────────────────────────────────────────────────────────────
   Every screen here is "as of a date", and the commonest mistake anybody can
   make with it is acting on the wrong one. So today says so in words wherever
   a date can be chosen, rather than leaving it to be worked out. */

.todaymark{
  display:inline-flex; align-items:center; vertical-align:middle;
  margin-left:10px; padding:3px 10px; border-radius:var(--r-pill);
  background:var(--accent-wash); color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent-line);
  font-family:var(--font-ui); font-size:var(--fs-2xs); font-weight:650;
  letter-spacing:0; line-height:1.5;
}

/* Meals on the first and last day of a stay, which are negotiated separately
   from the days in between. */
.edgemeals{ border:1px solid var(--rule); border-radius:var(--r-ctl); padding:var(--s4); }
.edgemeals legend{ padding:0 6px; }
.edgemeals__col{ padding-bottom:var(--s2); }
.edgemeals__meals{ display:flex; flex-wrap:wrap; gap:var(--s3); margin:var(--s2) 0 0 26px; }

/* ── The account button ─────────────────────────────────────────────────────
   This used to read "DE ▾", which looks like a language switcher — so nobody
   found user management behind it. It now looks like what it is: the person
   who is signed in, with everything about their account inside. */

.account{
  display:flex; align-items:center; gap:8px;
  height:38px; padding:0 10px 0 4px; border-radius:var(--r-pill);
  border:1px solid var(--rule); background:var(--paper);
  font-size:var(--fs-sm); color:var(--ink-2);
}
.account:hover{ background:var(--canvas); border-color:var(--rule-strong); }
.account__initials{
  width:28px; height:28px; border-radius:50%; flex:none;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent); color:var(--on-accent);
  font-size:var(--fs-2xs); font-weight:700; letter-spacing:.02em;
}
.account__name{ max-width:150px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.account__chev{ color:var(--ink-4); font-size:10px; }

@media (max-width: 1100px){ .account__name{ display:none; } .account{ padding-right:6px; } }

/* ── A stay, on the guest's own page ────────────────────────────────────────
   The same controls the front desk uses, because "change this guest's key
   card" should not depend on finding them in today's list. */

.staycard{ padding:var(--s4) var(--s5); border-bottom:1px solid var(--rule); }
.staycard:last-child{ border-bottom:0; }
.staycard__head{ display:flex; align-items:center; gap:var(--s3); flex-wrap:wrap;
  font-size:var(--fs-sm); margin-bottom:var(--s2); }
.staycard__controls{ display:flex; align-items:flex-end; gap:var(--s4); flex-wrap:wrap; }
.staycard__field{ display:flex; flex-direction:column; gap:3px; }
.staycard__field--tick{ align-items:center; }
.staycard__field .field__label{ margin:0; white-space:nowrap; }
.staycard__sleeps{ margin-left:auto; align-self:center; }

/* ── The retention stages ───────────────────────────────────────────────────
   Numbered because they genuinely are a sequence: the same person's data goes
   in three steps, each at its own distance from the day they left. */

.stage{ display:flex; gap:var(--s4); align-items:flex-start;
  padding:var(--s5); margin-bottom:var(--s3); }
.stage__n{
  flex:none; width:30px; height:30px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-wash); color:var(--accent);
  font-weight:700; font-variant-numeric:tabular-nums;
}
.stage__body{ flex:1; min-width:0; }
.stage__title{ font-family:var(--font-display); font-size:var(--fs-md); font-weight:700; letter-spacing:-.01em; margin-bottom:4px; }
.stage__what{ font-size:var(--fs-sm); margin-bottom:4px; }
.stage__why{ font-size:var(--fs-2xs); color:var(--ink-3); }
.stage__when{ flex:none; width:180px; text-align:right; }

/* ── Term and answer ──────────────────────────────────────────────────────
   For the places that are genuinely a list of questions with answers — who
   sees what, where the data sits — rather than a table pretending to be one. */
.deflist{ display:grid; grid-template-columns:minmax(140px, 210px) 1fr; gap:var(--s2) var(--s4); }
.deflist dt{ font-size:var(--fs-sm); font-weight:600; }
.deflist dd{ margin:0; font-size:var(--fs-sm); color:var(--ink-2); }

/* ── Money ────────────────────────────────────────────────────────────────
   One charge, its three sums, and everything paid against it. The three sums
   sit on one line in a fixed order — owed, paid, left — so the eye lands on
   the same number in the same place on every card, and "left" is the only one
   that ever changes colour, because it is the only one anybody has to act on.

   A voided charge or payment is dimmed and struck through rather than removed:
   money that was on the page and then vanished is worse than money that is
   visibly cancelled. */

.chargecard{
  border:1px solid var(--rule); border-radius:var(--r-ctl);
  background:var(--paper); margin-bottom:var(--s3);
}
.chargecard:last-child{ margin-bottom:0; }
.chargecard--void{ opacity:.6; }
.chargecard--void .chargecard__payer{ text-decoration:line-through; }

.chargecard__head{
  display:flex; align-items:flex-start; gap:var(--s3);
  padding:var(--s3) var(--s4); border-bottom:1px solid var(--rule);
}
.chargecard__payer{ font-size:var(--fs-sm); font-weight:650; }

.chargecard__sums{
  display:flex; align-items:center; gap:var(--s5); flex-wrap:wrap;
  padding:var(--s3) var(--s4);
}
.chargecard__sums > div{ display:flex; flex-direction:column; gap:1px; }
.chargecard__label{
  font-size:var(--fs-3xs); font-weight:600; color:var(--ink-3);
}
.chargecard__sums .nums{ font-family:var(--font-display); font-size:var(--fs-md); font-weight:650; font-variant-numeric:tabular-nums; }
.chargecard__left--owing{ color:var(--danger-ink); font-weight:700; }

.paylist{ list-style:none; margin:0; padding:0 var(--s4) var(--s3); }
.paylist__row{
  display:flex; align-items:baseline; gap:var(--s3);
  padding:5px 0; border-top:1px solid var(--rule);
  font-size:var(--fs-2xs);
}
.paylist__when{ flex:none; width:64px; color:var(--ink-3); }
.paylist__amount{ flex:none; min-width:92px; font-weight:600; font-size:var(--fs-xs); }
.paylist__how{ min-width:0; }
.paylist__row--void .paylist__when,
.paylist__row--void .paylist__amount{ text-decoration:line-through; color:var(--ink-4); }

.stat__value--owing{ color:var(--danger-ink); }

/* ── A short list of people ───────────────────────────────────────────────
   The cleaning roster and its history. Names on the left, the quiet facts on
   the right, the action last. */
.teamlist{ list-style:none; margin:0; padding:0; display:grid; gap:2px; }
.teamlist__row{
  display:flex; align-items:center; gap:var(--s3);
  padding:var(--s2) 0; border-bottom:1px solid var(--rule);
}
.teamlist__row:last-child{ border-bottom:0; }
.teamlist__name{ font-size:var(--fs-sm); font-weight:600; }
.teamlist__meta{ margin-left:auto; font-size:var(--fs-2xs); color:var(--ink-3);
  text-align:right; font-variant-numeric:tabular-nums; }
.teamlist__row--off .teamlist__name{ color:var(--ink-4); text-decoration:line-through; }
.teamlist--log{ max-height:340px; overflow-y:auto; }
.teamlist--log .teamlist__name{ font-weight:500; }
@media (max-width:620px){
  .deflist{ grid-template-columns:1fr; gap:2px var(--s4); }
  .deflist dd{ margin-bottom:var(--s3); }
}
.stage__when .hstack{ justify-content:flex-end; }
.stage__due{ margin-top:8px; font-size:var(--fs-2xs); color:var(--ink-4); }
.stage__due--now{ color:var(--warn-ink); font-weight:600; }

@media (max-width:720px){
  .stage{ flex-wrap:wrap; }
  .stage__when{ width:100%; text-align:left; }
  .stage__when .hstack{ justify-content:flex-start; }
}

/* ── A folding section heading ──────────────────────────────────────────────
   The browser's own triangle sits on the baseline and looks borrowed; this
   one is drawn, turns when the section opens, and lines up with the text. */
details > summary.h2{ list-style:none; display:flex; align-items:center; gap:var(--s2); }
details > summary.h2::-webkit-details-marker{ display:none; }
details > summary.h2::before{
  content:''; flex:none; width:8px; height:8px; margin:0 4px 0 2px;
  border-right:2px solid var(--ink-3); border-bottom:2px solid var(--ink-3);
  transform:rotate(-45deg); transition:transform var(--t);
}
details[open] > summary.h2::before{ transform:rotate(45deg) translate(-2px, -2px); }

/* Section headings on the older screens, in the display face like the
   rooming sheet's building names. */
.page .h2{ font-weight:700; letter-spacing:-.015em; }
.page .h2 .badge{ vertical-align:middle; margin-left:6px; font-family:var(--font-ui); letter-spacing:0; }
