/* West Coast In-Home — shared responsive base.
 * ============================================================================
 *
 * THE FIRST SHARED STYLESHEET IN THIS CODEBASE. Everything else is inline
 * <style> in a template. Read this header before adding to it.
 *
 * Served at /static/css/wci-core.css from the app-level static folder. That
 * path is deliberate and is the only one that works: the per-blueprint static
 * dirs (/admin/assets/, /assets/) belong to ONE site each, and the apex 302s
 * /admin/... to the admin host — so a stylesheet under /admin/assets/ can
 * never be fetched by the public site or the PWA. The app-level ``static``
 * endpoint is mapped to the pseudo-site "shared" in app/__init__.py and skips
 * the host gate entirely, so this one file serves identically on
 * westcoastinhome.com, admin.westcoastinhome.com, app.westcoastinhome.com and
 * statue-of-us.com.
 *
 * ── WHAT THIS FILE MUST NOT DO ──────────────────────────────────────────────
 *
 * 1. IT DECLARES NO PALETTE TOKENS. Not one --navy, not one hex from
 *    docs/PALETTE.md. Colour still lives in each shell's own :root, which
 *    keeps the drift check in docs/PALETTE.md working unchanged and means a
 *    mistake here cannot re-skin four surfaces at once. This file owns the
 *    RESPONSIVE system; the shells keep owning colour. The two layout tokens
 *    below are not colours.
 *
 * 2. THE FIVE STANDALONE LINK-TAP PAGES MUST NEVER LINK IT — scheduling_pick,
 *    scheduling_confirmed, offer_response, offer_confirmed, offer_invalid.
 *    An applicant opens those by tapping a link in an SMS on a phone and they
 *    make ZERO external requests on purpose; a stylesheet adds a blocking
 *    round-trip to exactly the pages that can least afford one. They are
 *    already phone-first (single column, rem max-widths, 100%-width controls,
 *    >=16px inputs) and need nothing from here. docs/PALETTE.md:175-189 warned
 *    that introducing a shared stylesheet would tempt someone to point them at
 *    it. Don't.
 *
 * ── CASCADE POSITION ────────────────────────────────────────────────────────
 *
 * Linked EARLY — after Bootstrap/fonts but BEFORE each shell's inline
 * <style>. This is the base layer: shells and pages are meant to override it.
 * public_base.html's {% block extra_css %} lives inside its inline <style>,
 * so loading this first is what lets a child page win.
 *
 * wci-admin.css is the opposite: it loads LAST, because it deliberately
 * reshapes the navbar and the SPA app-shell at compact widths.
 *
 * ── BREAKPOINTS ─────────────────────────────────────────────────────────────
 *
 * Bootstrap 5's scale, because the ATS already loads Bootstrap and leans on
 * col-md-* / col-lg-* heavily. Any other scale means custom rules fighting the
 * grid at a 20px offset.
 *
 *   compact   <= 767.98px   phones + small tablets  <- the important one
 *   tablet    768 - 991.98px
 *   desktop   >= 992px      (the SPA's existing left-sidebar flip)
 *   wide      >= 1200px
 *
 * Custom properties cannot be used inside @media, so these are literal values
 * everywhere. docs/RESPONSIVE.md is the record and carries a drift-check grep.
 */

:root{
  /* Layout tokens only — no colour. See the header. */
  --wci-bottomnav-h:56px;   /* compact-width bottom bar; 0 above the breakpoint */
  --wci-tap:44px;           /* minimum touch target, per WCAG 2.5.5 / iOS HIG */
}

/* ── Overflow safety ────────────────────────────────────────────────────────
   The single most common cause of a page that scrolls sideways on a phone is
   a replaced element with an intrinsic width wider than its container. These
   three rules prevent most of it before anyone writes a media query.

   min-width:0 on flex/grid children is the other half: those default to
   min-width:auto, which refuses to shrink below their content and is why a
   long unbroken string blows out a flex row. index.html already documents
   this at its .min-width-0 helper; this generalises it. */
img, svg, video, canvas, iframe{max-width:100%}
img, video{height:auto}
.wci-min0{min-width:0}

