/* ===========================================================================
   Two surfaces, one set of variables. Chosen 30 July 2026 from
   /app/theme-preview.html.

   OFFICE ("Fresh")  -- green accent, light page, generous spacing. What a
                        manager looks at for hours, so it stays calm.
   CREW   ("High contrast") -- blue accent, heavier weights, stronger borders,
                        tighter corners. Used one-handed in a driveway at noon,
                        where contrast beats elegance.

   BOTH share the navy #17293f top bar. That was originally crew-only, but
   seeing it on a desktop My Jobs next to a white-barred dashboard made the two
   look like different products, so the bar is now common chrome and the
   surfaces differ only below it.

   The crew surface is applied by api.js setting data-surface="crew" on <html>
   for the crew-facing pages -- NOT by screen width. A manager checking the
   schedule on a phone should still get the office styling; the difference is
   which job the page is doing, not how wide the screen is.

   Header contrast (white on #17293f) is 14.7:1, far above the 4.5:1 needed.
   =========================================================================== */

:root {
  /* Type scale, 1.2 ratio. Previously there was none, which is what made the
     app read flat regardless of colour. */
  --t-xs: 0.75rem;
  --t-sm: 0.875rem;
  --t-base: 1rem;
  --t-lg: 1.2rem;
  --t-xl: 1.5rem;
  --t-2xl: 1.85rem;

  /* Spacing rhythm -- every gap is a multiple, so nothing is arbitrary. */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;

  /* --- OFFICE: Fresh ----------------------------------------------------
     Every colour used for TEXT is measured against the page background
     (#f4f8f6), not against white -- most office text sits on the tinted page,
     not on a card, and the tint costs about 0.3:1. The first cut of this
     palette was picked to look pleasant and measured 4.4:1 on muted text and
     4.4:1 on the accent, both of which read washed out on a real monitor.
     Numbers below are text-on-page-background. */
  --bg: #f4f8f6;
  --card-bg: #ffffff;
  --text: #17322a;         /* 13.1:1 */
  --muted: #3f5c53;        /* 6.8:1  -- was #5c7a70 at 4.4:1 */
  --border: #cddcd5;       /* decorative only: card edges, table row rules */
  --field-border: #6d8579; /* 4.0:1 -- input/select outlines must be findable */
  --accent: #0b6e4b;       /* 5.9:1 as text, 6.3:1 white-on-accent for buttons */
  --accent-hover: #085538;
  --danger: #b0261a;
  --ok: #0b6e4b;
  --warn: #8a5a00;         /* 5.5:1  -- was #c47f17 at 3.3:1 */
  --radius: 10px;

  /* The navy bar is shared with the crew surface -- one piece of chrome across
     the whole product, phone and desktop alike, so the app looks like one app.
     The surfaces still differ below the bar: green accent and lighter weights
     here, blue accent and heavier weights on crew. */
  --header-bg: #17293f;
  --header-text: #ffffff;
  --header-border: #17293f;
  --shadow: 0 2px 6px rgba(23, 50, 42, 0.06);
  --heading-weight: 650;

  /* Hover/selection tints. These used to be hardcoded pale blues left over from
     the old theme, which fought the green accent everywhere they appeared.
     Now they follow the surface. */
  --hover-bg: #e7f2ec;
  --pill-bg: #e7f2ec;

  /* Light on navy. Kept as a variable rather than a per-surface override on
     the selector so the contrast audit in tools/check_contrast.py can see it. */
  --nav-link: #dfe6f1;
  --nav-link-hover: #ffffff;
}

