/* Content Calendar, the CLIENT PORTAL SETUP BAR (2026-08-21).
   Styles for window.buildPortalSetupBar in dd-portal-setup-bar.js.

   Every class here is pset-* prefixed and nothing in this file restyles a dd-*
   class. The bar REUSES .dd-card for its border, radius and background and
   .dd-btn / .dd-btn-sm / .dd-btn-primary for every control, so its buttons are
   the same buttons as the ones in the Focus Points card. Re-declaring any of
   those here would fork the look the first time deliverable-dashboard.css
   changes.

   Three things this file supplies that .dd-card does not:

   1. THE STATE COLOUR. .dd-card is a neutral white box, and the whole point of
      this bar is that its state is readable from across a desk. Red, green,
      amber and neutral are carried by a left edge stripe plus a tinted surface,
      never by colour alone: the title text says which state it is in, so a
      colour blind reader loses nothing. The palette is the one already in
      deliverable-dashboard.css (#b91c1c / #fecaca / #fef2f2 for danger,
      #16a34a / #15803d for complete) rather than a new set of greens.
   2. A 44px TAP TARGET AT 760px. .dd-btn-sm is 5px/9px padding, which is a
      mouse control. Under the breakpoint the actions go full width and full
      height, the same rule dd-focus-points-card.css applies to its own row
      controls.
   3. HOVER FREE ANSWERS FOR THE CLASSES THIS FILE OWNS. dd-mobile-hover-free.css
      already answers every :hover on .dd-btn and its variants, so the buttons
      are covered wherever they are mounted. The only hover this file adds is on
      .pset-act-quiet, and it gets its own @media (hover: none) answer at the
      bottom rather than being added to that file, so the bar can be reverted on
      its own.

   Dark mode follows the app convention, html[data-theme="dark"] overrides at the
   bottom, never a media query: the theme is a user setting in this app, not the
   operating system's. */

.pset-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  /* Tighter than a card, because it is a bar. The 4px left inset is the state
     stripe, painted with a border rather than a pseudo element so it cannot be
     clipped by the card's own border radius. */
  padding: 12px 16px;
  border-left-width: 4px;
  border-left-style: solid;
}

.pset-main {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;          /* let the text wrap instead of pushing the actions out */
  flex: 1 1 260px;
}

.pset-dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  margin-top: 4px;
  border-radius: 999px;
  background: #9ca3af;
}

.pset-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.pset-title {
  font-size: 13px;
  font-weight: 700;
  color: #111827;
  line-height: 1.3;
}

.pset-note {
  font-size: 12px;
  color: #6b7280;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.pset-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  flex: 0 0 auto;
}

/* Every action on this bar is a <button>. The two editor actions mint a write
   credential on click and must not exist as a followable href, so there is no
   anchor here to style.

   font-family is still declared because a <button> does NOT inherit the page
   font and this app has no global button font reset, so left alone the controls
   render in the UA default face while everything around them does not.
   box-sizing is the explicit guard behind the full width mobile rule below:
   width: 100% on a content-box control becomes 100% PLUS 24px of padding, which
   measured 337px against a 322px content box at 390px wide. */
.pset-act {
  box-sizing: border-box;
  font-family: inherit;
  color: #374151;
}
.pset-act.dd-btn-primary { color: #fff; }
.pset-act:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}
/* The quieter of the two green state actions. It is still a real button, only
   one step back from the one beside it. */
