/* ============================================================
   v1 additions.

   The five approved layers are copied from the prototype unchanged,
   so everything the prototype already styled still looks the way it
   was signed off. This sixth file holds only what v1 needs that the
   prototype had no model for: coverage inside a window, the public
   record as its own state, and the sign-in form.

   Layer rule still applies: nothing here restyles a token or a
   component. It adds.
   ============================================================ */

/* ---------- Sign in ---------- */
.signin-page { display: grid; place-items: center; min-height: 100dvh; padding: 24px; }
.signin { width: 100%; max-width: 380px; }
.signin-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 28px; }
.brand-emblem.lg { width: 42px; height: 42px; }
.signin-title { font-size: 1.5rem; margin: 0 0 6px; letter-spacing: -0.01em; }
.signin-sub { color: var(--ink-muted); margin: 0 0 24px; }
.signin-form { display: grid; gap: 14px; }
.signin-error {
  margin: 0; padding: 10px 12px; border-radius: var(--r-md);
  background: var(--danger-soft); color: var(--danger-ink);
  border: 1px solid var(--danger-line); font-size: 0.9rem;
}
.signin-note { color: var(--ink-muted); font-size: 0.82rem; margin-top: 20px; line-height: 1.5; }

/* ---------- Loading ---------- */
.loading {
  display: flex; align-items: center; gap: 10px; justify-content: center;
  padding: 56px 20px; color: var(--ink-muted);
}
.spin {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--ink-soft);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spin { animation-duration: 2s; } }

/* ---------- Coverage inside a calendar block ----------
   The block is the window the public was promised. The filled bars are the
   hours a host is actually there. What stays empty is the gap, and it reads as
   a hole in the block rather than a colour you have to look up. */
.cal-ev { position: absolute; overflow: hidden; }
.cal-shift {
  position: absolute; left: 0; right: 0;
  background: currentColor; opacity: 0.16; pointer-events: none;
}
.cal-ev[data-cov="partial"] { border-style: dashed; }
.cal-ev[data-cov="none"] .cal-shift { display: none; }

/* ---------- Coverage in words ---------- */
.cov-line {
  margin: 0; padding: 10px 12px; border-radius: var(--r-md);
  font-size: 0.88rem; line-height: 1.45; border: 1px solid transparent;
}
.cov-line.ok    { background: var(--positive-soft);    color: var(--positive-ink);    border-color: var(--positive-line); }
.cov-line.warn  { background: var(--attention-soft);  color: var(--attention-ink);  border-color: var(--attention-line); }
.cov-line.open  { background: var(--neutral-soft);  color: var(--neutral-ink);  border-color: var(--neutral-line); }

/* ---------- Ask dialog ---------- */
.askbox { max-width: 460px; width: calc(100vw - 32px); }
/* The ask dialog needs its own surface. `.sheet` is deliberately
   transparent — it is a frame, and the card is normally supplied by
   `.sheet-in` — but Shell.ask() builds a bare <form> instead, so without
   this the title and body of every confirmation dialog in the app render
   straight onto the translucent backdrop, over whatever is behind it. The
   only thing that looked like a dialog was the textarea.

   `margin: auto` restores the vertical centring the browser gives a modal
   <dialog> by default; `.sheet` overrides it to `auto auto 0` to sit at the
   thumb on a phone, which for a small confirmation box reads as pinned to
   the top of the screen on a desk. */
/* Restores the centring a modal <dialog> gets from the UA stylesheet.
   `.sheet` overrides it to `margin: auto auto 0` so a sheet rises from the
   bottom edge, where a thumb is — right for a full-height sheet on a phone,
   wrong for a small confirmation box on a desk, which ends up pinned to the
   top of the screen. Both insets have to be 0 for the auto margins to have
   anything to distribute; releasing one instead just re-pins it. */
.askbox { margin: auto; inset-block: 0; }
.askform {
  display: grid; gap: 14px;
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--canvas);
  box-shadow: var(--shadow-rail);
}
.sheet-acts { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }
.sheet-acts .btn { min-height: 44px; }

/* ---------- Requirement rows (checklist, publications, setups) ---------- */
.reqs { display: grid; gap: 2px; }
.req {
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center;
  padding: 12px 14px; background: var(--surface); border-bottom: 1px solid var(--line-soft);
}
.req:last-child { border-bottom: 0; }
.req-copy { min-width: 0; }
.req-label { margin: 0; font-weight: 550; font-size: 0.94rem; }
.req-meta { margin: 3px 0 0; color: var(--ink-muted); font-size: 0.8rem; line-height: 1.4; }
/* Status that belongs with the copy, not with the buttons. `.req` is a
   `1fr auto` grid: anything placed in the action column is measured at
   max-content and takes the width it wants, so a couple of chips over
   there quietly starve the address column to one word per line. */