/* --- CREW: high contrast, navy bar -------------------------------------- */
:root[data-surface="crew"] {
  --bg: #eef0f3;
  --card-bg: #ffffff;
  --text: #0b0d10;
  --muted: #4a5361;
  --border: #c9cfd8;
  --field-border: #7c8494; /* 3.8:1 */
  --accent: #0b5cd5;
  --accent-hover: #08409a;
  --danger: #c00f0f;
  --ok: #0a7a33;
  --warn: #a35c00;
  --radius: 6px;

  --header-bg: #17293f;
  --header-text: #ffffff;
  --header-border: #17293f;
  --shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
  --heading-weight: 800;

  --hover-bg: #e4ecf8;
  --pill-bg: #e4ecf8;

  /* Light on navy, not --text (near-black), which would be invisible up there. */
  --nav-link: #dfe6f1;
  --nav-link-hover: #ffffff;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}

/* Headings pick up the surface's weight, which is most of what separates the
   two looks -- the crew screen needs to be scannable at arm's length.

   h1 uses --t-xl rather than --t-2xl: 1.85rem is a jarring jump from the
   1.4rem these pages have always used, and --t-2xl is held back for the big
   single figures on the dashboard. 1.5rem / 1.2rem / 1rem still gives a real
   hierarchy without relaying out 25 existing pages. */
h1 {
  font-size: var(--t-xl);
  font-weight: var(--heading-weight);
  letter-spacing: -0.01em;
  margin: 0 0 0.75rem;
}
h2 {
  font-size: var(--t-lg);
  font-weight: var(--heading-weight);
  margin: 0 0 0.75rem;
}

header.topbar {
  background: var(--header-bg);
  color: var(--header-text);
  border-bottom: 1px solid var(--header-border);
  padding: 0.75rem 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
}

header.topbar .brand {
  font-weight: 600;
  font-size: 1.1rem;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}

/* Nav links are primary navigation, not secondary text, so they take a full
   nav colour rather than --muted. At 0.9rem, muted grey on the office surface
   was the single worst offender -- 4.4:1 and visibly washed out. */
header.topbar nav a {
  margin-left: 1rem;
  color: var(--nav-link);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
}

header.topbar nav a:hover,
header.topbar nav a:focus { color: var(--nav-link-hover); }

/* Who is signed in. Replaces the old ⚙, which identified nobody -- on a shared
   phone, or a desktop somebody else used last, there was no way to tell whose
   session you were in without opening a page.

   Both surfaces run the same navy bar, so one set of colours covers both. */
.whoami {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.avatar-img,
.avatar-initials {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  flex: 0 0 auto;
  /* 3:1 against the navy -- a non-text boundary still has a contrast minimum,
     and without it the circle disappears into the bar. */
  border: 1px solid rgba(255, 255, 255, 0.55);
}
.avatar-img {
  object-fit: cover;   /* never squash a portrait into the circle */
  display: block;
  background: rgba(255, 255, 255, 0.12);
}
.avatar-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.16);
  color: var(--nav-link-hover);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
}
.whoami-name {
  font-weight: 600;
  max-width: 8rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* (The crew-specific dropdown-link override that used to live here is gone --
   the scoped rule further down now gets this right on BOTH surfaces, and two
   rules setting the same property was how the office surface came to be
   missed in the first place.) */

.nav-dropdown {
  position: relative;
  display: inline-block;
}

.nav-dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 1rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  min-width: 140px;
  z-index: 20;
  padding: 0.25rem 0;
}

.nav-dropdown:hover .nav-dropdown-menu,
.nav-dropdown.open .nav-dropdown-menu {
  display: block;
}

/* The ⚙ menu is always the last thing in the bar, so a left-anchored panel
   opens straight off the right edge of the screen. Anchor it to the right.
   Worse since the panel widened to 200px for the longer module names. */
.nav-dropdown[data-menu="settings"] .nav-dropdown-menu {
  left: auto;
  right: 0;
}

/* Set by api.js on any OTHER dropdown that would overflow -- which one that is
   depends on the window width and the length of the business name, so it
   cannot be known from CSS alone. */
.nav-dropdown-menu.flip-right {
  left: auto;
  right: 0;
}