/* Long words / URLs / email addresses in a narrow column. Opt-in, because
   applying it globally breaks table cells that are meant to stay one line. */
.wci-wrap-anywhere{overflow-wrap:anywhere; word-break:break-word}

/* ── Containers ─────────────────────────────────────────────────────────────
   Gutters step down on small screens rather than staying at a desktop 24px,
   which wastes ~13% of a 375px viewport. */
.wci-container{
  width:100%;
  max-width:1120px;
  margin-inline:auto;
  padding-inline:24px;
}
@media (max-width:767.98px){
  .wci-container{padding-inline:16px}
}

/* ── Safe-area insets ───────────────────────────────────────────────────────
   Only meaningful once installed to a home screen: in standalone mode there
   is no browser chrome, so content runs under the notch, the rounded corners
   and the home indicator. env() resolves to 0 where it does not apply, so
   every one of these is a no-op in a desktop browser.

   Requires <meta name="viewport" content="... viewport-fit=cover"> — without
   it the insets are always 0 and these silently do nothing. */
.wci-safe-x{
  padding-left:env(safe-area-inset-left);
  padding-right:env(safe-area-inset-right);
}
.wci-safe-top{padding-top:env(safe-area-inset-top)}
.wci-safe-bottom{padding-bottom:env(safe-area-inset-bottom)}

/* ── Touch targets ──────────────────────────────────────────────────────────
   A 24px icon button is fine with a mouse and a miss with a thumb. Applied
   only at compact widths so desktop density is untouched. */
@media (max-width:767.98px){
  .wci-tap,
  .wci-taps > a,
  .wci-taps > button{
    min-width:var(--wci-tap);
    min-height:var(--wci-tap);
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }
}

/* ── Form controls: stop iOS zoom-on-focus ──────────────────────────────────
   Mobile Safari zooms the viewport when a focused field's font-size is below
   16px, and does not zoom back out. It is the single most-reported "the form
   is broken on my phone" bug, and it is invisible in DevTools emulation.

   Bootstrap's .form-control is 1rem (fine) but .form-control-sm is .875rem
   (14px) and the ATS uses the -sm variants throughout. This forces 16px on
   phones only; desktop density is untouched.

   Checkbox/radio/range are excluded — font-size does not size them, and
   Bootstrap sizes .form-check-input in em, so touching it would scale them. */
@media (max-width:767.98px){
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  select,
  textarea{
    font-size:16px;
  }
}

/* ── Horizontal scrollers ───────────────────────────────────────────────────
   For strips that are MEANT to scroll sideways (tab rails, chip rows).
   overscroll-behavior-x:contain stops a horizontal fling from turning into a
   browser back-navigation on iOS. */
.wci-hscroll{
  display:flex;
  flex-wrap:nowrap;
  overflow-x:auto;
  overflow-y:hidden;
  overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;
}
.wci-hscroll > *{flex:0 0 auto}

/* ── Visibility helpers ─────────────────────────────────────────────────────
   Prefer restyling over duplicating markup — two copies of a control drift.
   Use these only when one layout genuinely cannot serve both. */
@media (max-width:767.98px){ .wci-regular-only{display:none !important} }
@media (min-width:768px){    .wci-compact-only{display:none !important} }

/* ── Tables as cards ────────────────────────────────────────────────────────
   The core pattern for this codebase. An 8-column table inside a horizontally
   scrolling wrapper is technically not broken, but on a 375px screen it is
   unusable — you cannot see a row and its header at the same time.

   Opt in per table:
       <table class="table wci-cards-md">
         <thead><tr><th>Name</th><th>Job</th>...</tr></thead>
         <tbody><tr>
           <td data-label="Name">Ada</td>
           <td data-label="Job">Nanny</td>
           <td data-label="">   <-- empty label: actions, avatars, checkboxes
         </tr></tbody>
       </table>

   Below 768px each <tr> becomes a card and each <td> a label/value row, with
   the label taken from data-label. Above 768px the rules do not exist and the
   table is an ordinary table.

   THE data-label ATTRIBUTES ARE REQUIRED. Without them the cells render with
   no label and the card is unreadable — there is no automatic fallback,
   because CSS cannot read the matching <th>.

   Three details that are easy to get wrong and are handled here:
     - thead is clipped, not display:none — display:none removes it from the
       accessibility tree, so a screen reader loses the column names that the
       data-labels are duplicating.
     - td[colspan] (the "No results found" empty-state row every one of these
       tables has) is NOT turned into a label/value row. It spans the card.
     - .table-responsive must go overflow-x:visible, or the cards sit inside a
       scroller that no longer has anything to scroll and clips shadows.

   The :has() below is load-bearing for a PHASED rollout, not a flourish: it
   switches scrolling off only for wrappers that actually contain a converted
   table, so a .table-responsive still holding a plain wide table keeps
   scrolling instead of blowing out the page. Blanket-targeting
   .table-responsive would regress every table not yet converted. On a browser
   without :has() the cards simply render inside a harmless scroller. */