.req-chips { margin: 0 0 5px; display: flex; gap: 6px; flex-wrap: wrap; }
.req-act { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.req-act .btn { min-height: 44px; }
.req[data-done="true"] .req-label { color: var(--ink-soft); }

/* Says what is still missing, so nobody reads a disabled button as "the system
   is broken".

   NOT called .gate: the approved shell already owns that name for the
   full-screen sign-in gate, which is min-height:100dvh. Reusing it made every
   one of these paragraphs a whole viewport tall. */
.callout {
  margin: 0; padding: 12px 14px; border-radius: var(--r-md);
  background: var(--attention-soft); color: var(--attention-ink);
  border: 1px solid var(--attention-line); font-size: 0.88rem; line-height: 1.5;
}
.callout.ok { background: var(--positive-soft); color: var(--positive-ink); border-color: var(--positive-line); }
.callout ul { margin: 6px 0 0; padding-left: 18px; }
.callout li { margin: 2px 0; }

/* ---------- Urgency ---------- */
.urgent-flag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: 999px; font-size: 0.74rem; font-weight: 650;
  letter-spacing: 0.02em; text-transform: uppercase;
  background: var(--danger-soft); color: var(--danger-ink); border: 1px solid var(--danger-line);
}

/* ---------- History ---------- */
.hist { display: grid; gap: 0; }
.hist-item {
  display: grid; grid-template-columns: auto 1fr; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--line-soft); align-items: baseline;
}
.hist-item:last-child { border-bottom: 0; }
.hist-when { color: var(--ink-muted); font-size: 0.78rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hist-what { margin: 0; font-size: 0.88rem; line-height: 1.45; }
.hist-who { color: var(--ink-muted); }
.hist-why { display: block; color: var(--ink-muted); font-size: 0.82rem; margin-top: 2px; }

/* ---------- Notification obligations ----------
   Deliberately styled as a record, not as a sent message. Nothing in this
   product delivers anything yet and the interface must not imply otherwise. */
.obligation {
  display: grid; grid-template-columns: 1fr auto; gap: 10px;
  padding: 10px 12px; border-bottom: 1px solid var(--line-soft); align-items: center;
}
.obligation:last-child { border-bottom: 0; }
.obligation p { margin: 0; font-size: 0.86rem; }
.obligation .who { color: var(--ink-muted); font-size: 0.78rem; }

/* ---------- Search ---------- */
.searchbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.searchbar input { flex: 1 1 220px; min-height: 48px; }

/* ---------- Detail layout ---------- */
.detail-grid { display: grid; gap: 16px; }
@media (min-width: 1100px) {
  .detail-grid { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); align-items: start; }
  .detail-grid > .detail-wide { grid-column: 1 / -1; }
}

.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0; }
.kv dt { color: var(--ink-muted); font-size: 0.82rem; }
.kv dd { margin: 0; font-size: 0.88rem; }

.backlink {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
  color: var(--ink-soft); font-size: 0.88rem; background: none; border: 0; cursor: pointer;
  padding: 0 4px 0 0;
}
.backlink:hover { color: var(--ink); }

/* ---------- Empty calendar ---------- */
.cal-empty { padding: 48px 20px; text-align: center; }

/* ---------- Sign in sits on the light canvas ----------
   The brand block is built for the dark rail, where --shell-ink is near-white.
   On the sign-in page it is on the light canvas, so it needs the canvas ink or
   the brokerage's name is grey-on-grey. */
.signin-brand .brand-copy .n { color: var(--ink); }
.signin-brand .brand-copy .s { color: var(--ink-muted); }

/* ---------- Toolbar: the filters above a list ---------- */
.toolbar {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-bottom: var(--s4);
}
.toolbar .seg { flex: 0 1 auto; }

/* ---------- Section heading inside a panel ---------- */
.sec-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin: 0 0 10px;
}
.sec-head h2 { margin: 0; font-size: 1rem; letter-spacing: -0.005em; }
.sec-head .sec-note { color: var(--ink-muted); font-size: 0.82rem; }

/* ---------- A crowded calendar day scrolls instead of shrinking ----------
   Ten open houses in the same hours used to divide the column ten ways, which
   truncated every address to one character. Each lane now has a floor and the
   day scrolls sideways. The hour rail is pinned so the times stay put. */
.cal-body { overflow-x: auto; overscroll-behavior-x: contain; }
.cal-body .cal-rail {
  position: sticky; left: 0; z-index: 2;
  background: var(--surface); flex: none;
}
.cal-body .cal-col { min-width: calc(var(--lanes, 1) * 132px); }