/* ⚠️ The `header.topbar nav` prefix is LOAD-BEARING, not decorative -- do not
   "simplify" it away.

   `header.topbar nav a` sets the light-on-navy colour for links in the bar, and
   at specificity (0,1,3) it outranks a bare `.nav-dropdown-menu a` (0,1,1).
   Dropdown panels are white, so without this prefix every menu rendered
   #dfe6f1 text on #ffffff -- about 1.15:1, i.e. invisible. Scoping it here
   lifts this rule to (0,2,3) so the panel wins for its own children.

   The static contrast check in tools/check_contrast.py cannot catch this: the
   variables are individually fine, and only the cascade makes them meet. */
header.topbar nav .nav-dropdown-menu a {
  display: block;
  margin-left: 0 !important;
  padding: 0.5rem 0.8rem;
  color: var(--text);
  font-size: 0.85rem;
}

header.topbar nav .nav-dropdown-menu a:hover {
  background: var(--hover-bg);
  color: var(--accent);
}

/* A module this business has not switched on. Greyed rather than hidden, and
   only ever the ONE next step up -- anything beyond that is not rendered at
   all, because a menu full of padlocks reads as a paywall. Clicking opens a
   short panel explaining what the module does. */
/* Scoped the same way as the rule above, and for the same reason: the base
   dropdown-link rule now sits at (0,2,3), so an unscoped `.nav-dropdown-menu
   a.locked` at (0,2,1) would lose to it and locked items would stop looking
   locked. The drawer's own copy needs no prefix -- it is not inside the bar. */
header.topbar nav .nav-dropdown-menu a.locked,
.side-drawer a.locked {
  color: var(--muted);
  font-style: italic;
}
header.topbar nav .nav-dropdown-menu a.locked:hover,
.side-drawer a.locked:hover {
  background: var(--hover-bg);
  color: var(--text);
}

/* The upsell panel, and any other modal raised from api.js. Several pages
   already define their own .modal-overlay/.modal-box locally; these are the
   shared versions so a page does not have to. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 1rem;
}
.modal-box {
  background: var(--card-bg);
  border-radius: var(--radius);
  width: min(600px, 96vw);
  max-height: 88vh;
  overflow-y: auto;
  padding: 1rem;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25);
}

main {
  max-width: 900px;
  margin: 0 auto;
  padding: 1rem;
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  margin-bottom: 1rem;
}

label {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
  margin-top: 0.6rem;
  margin-bottom: 0.2rem;
}

/* Fields use --field-border, not --border. A card edge can be a whisper; the
   outline of something you are meant to click into cannot, and the old shared
   value sat at 1.4:1 against white. */
input, select, textarea {
  width: 100%;
  padding: 0.55rem;
  border: 1px solid var(--field-border);
  border-radius: 6px;
  font-size: 1rem;
  background: #fff;
  color: var(--text);
}

input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

/* Button hierarchy, three tiers:
   - Primary (default): filled accent -- the one main commit per view.
   - Secondary (.secondary): outline/ghost -- supporting actions.
   - Tertiary (.btn-text): text link -- low-stakes toggles (Edit, expand). */
button, .btn {
  display: inline-block;
  margin-top: 0.9rem;
  padding: 0.5rem 0.95rem;
  background: var(--accent);
  color: #fff;
  border: 1px solid var(--accent);
  border-radius: 6px;
  font-size: 0.9rem;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
}
button:hover, .btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

button.secondary, .btn.secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--field-border);
}
button.secondary:hover, .btn.secondary:hover {
  background: var(--hover-bg);
  border-color: var(--accent);
  color: var(--accent);
}

button.btn-text, .btn.btn-text {
  background: transparent;
  color: var(--accent);
  border: none;
  padding: 0.2rem 0.35rem;
  font-weight: 500;
}
button.btn-text:hover, .btn.btn-text:hover {
  background: transparent;
  color: var(--accent-hover);
  text-decoration: underline;
}

/* Wide tables scroll INSIDE their own box, never by dragging the whole page
   sideways. Applied automatically by api.js to every table that isn't already
   inside a scroll container, so a new page gets it without anyone remembering.
   The owner is reading these on a phone between jobs -- see commitment #1 in
   docs/product_narrative.md. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Stops a sideways flick at the end of the table from dragging the page. */
  overscroll-behavior-x: contain;
}