@media (max-width:767.98px){
  .table-responsive:has(> .wci-cards-md){overflow-x:visible}

  /* The table, tbody and rows ALL have to leave table layout together.
     Making only the rows display:block leaves the <table> as display:table,
     which shrink-wraps to its content: the rows then collapse to about one
     character wide and the card renders as a vertical column of letters.
     Every computed-style check still passes in that state — thead is
     clipped, cells are flex, labels resolve — so it looks correct to
     assertions and is unusable on screen. Do not drop these three rules. */
  .wci-cards-md{display:block; width:100%; border-collapse:separate; border-spacing:0}
  .wci-cards-md > tbody{display:block; width:100%}

  /* Percentage <col> widths are meaningless outside table layout, and an
     unhidden colgroup can still contribute a box in some engines. */
  .wci-cards-md > colgroup{display:none}

  .wci-cards-md > thead{
    position:absolute;
    width:1px; height:1px;
    overflow:hidden;
    clip-path:inset(50%);
    white-space:nowrap;
  }

  .wci-cards-md > tbody > tr{
    display:block;
    margin-bottom:.6rem;
    padding:.55rem .7rem;
    border:1px solid rgba(0,0,0,.08);
    border-radius:12px;
    background:#fff;
  }
  .wci-cards-md > tbody > tr:last-child{margin-bottom:0}

  /* The cell is a BLOCK with a left gutter, and the label is absolutely
     positioned into that gutter.

     Not flex, and that matters. A flex cell makes every child its own flex
     item, so a cell like
         <td>{{ phone }}<div class="ats-meta">{{ email }}</div></td>
     puts the phone and the email side by side in two squeezed columns
     instead of stacking them. Cells in these tables routinely hold a value
     plus one or two meta lines, so that is the common case, not the edge
     one. Block flow stacks any number of children correctly, whatever
     they are. */
  .wci-cards-md > tbody > tr > td{
    display:block;
    position:relative;
    width:auto !important;
    min-height:1.6rem;
    padding:.3rem 0 .3rem 38%;
    border:0;
    text-align:left !important;
    white-space:normal;
  }

  .wci-cards-md > tbody > tr > td::before{
    content:attr(data-label);
    position:absolute;
    left:0;
    top:.3rem;
    width:35%;
    font-size:.75rem;
    font-weight:600;
    text-transform:uppercase;
    letter-spacing:.04em;
    color:#8a94a3;         /* --faint; literal because this file declares no
                              palette tokens, see the header */
    line-height:1.6;
  }

  /* An empty data-label means "no label" — the name headline, actions,
     avatars, checkboxes. The cell takes the full card width. */
  .wci-cards-md > tbody > tr > td[data-label=""]{padding-left:0}
  .wci-cards-md > tbody > tr > td[data-label=""]::before{content:none}

  /* Empty-state rows span the card rather than becoming a label/value pair. */
  .wci-cards-md > tbody > tr > td[colspan]{
    display:block;
    padding-left:0;
    text-align:center !important;
    color:#6c757d;
  }
  .wci-cards-md > tbody > tr > td[colspan]::before{content:none}

  /* A card whose every cell is empty-state should not look like a card. */
  .wci-cards-md > tbody > tr:has(> td[colspan]:only-child){
    border:0; background:transparent; padding:0;
  }
}

