/* ============================================================================
   "We fixed it" notice — a modal, deliberately.

   The update bar next door is an offer and stays out of the way. This one is a
   reply to something the client raised, and it is dismissed for good on the
   first tap, so it gets the middle of the screen once and then never again.

   Tokens only, and no theme blocks: --scrim already carries a dark value in
   both themes, which is the one place a modal would otherwise be tempted to
   hard-code a colour.
   ========================================================================= */

.ntc {
  position: fixed;
  inset: 0;
  /* Over the chrome (20), the preview banner (30) and the update bar (40) — and
     over the other dialogs (100) too. Those are opened by a deliberate tap and
     this one arrives on its own, so on the rare overlap the visible dialog must
     be the one holding the focus trap; a buried modal that still eats Tab is a
     dead app. */
  z-index: 110;

  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--gutter);
}

.ntc__scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  animation: ntc-fade 160ms ease-out;
}

.ntc__dialog {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 420px;
  /* Against .ntc's content box, not the viewport. Those are not the same box:
     on a phone with a home indicator .ntc carries an extra safe-area inset at
     the bottom, and a dialog measured against 100dvh is taller than the space
     .ntc actually leaves it — centred, so half of the excess goes under the
     indicator, taking the bottom of the "Got it" button with it. */
  max-height: 100%;

  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);

  animation: ntc-pop 170ms cubic-bezier(.2, .8, .3, 1);
}

.ntc__title {
  /* Operator-typed, so it can be anything — including a pasted URL with no
     spaces in it, which at 375px would otherwise push the dialog wider than
     the phone. */
  overflow-wrap: anywhere;

  margin: 0;
  padding: 22px 22px 0;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.3;
}

.ntc__body {
  /* The body is one operator-authored string set with textContent, so the only
     structure it can carry is its own line breaks. pre-wrap keeps the
     paragraphs he typed without letting any markup through. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;

  flex: 0 1 auto;
  overflow-y: auto;
  padding: 12px 22px 4px;

  font-size: .95rem;
  line-height: 1.55;
  color: var(--text-muted);
}

.ntc__foot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 22px 20px;
}

/* Pushes the button to the right whether or not the counter is there. */
.ntc__count { margin-right: auto; }

.ntc__btn {
  min-height: var(--tap);
  padding: 0 22px;
  margin-left: auto;
}

@keyframes ntc-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes ntc-pop {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

/* One-handed: the button spans the width so it is reachable with a thumb, and
   the counter moves above it rather than squeezing it. */
@media (max-width: 460px) {
  .ntc { padding: var(--gutter) var(--gutter) calc(var(--gutter) + env(safe-area-inset-bottom)); }
  .ntc__title { padding: 18px 18px 0; font-size: 1.15rem; }
  .ntc__body { padding: 10px 18px 4px; }
  .ntc__foot {
    flex-wrap: wrap;
    padding: 16px 18px 18px;
  }
  .ntc__count { flex: 1 0 100%; margin-right: 0; }
  .ntc__btn { flex: 1 1 auto; margin-left: 0; }
}

/* Someone who has asked for less motion gets the dialog, not the entrance. */
@media (prefers-reduced-motion: reduce) {
  .ntc__scrim,
  .ntc__dialog { animation: none; }
}