table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }

/* Columns that earn their place on a 1200px screen but not on a 375px one.
   Marked per page, because which ones matter depends on what the page is for.
   Hiding is deliberate rather than shrinking: four readable columns beat eight
   unreadable ones, and the full set is one rotation away. */
/* The counterpart to .hide-sm: detail folded under a cell that stays, so a
   hidden column's information is moved rather than lost. */
.show-sm { display: none; }

@media (max-width: 640px) {
  .hide-sm { display: none !important; }
  .show-sm { display: block; }
  table { font-size: 0.85rem; }
  th, td { padding: 0.4rem 0.35rem; }
  /* A table with few enough columns to fit should not scroll at all. */
  .table-scroll table { min-width: 0; }
}
th, td { text-align: left; padding: 0.5rem; border-bottom: 1px solid var(--border); }
tr.clickable { cursor: pointer; }
tr.clickable:hover { background: var(--hover-bg); }

.muted { color: var(--muted); font-size: 0.85rem; }
.error { color: var(--danger); font-size: 0.9rem; margin-top: 0.5rem; }
.pill {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--pill-bg);
  color: var(--accent);
  font-size: 0.75rem;
  text-transform: capitalize;
}

@media (max-width: 600px) {
  main { padding: 0.6rem; }
  header.topbar nav a { margin-left: 0.6rem; }
}

/* Eight module menus fit a desktop bar and do not fit a phone. Below the
   docking breakpoint the bar keeps only what a person standing in a driveway
   needs -- Today, the language picker and ⚙ -- and everything else moves into
   the ☰ drawer, which is built from the same definition. Without this the bar
   wrapped to three lines and pushed the page content down the screen. */
@media (max-width: 900px) {
  header.topbar nav .nav-dropdown:not([data-menu="settings"]) {
    display: none;
  }
}

/* Some module names are genuinely long ("Accounts & balance sheet"), and at
   140px they wrapped mid-phrase. Capped against the viewport so the panel can
   never be wider than the screen it has to fit on. */
.nav-dropdown-menu {
  min-width: 200px;
  max-width: calc(100vw - 1rem);
}
@media (max-width: 420px) {
  .nav-dropdown-menu { min-width: 170px; }
}

/* EN/ES picker in the top bar. Deliberately narrow -- it sits in an already
   crowded nav, so it shows the language code rather than a full word. */
/* The Ask box. Sits in the navy bar between the company name and the menu, so
   it borrows the bar's own colours rather than importing a white field into it.

   It is a direct child of header.topbar, NOT of <nav>. Inside the nav its
   width counted against the menu's, the menu stopped fitting on one line, and
   the header's flex-wrap pushed it onto a second row -- which lifted the
   drawer over the company name.

   flex: 1 1 auto with a min-width of 0 means it absorbs whatever space is
   spare and SHRINKS when there isn't any, instead of forcing that wrap. */
.ask-box {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 300px;
  margin: 0 1rem;
}

.ask-box #ask-input {
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0.2rem 0.5rem;
  font-size: 0.82rem;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

/* The visible way to fire it. Without this the field looked inert -- there was
   nothing to say pressing Enter would do anything. */
.ask-box .ask-go-btn {
  flex: none;
  margin: 0;
  padding: 0.2rem 0.5rem;
  font-size: 0.9rem;
  line-height: 1.1;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
}
.ask-box .ask-go-btn:hover { background: rgba(255, 255, 255, 0.24); }
.ask-box .ask-go-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ask-box #ask-input::placeholder { color: rgba(255, 255, 255, 0.65); }
.ask-box #ask-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  background: rgba(255, 255, 255, 0.16);
}

/* The answer hangs below the bar. Anchored to the right so a long sentence
   grows leftwards into the bar rather than off the edge of the screen. */