@media (max-width: 700px) {
  .cal-body .cal-col { min-width: calc(var(--lanes, 1) * 116px); }
}

/* The block is a window that may only be partly staffed, so its label has to
   survive being narrow: address on one line, coverage note under it. */
.cal-ev-in b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
.cal-ev-in i { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }

/* ---------- The 48px floor applies to primary actions everywhere ----------
   `btn-sm` exists so secondary controls can sit quietly in a dense row, but a
   PRIMARY action is the thing the page is asking you to do and the floor for
   those is 48px at every width. Enforcing it on the class rather than at each
   call site means a future `btn-primary btn-sm` cannot reintroduce the
   violation by accident. */
.btn.btn-primary { min-height: 48px; }

/* ============================================================
   Availability Setup wizard.

   One question per screen. The constraint that shapes all of this:
   the person using it opens a laptop once a week and is not going to
   read a form. So there is one thing to look at, one thing to press,
   and the way back is always visible.
   ============================================================ */
.wiz { max-width: 620px; margin: 0 auto; padding-bottom: 32px; }

.wiz-progress { margin-bottom: 28px; }
.wiz-bar {
  height: 4px; border-radius: 999px; background: var(--line-soft); overflow: hidden;
}
/* The fill is always full width and slides in from the left, rather than
   being a narrow box that grows. Transitioning `width` puts a layout pass in
   the middle of the animation; translating a fixed-size box does not.

   Why translate and not `scaleX`: the fill is a pill, and scaling one
   horizontally stretches its end cap into an ellipse — visible on a bar this
   round. A translation moves the real cap without deforming it, and the left
   end is clipped to the same pill shape by the parent's border-radius and
   `overflow: hidden`, exactly as it was when the width changed.

   The step percentage arrives as an inline transform from progress() in
   availability.js: 0% filled is translateX(-100%), fully filled is 0.

   Note what the transition currently does, which is nothing: the wizard
   re-renders with `host.innerHTML` on every step, so this span is a NEW
   element each time and has no previous value to animate from. That was
   equally true of the `width` transition this replaces — it never ran
   either. The declaration is kept because it costs nothing and becomes
   correct the day the wizard updates the bar in place instead of rebuilding
   it; it is not load-bearing today, so do not read the bar moving smoothly
   in a screenshot as evidence that it works. */
.wiz-bar span {
  display: block; width: 100%; height: 100%; background: var(--ink);
  border-radius: 999px;
  transform: translateX(-100%);
  transition: transform var(--t-mid) var(--ease-out);
}
.wiz-count {
  margin: 8px 0 0; font-size: var(--t-xs); color: var(--ink-muted);
  letter-spacing: var(--track-label); text-transform: uppercase;
}

.wiz-q {
  font-size: clamp(1.4rem, 4.2vw, 1.9rem); line-height: 1.2;
  letter-spacing: -0.015em; margin: 0 0 10px;
}
.wiz-help { margin: 0 0 22px; color: var(--ink-soft); line-height: 1.5; }
.wiz-help em { font-style: normal; font-weight: var(--fw-semibold); color: var(--ink); }
.wiz-note { margin: 14px 0 0; color: var(--ink-muted); font-size: var(--t-sm); }

/* ---- Option cards ---- */
.wiz-opts { display: grid; gap: 10px; }
.wiz-opt {
  display: grid; grid-template-columns: 1fr auto; gap: 14px; align-items: center;
  width: 100%; min-height: 64px; padding: 16px 18px; text-align: left;
  background: var(--surface-raised); border: 1.5px solid var(--line);
  border-radius: var(--r-lg); cursor: pointer; color: inherit;
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.wiz-opt:hover { border-color: var(--line-strong); background: var(--surface-hover); }
.wiz-opt[data-on="true"] { border-color: var(--ink); background: var(--surface-raised); }
.wiz-opt-main { min-width: 0; display: block; }
.wiz-opt-title {
  display: block; font-weight: var(--fw-semibold); font-size: 1rem; margin-bottom: 3px;
}
.wiz-opt-say {
  display: block; color: var(--ink-muted); font-size: var(--t-sm); line-height: 1.45;
}
.wiz-opt-tick {
  width: 24px; height: 24px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--line-strong); display: grid; place-items: center;
  color: transparent;
}
.wiz-opt-tick svg { width: 14px; height: 14px; }
.wiz-opt[data-on="true"] .wiz-opt-tick {
  background: var(--ink); border-color: var(--ink); color: var(--surface);
}