/* ── Shift status ───────────────────────────────────────────────────────────
   One vocabulary for "what state is this shift in", used by the console's
   schedule and booking lists and by the caregiver app's agenda. Shared
   because a caregiver and an admin looking at the same shift should not have
   to learn two colour schemes.

   Declares NO palette tokens — it only *uses* the ones every shell sets on
   :root, which is what keeps PALETTE.md's drift check honest (it greps
   templates for declarations, so colour must not start being declared here).
   Custom properties resolve at computed-value time, so using them from a
   stylesheet that loads before the shell is fine.

   CONFIRMED IS PLAIN on purpose: it is the normal case and by far the most
   common, so marking it would make the whole list shout. Everything that is
   NOT simply fine gets a tint and a left edge.

   Cancelled is stripes rather than another tint: it is categorically
   different — not a state of the work but the absence of it — and stripes
   read as "void" at a glance without needing a colour nobody has learned. */
/* ``.wci-st`` OWNS THE BACKGROUND, including the plain one. That is not
   tidiness — it is the whole reason these rules reach the screen.

   Every carrier (.sc-row, .bd-row, .shift) is styled in a <style> block in
   its own template, and those blocks render AFTER this file is linked. A
   carrier declaring `background:#fff` therefore beats `.wci-st-open` on the
   later-wins rule: same specificity, one class each. The classes were on the
   markup and the rules were in this file and the rows were still plain
   white, which is a hard thing to see by reading either file alone.

   So: the carrier sets layout, this sets colour, and the plain default lives
   here where the variants can override it. scripts/audit_status_css.py fails
   the build if a carrier starts declaring a background again. */
.wci-st{
  background:#fff;
  border-left:4px solid transparent;
}