.ask-answer {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 60;
  min-width: 280px;
  max-width: min(420px, 90vw);
  padding: 0.6rem 0.75rem;
  background: var(--card, #fff);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  text-align: left;
}
.ask-answer .ask-text { margin: 0; font-size: 0.9rem; }
.ask-answer .ask-source {
  margin-top: 0.35rem;
  font-size: 0.74rem;
  color: var(--muted);
}

/* Hidden below 1280px, and the number is measured rather than guessed.
   Header height at each width, with the box and without it:

       1280px   53 / 53     fits either way
       1200px   87 / 53     the box is what wraps it
       1100px   87 / 53     the box is what wraps it
       1000px   87 / 87     wraps regardless -- eight module menus

   A wrapped bar is not a cosmetic problem: the second row lifts the drawer
   over the company name, which is what was reported. So the box gives way
   rather than the menu, and below 1280 the pages remain the way in.

   The band this costs is real -- a 1366-wide laptop loses the box. Winning it
   back means fewer top-level menus, which is a product decision, not a CSS
   one. */
@media (max-width: 1279px) {
  .ask-box { display: none; }
}

.lang-picker {
  width: auto;
  /* Matches the 1rem gap between nav links. It used to be 0, which butted the
     picker straight against the last menu item -- invisible in English, but
     Spanish labels are longer ("Análisis", "Materiales") and the last one ran
     into the select. */
  margin: 0 0 0 1rem;
  padding: 0.15rem 0.3rem;
  font-size: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

/* The OPEN dropdown is drawn by the operating system, not inside the navy bar,
   so it does not inherit the bar's dark background -- only its white text.
   White on the OS's white list is invisible, which is exactly what happened.
   `color: inherit` on a select styles the closed control; the options need
   their own colours.
   Set explicitly rather than left to inherit, because "inherit" here means two
   different things depending on whether the list is open. */
.lang-picker option {
  color: var(--text);
  background: #fff;
}

/* Left slide-in "Management" drawer, opened by the ☰ toggle. Added for
   management users only; the top nav is left exactly as-is. */
/* Sits inside the top bar, so it follows the HEADER's text colour, not the
   page's. With var(--text) it was near-black on the crew surface's navy bar. */
.side-toggle {
  background: none;
  border: none;
  color: var(--header-text);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  margin: 0;
  padding: 0.1rem 0.3rem;
}
.side-toggle:hover { background: none; color: var(--nav-link-hover); }

/* Set by api.js only while it restores the remembered drawer state on page
   load, so arriving on a page does not replay the open animation. Removed a
   couple of frames later, which leaves the toggle click animating normally. */
body.side-instant .side-drawer,
body.side-instant .side-overlay,
body.side-instant main {
  transition: none !important;
}

/* Someone who has asked their OS not to animate things should never see the
   drawer slide, toggle click included. */
@media (prefers-reduced-motion: reduce) {
  .side-drawer,
  .side-overlay,
  main {
    transition: none !important;
  }
}

.side-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  z-index: 40;
}
.side-overlay.open { opacity: 1; pointer-events: auto; }

.side-drawer {
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  /* 100% of a fixed element is the LAYOUT viewport, which on a phone is taller
     than what you can actually see while the browser's own chrome is showing.
     The last few links then sit underneath it and the drawer appears to stop
     scrolling short. dvh tracks the visible area instead; the 100% above stays
     as the fallback for browsers without it. */
  height: 100dvh;
  width: 260px;
  max-width: 80vw;
  background: var(--card-bg);
  border-right: 1px solid var(--border);
  box-shadow: 2px 0 12px rgba(0, 0, 0, 0.12);
  transform: translateX(-100%);
  transition: transform 0.25s ease;
  z-index: 50;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Keeps a flick at the end of the list from scrolling the page behind it. */
  overscroll-behavior: contain;
  /* Clear of the home indicator, plus enough room that the last link is never
     flush against the bottom edge -- eight module groups make this list long
     enough to actually reach the end of. */
  padding-bottom: calc(2rem + env(safe-area-inset-bottom, 0px));
}
.side-drawer.open { transform: translateX(0); }

.side-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}
.side-drawer-header .side-close {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  margin: 0;
  padding: 0 0.2rem;
}
.side-drawer-header .side-close:hover { background: none; color: var(--text); }
/* Expandable group ("Management", "Marketing"). Clicking the parent toggles
   it; the open/closed choice is remembered for the session. */