/* ---- Day picker ---- */
.wiz-days { display: flex; gap: 8px; flex-wrap: wrap; }
.wiz-day {
  min-width: 56px; min-height: 56px; padding: 0 6px;
  border-radius: var(--r-md); border: 1.5px solid var(--line);
  background: var(--surface-raised); cursor: pointer; color: inherit;
  font-weight: var(--fw-semibold); font-size: var(--t-sm);
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.wiz-day:hover { border-color: var(--line-strong); }
.wiz-day[data-on="true"] {
  background: var(--ink); border-color: var(--ink); color: var(--surface);
}
.wiz-daylist { margin-top: 16px; border: 1px solid var(--line-soft); border-radius: var(--r-md); }
.wiz-wide { width: 100%; margin-bottom: 4px; }

/* ---- Review ---- */
.wiz-summary {
  font-size: 1.08rem; line-height: 1.5; margin: 0 0 20px;
  padding: 16px 18px; border-radius: var(--r-md);
  background: var(--surface-sunken); border: 1px solid var(--line-soft);
}
.wiz-review { display: grid; gap: 0; margin: 0 0 18px; }
.wiz-review > div {
  display: grid; grid-template-columns: 8.5rem 1fr auto; gap: 12px;
  align-items: baseline; padding: 12px 0; border-bottom: 1px solid var(--line-soft);
}
.wiz-review > div:last-child { border-bottom: 0; }
.wiz-review dt { color: var(--ink-muted); font-size: var(--t-sm); }
.wiz-review dd { margin: 0; font-size: var(--t-base); }
.wiz-edit {
  background: none; border: 0; padding: 0 2px; min-height: 44px;
  color: var(--ink-soft); font-size: var(--t-sm); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.wiz-edit:hover { color: var(--ink); }

/* ---- Done ---- */
.wiz-done { text-align: left; }
.wiz-done-mark {
  width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center;
  background: var(--positive-soft); color: var(--positive-ink);
  border: 1px solid var(--positive-line); margin-bottom: 16px;
}
.wiz-done-mark svg { width: 24px; height: 24px; }
.wiz-facts {
  display: grid; gap: 10px; margin: 18px 0;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.wiz-facts > div {
  padding: 14px 16px; border-radius: var(--r-md);
  background: var(--surface-raised); border: 1px solid var(--line-soft);
}
.wiz-facts b { display: block; font-size: 1.4rem; line-height: 1.1; margin-bottom: 4px; }
.wiz-facts span { display: block; color: var(--ink-muted); font-size: var(--t-xs); line-height: 1.4; }
.wiz-acts { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 22px; }

/* ---- Footer nav ---- */
.wiz-nav {
  display: flex; gap: 10px; justify-content: space-between; align-items: center;
  margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--line-soft);
}
.wiz-nav .btn { min-height: 48px; min-width: 108px; }

@media (max-width: 560px) {
  .wiz-review > div { grid-template-columns: 1fr auto; }
  .wiz-review dt { grid-column: 1 / -1; }
  .wiz-nav .btn { flex: 1 1 auto; }
}

/* The queue row shows the status chip and the work hint together: the chip is
   the truth, the hint says what to do about it. */
.row-state .chip { margin-right: 8px; vertical-align: middle; }
.row-headline { vertical-align: middle; }

/* The bold time in a row means different things on different screens — the
   advertised open house on Needs a host, the host's own shift on My weekend.
   A one-word label under it is cheaper than making people infer from context. */
.row-when-note {
  display: block; margin-top: 2px; font-style: normal;
  font-size: var(--t-xs); color: var(--ink-muted);
  letter-spacing: var(--track-label); text-transform: uppercase;
}

/* A past item is not urgent, and must not borrow the urgent treatment. */
.urgent-flag.is-past {
  background: var(--neutral-soft); color: var(--neutral-ink);
  border-color: var(--neutral-line);
}

/* On a phone the requirement row put label, chip and buttons in one grid row,
   squeezing the text into ~43px. Stack it instead: text, then controls. */
@media (max-width: 560px) {
  .req { grid-template-columns: 1fr; gap: 10px; }
  .req-act { justify-content: flex-start; }
  .wiz-daylist .req { grid-template-columns: 1fr auto; }
}

/* A soft overlap is information, not an error, so it must not wear the error
   colour: the button beside it still works. */
.tl-warn[data-soft="true"] {
  background: var(--neutral-soft); color: var(--neutral-ink);
  border-color: var(--neutral-line);
}

/* ── Slack setup rows ───────────────────────────────────────
   A short identifier field sitting inline in a .req-act row. Narrow on
   purpose: a channel id is 11 characters and a full-width input would
   push the Save button off the row at tablet widths. */
.slackin {
  width: 148px;
  min-height: 44px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm, 8px);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--t-sm);
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}
.slackin:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}