.wci-st-open{
  background:#fff8e8;
  border-left-color:var(--tangerine,#f9b800);
}
.wci-st-offered,
.wci-st-tentative{
  background:rgba(42,95,126,.07);
  border-left-color:var(--navy,#2A5F7E);
  border-left-style:dashed;
}
.wci-st-completed{
  background:var(--well,#fafbfc);
  border-left-color:#cfd6de;
}
.wci-st-no_show{
  background:#fff0f1;
  border-left-color:#d98b92;
}
.wci-st-cancelled{
  border-left-color:#cfd6de;
  color:var(--muted,#6c757d);
  /* 6px of stripe over whatever background the row already has. Low
     contrast on purpose — this must read as "struck through", not as a
     warning competing with the open rows above it. */
  background-image:repeating-linear-gradient(
    -45deg,
    rgba(0,0,0,.055) 0 6px,
    transparent 6px 12px
  );
}
.wci-st-cancelled .wci-st-strike{ text-decoration:line-through; }

/* ── Toggle chips ───────────────────────────────────────────────────────────
   A checkbox that looks like something you would tap. Still a real
   <input type=checkbox> underneath — keyboard, screen readers and form
   submission all work exactly as before; only the paint changes.

   Used anywhere a list of options is picked from: age bands, capabilities,
   restrictions, the children on a shift, what is in a home. A column of bare
   checkboxes is both harder to hit on a phone and harder to scan, because
   the checked ones do not stand out until you look at each box. */
.wci-toggles{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
}
.wci-toggle{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:8px;
  min-height:44px;               /* WCAG 2.5.5 — see docs/RESPONSIVE.md */
  padding:8px 15px 8px 13px;
  border:1px solid var(--hairline,#e5e7eb);
  border-radius:999px;
  background:#fff;
  color:var(--slate,#4a5662);
  font-size:.9rem;
  font-weight:600;
  line-height:1.2;
  cursor:pointer;
  user-select:none;
  -webkit-tap-highlight-color:transparent;
  transition:background-color .12s, border-color .12s, color .12s;
}
.wci-toggle:hover{ border-color:var(--navy,#2A5F7E); color:var(--navy,#2A5F7E); }

/* The box is visually replaced by the tick, but stays in the layout and in
   the accessibility tree — it is the control, not decoration. */
.wci-toggle > input[type=checkbox]{
  position:absolute;
  opacity:0;
  width:1px;
  height:1px;
  margin:0;
  pointer-events:none;
}
.wci-toggle .wci-toggle-mark{
  flex:0 0 auto;
  width:18px;
  height:18px;
  border-radius:50%;
  border:1.5px solid #c3cad3;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  transition:background-color .12s, border-color .12s;
}
.wci-toggle .wci-toggle-mark::after{
  content:"";
  width:9px;
  height:5px;
  border-left:2px solid #fff;
  border-bottom:2px solid #fff;
  transform:rotate(-45deg) translateY(-1px);
  opacity:0;
  transition:opacity .12s;
}
.wci-toggle > input:checked ~ .wci-toggle-mark{
  background:var(--navy,#2A5F7E);
  border-color:var(--navy,#2A5F7E);
}
.wci-toggle > input:checked ~ .wci-toggle-mark::after{ opacity:1; }
.wci-toggle:has(> input:checked){
  background:rgba(42,95,126,.09);
  border-color:var(--navy,#2A5F7E);
  color:var(--navy,#2A5F7E);
}
/* Focus must be visible on the chip, since the real input is invisible. */
.wci-toggle:has(> input:focus-visible){
  outline:2px solid rgba(42,95,126,.45);
  outline-offset:2px;
}
.wci-toggle > input:disabled ~ .wci-toggle-mark{ opacity:.4; }
.wci-toggle:has(> input:disabled){ opacity:.55; cursor:default; }

.wci-toggle .wci-toggle-note{
  font-weight:400;
  font-size:.8rem;
  color:var(--faint,#8a94a3);
}

/* ── Overlays: stop the page scrolling underneath ───────────────────────────
   Two halves, and both are needed. overscroll-behavior keeps a flick that
   reaches the end of the panel from chaining to the document; the body lock
   stops iOS scrolling the page when the touch starts outside the panel.
   Without the pair, a modal appears frozen while the page slides behind it. */
.wci-scroll-contain{ overscroll-behavior:contain; -webkit-overflow-scrolling:touch; }

body.wci-locked{
  overflow:hidden !important;
  /* position:fixed would jump the page to the top; this holds the scroll
     position and simply stops it moving. */
  touch-action:none;
}

/* ── Unsaved-changes bar ────────────────────────────────────────────────────
   A Save button at the foot of a long form is easy to scroll past and
   forget. This appears only once something has actually changed, sits above
   any bottom navigation, and says which section it will save.

   ``--wci-bottom-gap`` is how anything fixed to the bottom clears the
   navigation bar. Shells that have one set it; everywhere else it is 0. */
:root{ --wci-bottom-gap:0px; }

.wci-unsaved{
  position:fixed;
  left:0; right:0;
  bottom:calc(var(--wci-bottom-gap) + env(safe-area-inset-bottom));
  z-index:1040;                  /* above bottom nav (1035), below modals */
  display:none;
  align-items:center;
  gap:12px;
  padding:11px calc(16px + env(safe-area-inset-left))
          11px calc(16px + env(safe-area-inset-right));
  background:var(--navy,#2A5F7E);
  color:#fff;
  box-shadow:0 -3px 16px rgba(0,0,0,.18);
}
.wci-unsaved.is-on{ display:flex; }
.wci-unsaved .wci-unsaved-text{
  flex:1;
  min-width:0;
  font-size:.9rem;
  line-height:1.3;
  overflow:hidden;
  text-overflow:ellipsis;
}
.wci-unsaved .wci-unsaved-text b{ display:block; font-weight:700; }
.wci-unsaved button{
  flex:0 0 auto;
  min-height:44px;
  padding:0 20px;
  border:0;
  border-radius:10px;
  background:#fff;
  color:var(--navy,#2A5F7E);
  font-family:inherit;
  font-size:.95rem;
  font-weight:700;
  cursor:pointer;
}
.wci-unsaved button.ghost{
  background:transparent;
  color:#fff;
  border:1px solid rgba(255,255,255,.5);
  padding:0 14px;
}

/* ── Motion ─────────────────────────────────────────────────────────────────
   Respect the OS setting. Not decorative: motion sensitivity is a real
   accessibility need and this costs nothing. */
@media (prefers-reduced-motion:reduce){
  *,
  *::before,
  *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
}