.side-group-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  margin: 0;
  padding: 0.75rem 1rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.side-group-toggle:hover { background: var(--hover-bg); color: var(--accent); }
.side-group-toggle .caret {
  font-size: 0.7rem;
  color: var(--muted);
  transition: transform 0.2s ease;
}
.side-group.expanded .side-group-toggle .caret { transform: rotate(90deg); }

.side-group-items { display: none; }
.side-group.expanded .side-group-items { display: block; }

/* Child links sit indented under their parent. Slightly larger and heavier
   than they were -- at 0.9rem/400 the drawer read as a wall of faint grey
   even though the colour itself was fine. */
.side-drawer a {
  display: block;
  padding: 0.6rem 1rem 0.6rem 2rem;
  color: var(--text);
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 500;
  border-bottom: 1px solid var(--border);
}
.side-drawer a:hover { background: var(--hover-bg); color: var(--accent); }

/* Desktop: dock the drawer *under* the top bar and leave it open until the
   toggle is clicked again -- no dimming overlay, and the page content shifts
   right so the sidebar never covers it. --topbar-h is measured in JS, since
   the top bar wraps to different heights. */
@media (min-width: 901px) {
  .side-drawer {
    top: var(--topbar-h, 56px);
    height: calc(100% - var(--topbar-h, 56px));
    height: calc(100dvh - var(--topbar-h, 56px));
    box-shadow: none;
  }
  .side-overlay { display: none; }
  main { transition: margin-left 0.25s ease; }
  body.side-docked main { margin-left: calc(260px + 1.5rem); }
}

.day-cell.today,
.month-day.today {
  border: 2px solid var(--accent) !important;
}

.day-cell.drag-over {
  border-color: var(--accent) !important;
  background: var(--hover-bg);
}

.entry-card[draggable="true"] {
  cursor: grab;
}

.entry-card[draggable="true"]:active {
  cursor: grabbing;
}

/* ---- "What needs you today" ---------------------------------------------
   Shown twice: raised in front of the dashboard on arrival, and sitting on the
   dashboard afterwards. One set of styles for both.

   ⚠️ Severity is carried by the WORD in .att-flag first and colour second.
   Roughly one man in twelve cannot reliably separate red from green, so a
   status told only in colour is a status those users cannot read. The colours
   below are reinforcement, never the message. */
.att-headline {
  font-size: 1.05rem;
  font-weight: 600;
  margin: 0 0 0.6rem;
}
.att-list { list-style: none; margin: 0; padding: 0; }
.att-item {
  border: 1px solid var(--border);
  border-left-width: 4px;
  border-radius: var(--radius);
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.6rem;
}
.att-item-head {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.att-flag {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  white-space: nowrap;
}
.att-title { font-weight: 600; flex: 1 1 12rem; }
.att-money { font-weight: 700; white-space: nowrap; }
.att-why { margin: 0.35rem 0 0.5rem; font-size: 0.9rem; color: var(--text); }
.att-go { font-size: 0.9rem; font-weight: 600; }
.att-more, .att-clear { margin: 0.4rem 0 0; }

/* All three pass 4.5:1 on their own background -- see tools/check_contrast.py. */
.att-blocking { border-left-color: #b91c1c; }
.att-blocking .att-flag { background: #fee2e2; color: #8c1616; }
.att-warning  { border-left-color: #b45309; }
.att-warning  .att-flag { background: #fef3c7; color: #7c3d06; }
.att-note     { border-left-color: #0b5cd5; }
.att-note     .att-flag { background: #dbeafe; color: #0a4aa8; }

/* Tall enough to need its own scroll on a phone rather than pushing the OK
   button off the bottom, which would make it feel like a trap. */
.att-modal { max-width: 40rem; }
@media (max-width: 600px) {
  .att-item-head { gap: 0.3rem; }
  .att-money { width: 100%; }
}
