:root{
  --ink:#1C1F26; --paper:#F7F7F5; --card:#FFFFFF; --line:#E3E1DA; --muted:#6B6A63;
  --red:#C0392B; --red-bg:#FBE4E2; --amber:#B8860B; --amber-bg:#FCEFCF;
  --green:#1F7A54; --green-bg:#E1F3E9; --blue:#2B5FA6; --blue-bg:#E4ECF7; --gray-bg:#EEEEEC;
  --purple:#7C5CFC; --orange:#E0791F; --slate:#6B6A63; --cancel-gray:#9A9990;
  /* --ink, tinted toward the darkest point of the Clover logo's leaf
     gradient rather than using that green at full saturation -- keeps the
     top bar reading as the same near-black neutral as the rest of the app
     (color as accent, not as a dominant field), just quietly brand-tinted.
     --clover-green-light (the leaf's brightest point) is reserved for a
     small hover accent, not a static stripe. */
  --clover-green:#1A3529; --clover-green-light:#2FA748;
}
*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;background:var(--paper);color:var(--ink);font-size:14px;}
a{color:var(--blue);text-decoration:none;}
a:hover{text-decoration:underline;}
.topnav{display:flex;align-items:center;justify-content:space-between;background:var(--clover-green);color:#fff;padding:12px 24px;}
.topnav a{color:#fff;opacity:.85;margin-right:18px;font-size:13px;font-weight:600;padding-bottom:2px;border-bottom:2px solid transparent;}
.topnav a:hover{opacity:1;text-decoration:none;border-bottom-color:var(--clover-green-light);}
.link-button{background:none;border:none;border-bottom:2px solid transparent;color:#fff;opacity:.85;font-size:13px;font-weight:600;font-family:inherit;padding:0 0 2px;cursor:pointer;}
.link-button:hover{opacity:1;border-bottom-color:var(--clover-green-light);}
.topnav-logo{background:#fff;border-radius:6px;padding:3px 10px;display:flex;align-items:center;margin-right:16px;}
.topnav-logo img{height:30px;display:block;}
.brand-lockup{display:flex;flex-direction:column;justify-content:center;margin-right:30px;line-height:1.15;}
.brand-name{font-weight:800;font-size:18px;color:#fff;letter-spacing:.01em;}
.brand-subtitle{font-weight:700;font-size:10px;color:var(--clover-green-light);text-transform:uppercase;letter-spacing:.1em;margin-top:3px;}
/* Desktop: .topnav-header (logo+brand) and .topnav-menu (links+account) sit
   side by side exactly as the old two-plain-divs markup did -- topnav-menu
   takes the remaining space and space-betweens its own two children, so
   links stay hugged up against the brand and the account block stays
   pinned to the far right. The hamburger toggle is desktop-hidden; the
   mobile media query below is what actually turns this into a menu. */
.topnav-header{display:flex;align-items:center;}
.topnav-menu{display:flex;align-items:center;justify-content:space-between;flex:1;}
.topnav-links{display:flex;align-items:center;flex-wrap:wrap;}
.topnav-right{display:flex;align-items:center;}
.topnav-toggle{display:none;background:none;border:1px solid rgba(255,255,255,.4);color:#fff;font-size:18px;line-height:1;padding:6px 12px;border-radius:5px;cursor:pointer;margin-left:auto;}
.topnav-toggle:hover{border-color:#fff;}

/* Grouped nav dropdowns -- plain <details>/<summary>, no JS needed to open/
   close (click-outside-closes and only-one-open-at-a-time are the two small
   enhancements inline-edit.js adds on top, since native <details> doesn't
   do either by itself). Same list of items can appear under more than one
   group on purpose (e.g. Department Dashboards under both Dashboard and
   Onboarding & Rollout) -- that's deliberate, not a bug. */
.nav-group{position:relative;margin-right:18px;}
.nav-group summary{color:#fff;opacity:.85;font-size:13px;font-weight:600;cursor:pointer;list-style:none;padding-bottom:2px;border-bottom:2px solid transparent;}
.nav-group summary::-webkit-details-marker{display:none;}
.nav-group summary::after{content:"\25BE";font-size:9px;margin-left:4px;opacity:.8;}
.nav-group summary:hover{opacity:1;}
.nav-group[open] summary{opacity:1;border-bottom-color:var(--clover-green-light);}
.nav-group-menu{position:absolute;top:100%;left:0;margin-top:6px;background:var(--clover-green);border:1px solid rgba(255,255,255,.25);border-radius:6px;padding:6px 0;min-width:200px;z-index:20;box-shadow:0 6px 16px rgba(0,0,0,.3);}
.nav-group-menu a{display:block;margin-right:0;padding:8px 16px;border-bottom:none;opacity:.9;font-size:13px;}
.nav-group-menu a:hover{background:rgba(255,255,255,.12);opacity:1;text-decoration:none;}

.wrap{max-width:1280px;margin:0 auto;padding:24px;}
.flash-message{padding:10px 14px;border-radius:8px;margin-bottom:14px;font-size:13px;font-weight:600;}
.flash-error{background:var(--red-bg);color:var(--red);border:1px solid var(--red);}
.flash-info{background:var(--blue-bg);color:var(--blue);border:1px solid var(--blue);}
.flash-success{background:var(--green-bg);color:var(--green);border:1px solid var(--green);}
h1{font-size:22px;margin:0 0 4px;}
h2{font-size:16px;margin:28px 0 10px;border-bottom:2px solid var(--ink);padding-bottom:6px;}
h3{font-size:14px;margin:16px 0 6px;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;}
.crumb{font-size:12px;color:var(--muted);margin-bottom:6px;}
.muted{color:var(--muted);}
.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:16px;margin-bottom:16px;}
.notes-log{list-style:none;margin:0;padding:0;}
.notes-log li{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:10px 14px;margin-bottom:8px;}
.grid-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px;margin-bottom:20px;}
table{width:100%;border-collapse:collapse;background:var(--card);border:1px solid var(--line);border-radius:8px;overflow:hidden;}
th,td{text-align:left;padding:8px 10px;border-bottom:1px solid var(--line);font-size:13px;vertical-align:middle;}
th{background:var(--clover-green);color:#fff;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.03em;}
tr:last-child td{border-bottom:none;}
tr:hover td{background:#FCFCFB;}
.badge{display:inline-block;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:700;white-space:nowrap;color:#fff;}
.badge-open{background:var(--slate);}
.badge-progress{background:var(--blue);}
.badge-resolved,.badge-complete{background:var(--green);}
.badge-hold{background:var(--purple);}
.badge-cancelled{background:var(--cancel-gray);text-decoration:line-through;}
.badge-waiting{background:var(--orange);}
.badge-blocked,.badge-atrisk{background:var(--red);}
.badge-atrisk-broad{background:var(--amber);}
.badge-noviolation{background:var(--gray-bg);color:var(--muted);}

/* Status cells: same palette as badges, but filling the whole editable
   dropdown so a task's status reads as a solid block of color, not a small pill. */
.status-cell{
  width:100%;border:none;border-radius:6px;font-weight:700;font-size:12px;color:#fff;cursor:pointer;
  -webkit-appearance:none;-moz-appearance:none;appearance:none;
  padding:6px 24px 6px 10px;background-repeat:no-repeat;background-position:right 8px center;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='white'/%3E%3C/svg%3E");
}
.status-open{background-color:var(--slate);}
.status-progress{background-color:var(--blue);}
.status-resolved{background-color:var(--green);}
.status-hold{background-color:var(--purple);}
.status-cancelled{background-color:var(--cancel-gray);text-decoration:line-through;}
.status-waiting{background-color:var(--orange);}
.status-blocked,.status-atrisk{background-color:var(--red);}
.status-noviolation{background-color:var(--gray-bg);color:var(--ink);}
.pill-row{display:flex;gap:6px;flex-wrap:wrap;align-items:center;}
.overdue{color:var(--red);font-weight:700;}
.stat{display:flex;flex-direction:column;gap:2px;border-left:4px solid var(--accent, var(--line));padding-left:12px;}
.stat .n{font-size:26px;font-weight:800;}
.stat .l{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;}
.stat-row{display:flex;gap:24px;margin-bottom:20px;flex-wrap:wrap;}
.stat-link{color:inherit;text-decoration:none;flex:1;min-width:140px;}
.stat-link:hover{text-decoration:none;}
.stat-link:hover .stat,.stat-link:hover .risk-banner{border-color:var(--accent, var(--line));box-shadow:0 0 0 1px var(--accent, var(--line));}
.stat-link .stat{margin:0;}
.risk-banner{display:flex;align-items:center;gap:20px;padding:20px 24px;border-left:6px solid var(--accent, var(--line));margin-bottom:8px;}
.risk-banner-n{font-size:44px;font-weight:800;line-height:1;color:var(--ink);}
.risk-banner-l{font-size:16px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--ink);}

/* Dashboard "Needs attention": the risk-count tiles from a narrow column
   beside the actual flagged-project list, instead of alone above a full
   task table -- the whole point is answering "what's wrong" without a
   click, not just "how many things are wrong." */
.attn-grid{display:grid;grid-template-columns:180px 1fr;gap:14px;align-items:stretch;margin-bottom:28px;}
.attn-tiles{display:flex;flex-direction:column;gap:10px;}
.attn-tile{border-left-width:6px;border-left-style:solid;border-left-color:var(--line);padding:14px 16px;
  display:flex;flex-direction:column;justify-content:center;flex:1;margin-bottom:0;}
.attn-tile.crit{border-left-color:var(--red);}
.attn-tile.risk{border-left-color:var(--amber);}
.attn-tile .n{font-size:28px;font-weight:800;line-height:1;}
.attn-tile.crit .n{color:var(--red);}
.attn-tile.risk .n{color:var(--amber);}
.attn-tile .l{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--muted);margin-top:2px;}
.attn-list{padding:0;overflow:hidden;margin-bottom:0;}
.attn-row{display:flex;align-items:center;gap:14px;padding:12px 16px;border-bottom:1px solid var(--line);
  text-decoration:none;color:inherit;}
.attn-row:last-child{border-bottom:none;}
.attn-row:hover{background:var(--paper);}
.attn-stripe{width:4px;align-self:stretch;border-radius:2px;flex-shrink:0;background:var(--line);}
.attn-stripe.crit{background:var(--red);}
.attn-stripe.risk{background:var(--amber);}
.attn-stripe.wait{background:var(--orange, var(--blue));}
.attn-main{flex:1;min-width:0;}
.attn-title{font-weight:700;font-size:13.5px;}
.attn-title .cust{color:var(--muted);font-weight:500;}
.attn-reason{font-size:12px;color:var(--muted);margin-top:1px;}
.attn-days{font-size:12px;color:var(--muted);white-space:nowrap;min-width:70px;text-align:right;}
.attn-empty{padding:28px;text-align:center;color:var(--muted);font-size:13px;}
.attn-overflow{justify-content:center;color:var(--blue);font-weight:600;font-size:12.5px;}
.attn-overflow .attn-main{flex:none;}

/* Dashboard hub row -- the "quickly get to the main pages" part */
.hub-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px;margin-bottom:8px;}
.hub-card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:14px 16px;
  text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:5px;min-height:74px;
  border-top:3px solid var(--accent, var(--line));}
.hub-card:hover{border-color:var(--accent, var(--line));}
.hub-title{font-weight:700;font-size:13.5px;}
.hub-desc{font-size:11.5px;color:var(--muted);line-height:1.4;}
.hub-count{font-size:11px;color:var(--muted);font-weight:700;margin-top:auto;padding-top:2px;}

form.inline{display:inline;}
input,select,textarea{font-family:inherit;font-size:13px;padding:6px 8px;border:1px solid var(--line);border-radius:5px;background:#fff;color:var(--ink);}
button{font-family:inherit;font-size:13px;padding:7px 14px;border:none;border-radius:5px;background:var(--clover-green);color:#fff;font-weight:600;cursor:pointer;}
button.keep-ink{background:var(--ink);}
button:hover{opacity:.88;}
button.secondary{background:var(--card);color:var(--ink);border:1px solid var(--line);}
button.danger{background:var(--red);}
.form-row{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end;margin-bottom:10px;}
.form-row label{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.02em;}
.editable-select:not(.status-cell),.editable-input{border:1px solid transparent;background:transparent;cursor:pointer;}
.editable-select:not(.status-cell):hover,.editable-input:hover{border-color:var(--line);background:#fff;}
.status-cell:hover{opacity:.88;}
.editable-input{width:100%;overflow:hidden;text-overflow:ellipsis;}
.editable-select{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.task-table{table-layout:fixed;}
.chores-row td{border-top:none;padding-top:0;padding-bottom:10px;background:#FAFAF9;}
.chores-row summary{cursor:pointer;color:var(--blue);font-weight:600;padding:4px 0;}
.chores-table{margin:8px 0 8px 20px;width:calc(100% - 20px);}
.chores-table th,.chores-table td{font-size:12px;padding:6px 8px;}
.chores-subhead{margin:8px 0 2px 20px;font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.02em;}
.chores-complete-badge{color:var(--green);font-weight:700;}
/* Ties a task row to its expanded sub-tasks block beneath it -- a plain
   border-left on both, which the table's border-collapse:collapse merges
   into one unbroken line down the left margin. Only shows while the
   disclosure is actually open (native :has(details[open])), since that's
   when there's separate content underneath worth visually grouping --
   collapsed "Sub-tasks (0)" rows stay plain. */
.task-table tr:has(+ tr.chores-row details[open]) > td:first-child,
.task-table tr.chores-row:has(details[open]) > td {
  border-left: 4px solid var(--clover-green-light);
}
/* Department dashboard task rows: a colored edge for at-a-glance status,
   same idea as the connector-line above but a box-shadow instead of
   border-left specifically so the two can never fight over the same
   property on the same cell (e.g. an overdue task with its sub-tasks
   open) -- both just render, independently. */
.task-table tr.row-overdue > td:first-child{box-shadow: inset 3px 0 0 var(--red);}
.task-table tr.row-pasttarget > td:first-child{box-shadow: inset 3px 0 0 var(--amber);}
.task-table tr.row-done{opacity:.6;}
details.new-form{margin-bottom:14px;}
details.new-form summary{cursor:pointer;font-weight:700;color:var(--blue);font-size:13px;padding:6px 0;}
.category-block{margin-bottom:22px;border-left:5px solid var(--accent, var(--line));padding-left:14px;}
.dep-name{font-size:11px;color:var(--muted);}
.small{font-size:12px;}
.empty-note{color:var(--muted);font-size:13px;padding:20px;text-align:center;}

/* Inventory page's product-photo gallery -- a small clickable thumbnail per
   row, opening a full-size lightbox overlay. contain (not cover), same
   reasoning as the project-header photo: never crop the exact detail that
   makes a product recognizable. */
.product-thumb{width:36px;height:36px;object-fit:contain;border-radius:5px;border:1px solid var(--line);
  background:var(--gray-bg);cursor:zoom-in;display:block;}
.photo-lightbox{position:fixed;inset:0;background:rgba(0,0,0,.75);display:flex;align-items:center;
  justify-content:center;z-index:100;cursor:zoom-out;padding:40px;}
/* Same bug class as .project-row[hidden] above: this element's own
   display:flex silently overrides the browser's default [hidden]{display:
   none}, so toggling the `hidden` property/attribute alone does nothing --
   without this the overlay would actually show on page load despite the
   `hidden` attribute in the template, and never hide again after opening. */
.photo-lightbox[hidden]{display:none;}
.photo-lightbox img{max-width:100%;max-height:100%;border-radius:8px;box-shadow:0 20px 60px rgba(0,0,0,.5);
  background:var(--card);}
.progress-ring-text{font-size:19px;font-weight:800;fill:var(--ink);}
.progress-bar{flex:1;height:8px;background:var(--gray-bg);border-radius:20px;overflow:hidden;position:relative;}
.progress-bar-fill{height:100%;border-radius:20px;position:relative;}
.progress-bar-inprogress{position:absolute;top:0;height:100%;opacity:.35;}
.project-header{display:flex;gap:22px;align-items:center;}
.project-ring-wrap{display:flex;flex-direction:column;align-items:center;gap:2px;flex-shrink:0;}
.project-product-photo{width:140px;height:140px;object-fit:contain;border-radius:8px;border:1px solid var(--line);background:var(--gray-bg);flex-shrink:0;}
/* The upload/replace control lives up in the header's button row (next to
   View Timeline), not next to the photo -- admin-only both by the {% if
   session.role == 'admin' %} wrapping it in the template AND by
   upload_product_photo itself being @admin_required server-side, so this
   is belt-and-suspenders, not the only thing enforcing it. */
.product-photo-upload-inline input[type="file"]{font-size:11px;max-width:150px;}
.project-header-right{margin-left:auto;display:flex;gap:10px;align-items:stretch;flex-shrink:0;}
.project-header-dates{min-width:170px;background:var(--blue-bg);border:1px solid var(--blue);border-radius:8px;padding:10px 14px;}
.project-header-dates label{font-size:10px;}
.project-header-dates input{padding:4px 6px;font-size:12px;}
.project-inventory{position:relative;min-width:150px;text-align:center;background:var(--gray-bg);border:1px solid var(--line);border-radius:8px;padding:10px 16px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;}
.project-inventory-label{font-size:10px;text-transform:uppercase;font-weight:700;letter-spacing:.02em;color:var(--muted);}
.project-inventory-count{font-size:32px;font-weight:800;line-height:1;color:var(--ink);}
.project-inventory-caption{font-size:11px;}
/* Floats over the box's top-left corner, dipping slightly into it -- plain
   colored text on purpose, no background/border of its own (the box itself
   stays a neutral gray always, since green/red on the box would read as
   "good"/"bad" when a stock change is usually just normal movement). */
.project-inventory-delta{position:absolute;top:0;left:14px;transform:translateY(-60%);font-size:20px;font-weight:800;line-height:1;letter-spacing:-.01em;text-shadow:0 1px 0 var(--card),0 0 6px var(--card);pointer-events:none;}
.project-inventory-delta.up{color:var(--green);}
.project-inventory-delta.down{color:var(--red);}
.project-inventory-delta.flat{color:var(--muted);}
.inv-inline-wrap{white-space:nowrap;}
.inv-count{font-weight:700;}
.inv-delta{font-weight:700;margin-left:3px;}
.inv-delta-up{color:var(--green);}
.inv-delta-down{color:var(--red);}
.inv-delta-flat{color:var(--muted);}
.project-header-meta{display:flex;flex-direction:column;gap:5px;}
.project-countdown{font-size:22px;font-weight:800;color:var(--ink);}
.project-countdown.project-countdown-overdue{color:var(--red);}
.project-countdown.project-countdown-soon{color:var(--amber);}
.project-count{font-weight:700;font-size:14px;}
.project-next{font-size:13px;}
.project-target{font-size:12px;}
.category-progress{display:flex;align-items:center;gap:10px;margin:16px 0 6px;}
.category-progress h3{margin:0;white-space:nowrap;color:var(--accent, var(--muted));}
.category-progress .pct{font-size:12px;font-weight:700;color:var(--muted);white-space:nowrap;}
.milestone-summary{cursor:pointer;}
.milestone-summary:hover h3{text-decoration:underline;}
.project-banner{margin-bottom:26px;}
.project-banner-title{font-size:16px;font-weight:800;}
.view-project-btn{border-color:var(--blue);color:var(--blue);font-weight:700;}
.view-project-btn:hover{background:var(--blue-bg);}
.project-progress{display:flex;align-items:center;gap:8px;margin-top:8px;max-width:240px;}
.project-progress .progress-bar{flex:1;}
.project-progress-pct{font-size:11px;color:var(--muted);font-weight:700;white-space:nowrap;}

/* Department dashboard's pending-requests panel -- was a plain <table>,
   now a card matching the main Dashboard's "Needs attention" visual
   language (colored header bar instead of a colored table border). */
.pending-panel{background:var(--card);border:1px solid var(--amber);border-radius:8px;overflow:hidden;margin-bottom:24px;}
.pending-panel-head{background:var(--amber-bg);padding:10px 16px;font-weight:700;font-size:13px;color:#6b5209;
  display:flex;justify-content:space-between;align-items:center;}
.pending-panel-count{background:var(--amber);color:#fff;border-radius:20px;font-size:11px;font-weight:800;
  padding:1px 8px;}
.pending-panel-row{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:12px 16px;border-top:1px solid var(--line);}
.pending-panel-main{flex:1;min-width:200px;}
.pending-panel-title{font-weight:600;font-size:13.5px;}
.pending-panel-meta{font-size:12px;color:var(--muted);margin-top:2px;}

/* Department Timeline's mobile accordion -- a collapsible list of projects,
   each opening into its own full-width timeline (see .timeline-card-dept's
   mobile rules) instead of cramming every project's track into one shared,
   narrow chart. Hidden entirely outside the mobile breakpoint (see
   .dept-timeline-desktop/.dept-timeline-mobile-accordion toggle there) --
   this block only styles what it looks like once shown. */
.dept-timeline-mobile-accordion{display:none;}
.dept-timeline-item{background:var(--card);border:1px solid var(--line);border-radius:8px;
  padding:10px 12px;margin-bottom:10px;}
.dept-timeline-item summary{cursor:pointer;display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  list-style:none;}
.dept-timeline-item summary::-webkit-details-marker{display:none;}
.dept-timeline-item summary::before{content:"▸";color:var(--muted);font-size:11px;transition:transform .15s;}
.dept-timeline-item[open] summary::before{transform:rotate(90deg);}
.dti-name{font-weight:700;font-size:13px;}
.dti-meta{width:100%;}
.dept-timeline-item[open] summary{margin-bottom:10px;}
.dept-timeline-item .card{border:none;padding:0;margin:0;}
.project-link{font-weight:700;white-space:nowrap;}
.project-header{border-top:4px solid var(--accent, var(--line));}
.widget-row{display:flex;gap:16px;margin-bottom:20px;flex-wrap:wrap;}
.widget{display:flex;align-items:center;justify-content:center;gap:14px;flex:1;min-width:220px;}
.widget-label{font-size:13px;font-weight:700;}

.launch-btn-row{display:flex;gap:16px;margin-bottom:28px;flex-wrap:wrap;}
.big-launch-btn{flex:1;min-width:220px;padding:28px 20px;font-size:16px;font-weight:800;border-radius:10px;
  cursor:pointer;border:none;color:#fff;text-align:center;font-family:inherit;}
.big-launch-btn:hover{opacity:.9;}
.big-launch-btn.onboarding{background:#12B5A6;}
.big-launch-btn.rollout{background:var(--purple);}
.big-launch-btn.customer{background:var(--blue);}

.wizard-overlay{position:fixed;inset:0;background:rgba(28,31,38,.55);display:flex;align-items:center;
  justify-content:center;z-index:100;padding:20px;}
.wizard-overlay[hidden]{display:none;}
.wizard-box{background:var(--card);border-radius:10px;padding:24px;max-width:640px;width:100%;
  max-height:88vh;overflow-y:auto;}
.wizard-box h2{margin-top:0;}
.wizard-box-header{display:flex;align-items:flex-start;justify-content:space-between;}
.wizard-close{background:none;border:none;color:var(--muted);font-size:26px;line-height:1;padding:0 4px;cursor:pointer;font-weight:400;}
.wizard-close:hover{color:var(--ink);opacity:1;}
.wizard-step{display:none;}
.wizard-step.active{display:block;}
.wizard-nav{display:flex;justify-content:space-between;margin-top:20px;}
.extra-task-row{display:flex;gap:8px;margin-bottom:8px;}
.extra-task-row input,.extra-task-row select{flex:1;}

.timeline-scale{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);margin:0 0 6px 168px;}
.timeline-row{display:flex;align-items:center;gap:12px;margin-bottom:12px;border-left:4px solid var(--accent, var(--line));padding-left:10px;}
.timeline-row-label{width:140px;flex-shrink:0;font-size:12px;font-weight:700;color:var(--accent, var(--muted));
  text-transform:uppercase;letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.timeline-row-track{position:relative;flex:1;height:34px;background:var(--gray-bg);border-radius:6px;}
.timeline-marker{position:absolute;top:50%;width:16px;height:16px;border-radius:50%;border:2px solid #fff;
  transform:translate(-50%,-50%);box-shadow:0 0 0 1px var(--line);cursor:default;}
.timeline-marker-overdue{box-shadow:0 0 0 3px var(--red);}
.timeline-marker-past-target{box-shadow:0 0 0 3px var(--amber);}
.timeline-marker-small{width:12px;height:12px;}
.timeline-marker-badge{width:20px;height:20px;display:flex;align-items:center;justify-content:center;
  color:#fff;font-size:10px;font-weight:800;font-family:inherit;cursor:default;}
/* A small dot flagging "this task has open sub-tasks" -- a separate layer
   (not a box-shadow ring like overdue/past-target) so it composes cleanly
   even when a marker already has one of those rings. Department timeline
   only -- see _timeline_marker() in _macros.html. */
.timeline-marker-has-subtasks::after{content:"";position:absolute;top:-3px;right:-3px;
  width:7px;height:7px;border-radius:50%;background:var(--blue);border:1.5px solid #fff;}
.timeline-card-dept{border:3px solid var(--clover-green);background:#F4F7F5;}
.timeline-row-track-dept{background:#E1E9E4;}
.timeline-marker-dept{border-radius:3px;transform:translate(-50%,-50%) rotate(45deg);cursor:pointer;}
.timeline-marker-dept:hover{box-shadow:0 0 0 3px var(--clover-green-light);}
.task-table tr:target{animation:target-flash 2s ease-out;}
@keyframes target-flash{
  0%,30%{background:var(--amber-bg);}
  100%{background:transparent;}
}
.timeline-today-line,.timeline-target-line{position:absolute;top:-4px;bottom:-4px;width:2px;}
.timeline-today-line{background:var(--ink);}
.timeline-target-line{background:var(--red);}
.timeline-legend{display:flex;gap:18px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin-top:14px;}
.timeline-legend-swatch{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:5px;vertical-align:middle;}
/* Mobile-only alternative to the plain inline secondary-legend spans, same
   dual-render idea as .timeline-scroll/.timeline-list above -- desktop
   never shows this at all; see the .timeline-card-dept mobile override. */
.timeline-legend-more-mobile{display:none;font-size:12px;color:var(--muted);}
.timeline-legend-more-mobile summary{cursor:pointer;color:var(--blue);font-weight:600;}
.timeline-legend-more-mobile .timeline-legend{margin-top:8px;gap:10px 16px;}
.timeline-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}
/* Chronological list alternative to the scroll-track, mobile-only (see the
   media query below) -- hidden on desktop by default. */
.timeline-list{display:none;}
.timeline-list-item{display:flex;align-items:baseline;gap:12px;padding:8px 10px;border-left:4px solid var(--accent, var(--line));
  border-radius:4px;background:var(--gray-bg);margin-bottom:6px;text-decoration:none;color:inherit;}
.timeline-list-item-overdue{box-shadow:inset 0 0 0 2px var(--red);}
.timeline-list-item-past-target{box-shadow:inset 0 0 0 2px var(--amber);}
.timeline-list-item-done{opacity:.55;}
.timeline-list-date{flex-shrink:0;width:64px;font-size:12px;font-weight:700;color:var(--accent, var(--muted));}
.timeline-list-body{flex:1;display:flex;flex-direction:column;min-width:0;}
.timeline-list-task{font-size:13px;font-weight:600;color:var(--ink);}
.timeline-list-row{font-size:11px;color:var(--muted);}
.timeline-list-status{flex-shrink:0;font-size:11px;color:var(--muted);text-align:right;}

/* ---- Projects Navigator (/projects) -- search/filter is instant, client-
   side (see projects.html's own <script>), not a server round-trip like
   /requests or /audit-log, since the whole point is fast jumping around. ---- */
.chip-toggle{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--muted);padding:8px 12px;border:1px solid var(--line);border-radius:7px;cursor:pointer;user-select:none;background:var(--paper);}
.chip-toggle input{accent-color:var(--red);}
.chip-toggle.active{background:var(--red-bg);border-color:var(--red);color:var(--red);font-weight:600;}
.result-count{font-size:12px;color:var(--muted);margin:10px 0 14px 2px;}
.customer-group{margin-bottom:26px;}
.customer-group-head{display:flex;align-items:baseline;gap:10px;margin-bottom:10px;padding-bottom:6px;border-bottom:1px solid var(--line);}
.customer-group-head h2{margin:0;font-size:16px;}
.project-list{display:flex;flex-direction:column;gap:8px;}
.project-row{display:grid;grid-template-columns:92px 1fr auto auto 140px 100px auto;gap:16px;align-items:center;
  background:var(--card);border:1px solid var(--line);border-left:4px solid var(--accent, var(--line));border-radius:8px;
  padding:11px 16px;color:inherit;}
/* Filtering sets the native `hidden` attribute via JS, but this rule's own
   `display:grid` above -- an author-stylesheet rule -- silently overrides
   the browser's default `[hidden]{display:none}`, since author styles beat
   user-agent defaults regardless of selector specificity. Without this,
   row.hidden=true is set correctly (the visible-count text was already
   right) but the row never actually disappears. */
.project-row[hidden]{display:none;}
.project-row:hover{border-color:var(--accent, var(--muted));text-decoration:none;}
.kind-tag{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);}
.project-row .project-name{font-weight:600;font-size:14px;}
.project-row .flags{display:flex;gap:5px;}
.project-row .progress-cell{display:flex;flex-direction:column;gap:4px;min-width:0;}
.project-row .progress-label{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;}
.project-row .due-cell{text-align:right;font-size:12px;}
.project-row .due-cell .days{font-weight:700;font-variant-numeric:tabular-nums;}
.project-row .open-link{justify-self:end;font-size:12px;font-weight:600;padding:6px 12px;border-radius:6px;background:var(--paper);border:1px solid var(--line);color:var(--ink);}

/* ===========================================================================
   Mobile (phones/small tablets). This is a retrofit onto a desktop-first
   layout, not a rebuild -- one breakpoint, and the strategy throughout is
   "stack to a single column, let wide things scroll sideways" rather than
   redesigning every screen. Verified by reading computed layout/fetching
   real pages, NOT by eye on an actual device (no browser tool available in
   this session) -- worth a real phone/narrow-window check before calling
   this done, especially the tables and timeline below.
   =========================================================================== */
@media (max-width: 768px){
  .wrap{padding:14px;}

  /* Topnav: collapses behind a hamburger toggle instead of wrapping to
     several lines of green (the first mobile pass just let it wrap, which
     ate a huge chunk of the screen before any real content -- this hides
     it behind a tap instead). The open menu is an overlay (position:absolute,
     floating above the page) rather than pushing page content down the way
     it did originally -- with 4 nav-group dropdowns plus the account row,
     an inline-flow menu got tall enough to bury the actual page below a
     full screen of green before you'd even scrolled. top:100% positions it
     right below .topnav-header without hardcoding a header height (same
     trick .nav-group-menu already uses relative to its own summary). */
  .topnav{flex-wrap:wrap;padding:10px 16px;position:relative;}
  .topnav-header{width:100%;justify-content:space-between;}
  .topnav-toggle{display:inline-block;}
  .topnav-menu{display:none;position:absolute;top:100%;left:0;right:0;width:100%;flex-direction:column;
    align-items:flex-start;gap:14px;margin-top:0;padding:16px;background:var(--clover-green);
    max-height:80vh;overflow-y:auto;box-shadow:0 12px 28px rgba(0,0,0,.35);z-index:50;}
  .topnav-menu.open{display:flex;}
  .topnav-links,.topnav-right{flex-direction:column;align-items:flex-start;gap:10px;width:100%;}
  .topnav a,.link-button{margin-right:0;}
  .brand-lockup{margin-right:16px;}

  /* Nav-group dropdowns: no room to float an absolutely-positioned panel on
     a narrow screen, so they just expand inline in the already-vertical
     stack instead -- same idea as any mobile accordion. */
  .nav-group{width:100%;margin-right:0;}
  .nav-group-menu{position:static;margin-top:4px;margin-left:10px;padding:2px 0;min-width:0;background:rgba(255,255,255,.08);box-shadow:none;border:none;}

  /* Stat tiles / risk banners / completion rings / launch buttons: all
     already flex-wrap, just force them to one full-width column instead of
     an uneven 2-then-1 wrap. */
  .stat-row,.widget-row,.launch-btn-row{flex-direction:column;}
  .stat-link,.widget,.big-launch-btn{width:100%;min-width:0;}
  .risk-banner-n{font-size:34px;}

  /* Needs-attention grid: the two risk-count tiles stack above the flagged
     list instead of sitting in a cramped fixed-width side column. */
  .attn-grid{grid-template-columns:1fr;}
  .attn-tiles{flex-direction:row;}

  /* Project header: ring + meta + the target-date panel no longer fit in
     one row -- let the date panel drop below instead of squeezing. Centered
     rather than left-packed (the default for a wrapped flex row) so each
     wrapped line reads as a centered group instead of hugging the left
     edge with dead space on the right. */
  .project-header{flex-wrap:wrap;justify-content:center;text-align:center;}
  .project-header-meta{align-items:center;}
  .project-header-right{margin-left:0;width:100%;flex-wrap:wrap;justify-content:center;}
  .project-header-dates{min-width:0;flex:1;text-align:left;}
  .project-inventory{min-width:0;flex:1;}

  /* Tables: the standard "let it scroll sideways instead of overflowing
     the page or crushing every column unreadably" pattern. Text-only
     tables still lay out fine; ones with unreadable multi-column data (the
     admin task-edit tables especially) need a real full-screen device test,
     not just "doesn't overflow the page." */
  table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;}

  /* Task tables specifically (onboarding_detail.html/rollout_detail.html):
     confirmed genuinely broken on a real phone. First attempt (just adding
     min-width to the table itself) was wrong -- unlike the div-based
     timeline below, .task-table is a real <table table-layout:fixed> with
     percentage-width <col>s, and the generic `table{display:block}` rule
     above breaks the table formatting context those percentages depend on
     entirely (a `display:block` table can't run its own column-width
     algorithm), no matter what min-width says. Real fix: override back to
     `display:table` here specifically -- higher specificity than the bare
     `table` selector above, so .task-table keeps real table layout and its
     <col> widths -- and let a wrapping .task-table-scroll div (see the
     templates) handle the actual horizontal scrolling instead of the table
     element itself. */
  /* Still cramped at 740px per a follow-up screenshot -- that width was
     never actually enough for the 8-column admin table (Department/POC/Due
     were still truncating to a couple of characters), and there was no
     visual hint that the table scrolls sideways at all, so the missing
     Task/Status columns just looked gone. Widened to comfortably fit every
     column in the widest (8-column) variant -- the 4-column department
     table ends up wider than it strictly needs, which is a much smaller
     problem than any column being too narrow to read or tap. The `::before`
     hint text needs no template changes, so it can't be missed on a table
     the way the .task-table-scroll wrapper div itself was the first time. */
  .task-table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;position:relative;}
  .task-table-scroll::before{content:"\21D4 scroll sideways for more";display:block;
    font-size:11px;font-weight:600;color:var(--muted);text-align:center;padding:5px 0;
    background:var(--gray-bg);border-radius:6px 6px 0 0;}
  .task-table{display:table;table-layout:fixed;min-width:1100px;}

  /* Timeline: reverted back to the horizontal scroll-track (the vertical
     chronological list lost the at-a-glance relative spacing that's the
     whole point of a timeline). Compressing further would overlap markers
     into illegibility, so it scrolls sideways instead, same idea as tables
     above. The chronological-list markup still exists in timeline_widget()
     (unused, .timeline-list stays display:none) in case a real axis-flip
     redesign is wanted later. */
  .timeline-scale,.timeline-row{min-width:520px;}

  /* Department Timeline specifically (.timeline-card-dept -- scoped so the
     project-level timeline above is completely untouched): the
     label-beside-track layout squeezes the track down to almost nothing on
     a narrow screen (confirmed by a real screenshot -- the label was
     truncating mid-word and the track showed no markers at all). Stack the
     label on its own full-width line above the track instead -- that part
     was right. Dropping the track's min-width entirely was wrong, though
     (a second screenshot): the track just got *narrower* than before (the
     viewport minus padding, vs. the old 520px scrollable width), packing
     the same markers into less room and making them overlap worse, not
     better. Real fix: keep a real min-width on the track/scale (so markers
     get real breathing room and stay aligned with each other) and let
     .timeline-scroll handle the horizontal scroll like the project
     timeline already does -- the label, on its own full-width line above,
     never needs to scroll at all, which is the actual win here. */
  .timeline-card-dept .timeline-row{flex-direction:column;align-items:stretch;gap:4px;min-width:0;}
  .timeline-card-dept .timeline-row-label{width:auto;white-space:normal;overflow:visible;text-overflow:clip;min-width:0;}
  .timeline-card-dept .timeline-scale{margin-left:0;min-width:520px;}
  .timeline-card-dept .timeline-row-track{min-width:520px;}
  .timeline-card-dept .timeline-scroll{position:relative;}
  .timeline-card-dept .timeline-scroll::before{content:"\21D4 scroll sideways for more";display:block;
    font-size:11px;font-weight:600;color:var(--muted);text-align:center;padding:5px 0;
    background:var(--gray-bg);border-radius:6px;margin-bottom:6px;}
  /* Secondary legend meanings (faded/overdue/past-target/sub-tasks) move
     behind a tap-to-reveal <details> here instead of eating several lines
     by default -- Today/Target/marker-color stay always visible. Desktop
     never sees the toggle (.timeline-legend-more-mobile stays display:none
     there); the plain inline versions of the same items
     (.timeline-legend-secondary-inline) are what desktop shows instead,
     and those are what get hidden here. */
  .timeline-card-dept .timeline-legend-secondary-inline{display:none;}
  .timeline-card-dept .timeline-legend-more-mobile{display:block;margin-top:8px;}

  /* Swap the shared multi-project timeline for the per-project accordion --
     desktop has room to show every project's track together; mobile
     doesn't, so it shows a collapsible list instead (see .dept-timeline-item
     above for what each one looks like open/closed). */
  .dept-timeline-desktop{display:none;}
  .dept-timeline-mobile-accordion{display:block;}

  /* Projects Navigator: the 7-column row grid has nowhere to go on a narrow
     screen, so it stacks into a single column per project instead. */
  .project-row{grid-template-columns:1fr;gap:6px;}
  .project-row .due-cell{text-align:left;}
  .project-row .open-link{justify-self:start;}

  /* Wizard: repeatable task-row inputs (category/name/department/date)
     stack instead of squeezing four fields into one line. */
  .extra-task-row{flex-direction:column;}
  .wizard-box{padding:16px;}

  /* Slightly larger tap targets -- 13px/6-7px padding is comfortable with a
     mouse but tight in a touch UI. */
  input,select,textarea,button{font-size:14px;padding:9px 10px;}
}