.pset-act-quiet { color: #6b7280; border-color: #e5e7eb; }
.pset-act-quiet:hover { background: #f3f4f6; border-color: #d1d5db; }

/* The pending state while an editor token is being minted. The control keeps its
   exact size, because a button that shrinks to the width of the word "Opening"
   moves everything beside it in the moment a person is looking at it. cursor
   stays default rather than becoming not-allowed: this is busy, not refused. */
.pset-act[disabled],
.pset-act-pending {
  opacity: .65;
  cursor: default;
}

/* A mint that failed, and the only message on this bar that does not clear
   itself. It wraps under the actions rather than beside them so a long
   administrator sentence cannot squeeze the buttons. */
.pset-flash {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 600;
  color: #15803d;
}
.pset-flash:empty { display: none; }
.pset-flash.is-error {
  flex: 1 1 100%;
  color: #b45309;
  font-weight: 600;
  line-height: 1.45;
}
.pset-red .pset-flash.is-error,
.pset-failed .pset-flash.is-error { color: #92400e; }

/* -- the four states ------------------------------------------------------- */

/* Checking. Neutral on purpose: it is not an answer yet, and painting it green
   or red for the half second before the fetch lands is a lie either way. */
.pset-checking {
  border-left-color: #d1d5db;
  background: #f9fafb;
}
.pset-checking .pset-dot {
  background: #9ca3af;
  animation: pset-pulse 1.1s ease-in-out infinite;
}
@keyframes pset-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}
/* A person who has switched motion off still needs to know it is working, and
   the word "Checking" in the title is what tells them. */
@media (prefers-reduced-motion: reduce) {
  .pset-checking .pset-dot { animation: none; }
}

/* Not set up. The blocking state, and the only one with a primary action. */
.pset-red {
  border-color: #fecaca;
  border-left-color: #b91c1c;
  background: #fef2f2;
}
.pset-red .pset-dot { background: #b91c1c; }
.pset-red .pset-title { color: #991b1b; }
.pset-red .pset-note { color: #b91c1c; }

/* Ready. */
.pset-green {
  border-color: #bbf7d0;
  border-left-color: #16a34a;
  background: #f0fdf4;
}
.pset-green .pset-dot { background: #16a34a; }
.pset-green .pset-title { color: #14532d; }
.pset-green .pset-note { color: #15803d; }

/* Failed. Amber, NOT red: red is the answer "this client has no portal", and a
   failed check is not an answer at all. Two faults, two colours, so nobody
   chases a client record over a 500. */
.pset-failed {
  border-color: #fde68a;
  border-left-color: #b45309;
  background: #fffbeb;
}
.pset-failed .pset-dot { background: #b45309; }
.pset-failed .pset-title { color: #92400e; }
.pset-failed .pset-note { color: #b45309; }

/* No token, and no client. Neutral, because there is nothing here anyone on
   this page can act on. */
.pset-none {
  border-left-color: #d1d5db;
  background: #f9fafb;
}
.pset-none .pset-dot { background: #9ca3af; }

/* -- phone, 760px ---------------------------------------------------------
   The same breakpoint dd-mobile.css, dd-focus-points-card.css and dd-move-mode.js
   use. The bar stops being a row: the text takes the full width and every action
   becomes a full width 44px target, because two 12px buttons side by side on a
   390px screen are two buttons nobody can hit reliably. */
@media (max-width: 760px) {
  .pset-bar {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 12px 14px;
    /* nowrap is load bearing, it is not tidying. This is a COLUMN here, and a
       wrapping column breaks its overflow into a SECOND COLUMN beside the first
       rather than onto a new line. Caught on the live page at 390px: the error
       sentence rendered as a tall column off the right edge of the bar with the
       button stranded under a block of empty space. The desktop row above keeps
       wrap, where it means what it looks like it means. */
    flex-wrap: nowrap;
  }
  .pset-main { flex: 1 1 auto; }
  .pset-title { font-size: 14px; }
  .pset-note { font-size: 13px; }
  .pset-actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 8px;
  }
  .pset-actions .dd-btn {
    width: 100%;
    justify-content: center;
    min-height: 44px;
    font-size: 14px;
  }
  .pset-flash { font-size: 13px; }
  /* The row layout gives the error a 100% basis so it wraps onto its own line.
     Stacked, every child is already full width and a 100% BASIS in a column is a
     100% HEIGHT request. */
  .pset-flash.is-error { flex: 0 0 auto; }
}

/* -- hover free -----------------------------------------------------------
   .dd-btn and .dd-btn-primary already have their :active answers in
   dd-mobile-hover-free.css. .pset-act-quiet is this file's own hover, so it
   answers it here. */
@media (hover: none) {
  .pset-act-quiet:hover { background: #fff; border-color: #e5e7eb; }
  .pset-act:active { background: #e5e7eb; border-color: #9ca3af; }
  .pset-act.dd-btn-primary:active { background: #1d4ed8; border-color: #1d4ed8; }
  .pset-act-quiet:active { background: #f3f4f6; border-color: #d1d5db; }
}

/* -- dark theme ------------------------------------------------------------ */

html[data-theme="dark"] .pset-title { color: #e2e8f0; }
html[data-theme="dark"] .pset-note { color: #94a3b8; }
html[data-theme="dark"] .pset-flash { color: #4ade80; }
html[data-theme="dark"] .pset-flash.is-error,
html[data-theme="dark"] .pset-red .pset-flash.is-error,
html[data-theme="dark"] .pset-failed .pset-flash.is-error { color: #fbbf24; }
html[data-theme="dark"] .pset-act { color: #e2e8f0; }
html[data-theme="dark"] .pset-act.dd-btn-primary { color: #fff; }
html[data-theme="dark"] .pset-act-quiet { color: #94a3b8; border-color: #334155; }
html[data-theme="dark"] .pset-act-quiet:hover { background: #334155; border-color: #475569; }

html[data-theme="dark"] .pset-checking,
html[data-theme="dark"] .pset-none {
  background: #1e293b;
  border-color: #334155;
  border-left-color: #475569;
}
html[data-theme="dark"] .pset-red {
  background: #3f1d1d;
  border-color: #7f1d1d;
  border-left-color: #f87171;
}
html[data-theme="dark"] .pset-red .pset-dot { background: #f87171; }
html[data-theme="dark"] .pset-red .pset-title { color: #fecaca; }
html[data-theme="dark"] .pset-red .pset-note { color: #f87171; }

html[data-theme="dark"] .pset-green {
  background: #14311f;
  border-color: #166534;
  border-left-color: #4ade80;
}
html[data-theme="dark"] .pset-green .pset-dot { background: #4ade80; }
html[data-theme="dark"] .pset-green .pset-title { color: #bbf7d0; }
html[data-theme="dark"] .pset-green .pset-note { color: #4ade80; }

html[data-theme="dark"] .pset-failed {
  background: #3a2c10;
  border-color: #78350f;
  border-left-color: #fbbf24;
}
html[data-theme="dark"] .pset-failed .pset-dot { background: #fbbf24; }
html[data-theme="dark"] .pset-failed .pset-title { color: #fde68a; }
html[data-theme="dark"] .pset-failed .pset-note { color: #fbbf24; }

@media (hover: none) {
  html[data-theme="dark"] .pset-act-quiet:hover { background: transparent; border-color: #334155; }
}

/* -- full width placement --------------------------------------------------
   The bar is a status line for the whole month and never a column card. When a
   layout drops it straight into .dd-cols (a two column grid) it must span both,
   the same claim .ccfp-card makes for itself in dd-focus-points-card.css. Scoped
   to .dd-cols so the bar is still free to sit in a one column context. */
.dd-cols > .pset-bar { grid-column: 1 / -1; }
