/* ============================================================================
   kaymen.dev — client portal

   Ported from mockup/back-office.html (2026-08-16). Ohav's pick:
     · Portal → "Reassurance" base, plus Workspace's "yours to do" block when the
       client actually has something to do.

   Palette, faces and the glass recipe are the LOCKED ones from
   HANDOFF-REDESIGN-2026-08-15.md §1 and ../styles.css. Do not re-open them here.

   Three things that will bite:

   1. THE LEGACY TOKEN BRIDGE IS GONE (removed in the 2026-08-16 sweep), as it is
      in admin/styles.css. It used to remap the old dark theme's variable names
      (--surface-3, --text-dim, --danger …) onto this palette. Those are classes
      now. The last two holdouts were inside progressRing(), which drew with
      var(--surface-3) and var(--text) *inside SVG* — where a missing variable
      renders as nothing at all rather than as an obviously wrong colour.

   2. The dark/light toggle is GONE, on the same grounds the main site and the
      admin dropped theirs: the palette is light-first and no dark variant is
      designed. Do not ship a half-working dark mode.

   3. This portal is read by clients, not operators. The admin's two severity
      tones exist here too, but the bar is higher: --alert is for a thing that is
      actually wrong, never for "you have a ticket open". A client who is shown
      red for normal work learns to ignore red.

   Layout:
     1. Tokens
     2. Base, ambience, the glass rail, the mobile tabbar
     3. Shared atoms — card, badge, button, table, form, alert
     4. Overview — "Reassurance": hero sentence, timeline, ring, story
     5. "Yours to do" — the Workspace block, shown only when it has contents
     6. Dashboard cards, plan, tickets, ticket detail, comments
     7. Login, invite, markdown
     8. Mobile
   ============================================================================ */

/* ================================================================ 1. TOKENS */
:root{
  /* --- the Kaymen Group palette, verbatim --- */
  --bg:#ffffff;
  --bg-alt:#f4f5f7;
  --ink:#1a1b1e;
  --muted:#5f6368;
  --accent:#2bbcb3;
  --accent-dark:#229e96;
  --accent-soft:rgba(43,188,179,.08);
  --accent-glow:rgba(43,188,179,.18);
  --line:#e2e4e8;
  --deep:#16303d;

  /* the same two severity tones the admin declares, held to a higher bar here */
  --warn:#a8761c;   --warn-soft:rgba(168,118,28,.09);
  --alert:#b8443c;  --alert-soft:rgba(184,68,60,.08);

  --display:'Sora',-apple-system,BlinkMacSystemFont,sans-serif;
  --body:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;

  --w-page:1120px;
  --rail-w:224px;
  --rail-gap:32px;
  --rail-off:26px;   /* minimum clearance from the screen edge */
  /* .main is left-aligned with a max-width here, so the text edge is a fixed
     expression rather than the viewport-dependent one the marketing site needs */
  --text-left:calc(var(--rail-off) + var(--rail-w) + var(--rail-gap));
  /* dead centre reads as parked. One number — raise or lower it here. */
  --rail-lift:clamp(0px,5.5vh,58px);
  --ease:cubic-bezier(.4,0,.2,1);
  --spring:cubic-bezier(.34,1.4,.64,1);

  --gradient:linear-gradient(150deg,var(--accent) 0%,var(--accent-dark) 100%);
  /* JetBrains Mono went with the 2026-08-15 redesign; the system stack carries
     the few monospace strings left */
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}

/* THE LEGACY TOKEN BRIDGE IS GONE, as of the 2026-08-16 sweep. It existed
   because app.js carried inline styles written against the old dark theme's
   variable names; those are classes now, and
   `grep 'var(--surface\|--text-dim\|--danger\|--border)' portal/app.js`
   returns nothing. progressRing() was the dangerous one — it drew with
   var(--surface-3) and var(--text) INSIDE svg, where a missing variable renders
   as nothing at all rather than as an obviously wrong colour. It uses --line
   and --ink now. Do not reintroduce a bridge name to make a new inline style
   work; add a class here instead. */

/* ======================================================= 2. BASE + RAIL */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{
  font-family:var(--body);background:var(--bg);color:var(--ink);
  line-height:1.6;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;max-width:100vw;
}
a{color:inherit;text-decoration:none}
button{font:inherit;cursor:pointer;border:0;background:none;color:inherit}
ul{list-style:none}
h1,h2,h3,h4{font-family:var(--display);letter-spacing:-.03em;line-height:1.15;font-weight:700}
svg{display:block}
::selection{background:var(--accent-soft)}

.ambient{position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.ambient i{position:absolute;border-radius:50%;filter:blur(90px);display:block}
.ambient .g1{width:640px;height:640px;top:-330px;left:-220px;background:rgba(43,188,179,.055)}
.ambient .g2{width:520px;height:520px;top:40%;right:-280px;background:rgba(43,188,179,.04)}
.ambient .g3{width:480px;height:480px;bottom:-280px;left:20%;background:rgba(28,35,51,.03)}

.layout{position:relative;z-index:1}

/* --------------------------------------------------------------- the rail
   Recipe lifted verbatim from ../styles.css, same as the admin's.
   LOCKED: always 224px, always labelled, no hover-to-collapse.              */
.sidebar{
  position:fixed;top:calc(50% - var(--rail-lift));transform:translateY(-50%);
  left:max(var(--rail-off),calc((var(--text-left) - var(--rail-w)) / 2));
  z-index:80;width:var(--rail-w);padding:10px 9px;border-radius:26px;
  display:flex;flex-direction:column;gap:2px;overflow:hidden;
  background:rgba(255,255,255,.55);
  backdrop-filter:blur(30px) saturate(190%);
  -webkit-backdrop-filter:blur(30px) saturate(190%);
  box-shadow:
    0 24px 54px -18px rgba(22,48,61,.22),
    0 8px 20px -8px rgba(22,48,61,.10),
    0 0 0 .5px rgba(255,255,255,.70),
    0 0 0 1px rgba(226,228,232,.75),
    inset 0 1px 0 rgba(255,255,255,.90),
    inset 0 -1px 0 rgba(22,48,61,.04);
  transition:box-shadow .38s var(--ease);
}
.sidebar::before{
  content:"";position:absolute;inset:0;border-radius:26px;pointer-events:none;
  background:linear-gradient(180deg,rgba(255,255,255,.65) 0%,rgba(255,255,255,.14) 22%,rgba(255,255,255,0) 48%);
  mix-blend-mode:screen;
}
.sidebar:hover,.sidebar:focus-within{
  box-shadow:
    0 34px 70px -20px rgba(22,48,61,.28),
    0 10px 24px -8px rgba(22,48,61,.12),
    0 0 0 .5px rgba(255,255,255,.75),
    0 0 0 1px rgba(226,228,232,.8),
    inset 0 1px 0 rgba(255,255,255,.92);
}
/* The lockup: arch with the name under it, replacing the tile-plus-text mark on
   2026-08-16. The sidebar is --rail-w (224px) with 9px padding, so this lands at
   ~169px, inside the display cut's 140px-and-up band. It is a background-image
   rather than an inline SVG because an SVG loaded as an image cannot reach the
   page's webfont; the file carries its own embedded Sora. */
.sidebar-logo{
  display:block;flex:none;position:relative;z-index:2;
  height:88px;margin:0 4px 8px;
  background:url("/assets/brand/kaymen-lockup.svg") no-repeat center/contain;
}
.sidebar-label{
  font-size:9px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:var(--muted);padding:0 8px 8px 50px;margin-top:-8px;position:relative;z-index:2;
}
.sidebar-nav{position:relative;display:flex;flex-direction:column;gap:2px;z-index:2}
.sidebar-nav li a{
  display:flex;align-items:center;gap:13px;height:40px;padding:0 9px;
  border-radius:14px;color:var(--muted);position:relative;
  transition:color .2s var(--ease);font-size:13.5px;font-weight:500;
  letter-spacing:-.005em;white-space:nowrap;
}
.sidebar-nav li a .icon{
  width:18px;height:18px;flex:none;display:flex;align-items:center;justify-content:center;
}
.sidebar-nav li a .icon svg{width:18px;height:18px;stroke-width:1.6}
.sidebar-nav li a:hover{color:var(--ink)}
.sidebar-nav li a.active{
  color:var(--accent-dark);font-weight:600;background:var(--accent-soft);
  box-shadow:inset 0 0 0 1px rgba(43,188,179,.22),inset 0 1px 0 rgba(255,255,255,.7);
}
/* the count is how a client sees "there is something here for me" without
   opening the tab — the only place the rail carries a number */
.sidebar-nav li a .count{
  margin-left:auto;font-size:10.5px;font-weight:700;min-width:19px;height:19px;
  padding:0 5px;border-radius:7px;display:flex;align-items:center;justify-content:center;
  background:var(--bg-alt);color:var(--muted);
}
.sidebar-nav li a .count.hot{background:var(--accent-soft);color:var(--accent-dark)}
.sidebar-bottom{
  margin-top:8px;padding-top:10px;border-top:1px solid rgba(226,228,232,.9);
  padding-left:9px;padding-right:9px;flex:none;position:relative;z-index:2;
}
.sidebar-org{display:flex;align-items:center;gap:10px;height:26px;margin-bottom:8px}
.sidebar-org em{
  font-style:normal;font-size:11px;font-weight:600;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pulse{width:8px;height:8px;border-radius:50%;background:var(--accent);flex:none;position:relative}
.pulse::after{
  content:"";position:absolute;inset:-4px;border-radius:50%;
  border:1.5px solid var(--accent);opacity:0;animation:ping 2.6s var(--ease) infinite;
}
@keyframes ping{0%{transform:scale(.6);opacity:.7}70%{transform:scale(1.5);opacity:0}100%{opacity:0}}
.sidebar-user{
  font-size:11px;color:var(--muted);font-weight:500;margin-bottom:9px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* the content column must clear rail-offset + rail-width + gap, or it slides
   underneath — same arithmetic as the site's .page */
.main{
  position:relative;z-index:1;
  padding:34px clamp(24px,3vw,48px) 80px
          calc(var(--rail-off) + var(--rail-w) + var(--rail-gap));
  max-width:calc(var(--w-page) + var(--rail-off) + var(--rail-w) + var(--rail-gap) + 48px);
}

.page-header{padding-bottom:22px}
.page-header h1{font-size:30px;letter-spacing:-.04em}
.page-header p{font-size:13.5px;color:var(--muted);margin-top:8px}
.rule{height:1px;background:var(--line);border:0;margin:0}
.eyebrow{
  font-size:10.5px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
  color:var(--accent-dark);
}

/* ===================================================== 3. SHARED ATOMS */
.card{
  background:#fff;border:1px solid var(--line);border-radius:16px;
  padding:0;margin-bottom:18px;
}
.card > *:not(.card-header):not(.table-wrap):not(.no-pad){padding-left:18px;padding-right:18px}
.card > *:first-child:not(.card-header){padding-top:16px}
.card > *:last-child:not(.card-header){padding-bottom:16px}
.card-header{
  padding:15px 18px;border-bottom:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
}
.card-title{font-family:var(--display);font-size:14px;font-weight:700;letter-spacing:-.02em}

.badge{
  display:inline-flex;align-items:center;gap:5px;height:20px;padding:0 8px;
  border-radius:6px;font-size:10.5px;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;white-space:nowrap;
}
.badge-green,.badge-blue,.badge-purple{background:var(--accent-soft);color:var(--accent-dark)}
.badge-yellow{background:var(--warn-soft);color:var(--warn)}
.badge-red{background:var(--alert-soft);color:var(--alert)}
.badge-gray{background:var(--bg-alt);color:var(--muted)}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:12px 22px;border-radius:11px;font-family:var(--body);
  font-size:13.5px;font-weight:600;transition:all .28s var(--ease);white-space:nowrap;
}
.btn-primary{background:var(--accent);color:#fff;box-shadow:0 4px 16px var(--accent-glow)}
.btn-primary:hover{background:var(--accent-dark);transform:translateY(-1px);box-shadow:0 8px 26px var(--accent-glow)}
.btn-secondary,.btn-ghost{border:1.5px solid var(--line);color:var(--ink);background:#fff}
.btn-secondary:hover,.btn-ghost:hover{border-color:var(--accent);color:var(--accent-dark)}
.btn-success{background:var(--accent);color:#fff;box-shadow:0 4px 16px var(--accent-glow)}
.btn-success:hover{background:var(--accent-dark)}
.btn-danger{background:var(--alert-soft);color:var(--alert);box-shadow:inset 0 0 0 1px rgba(184,68,60,.2)}
.btn-danger:hover{background:var(--alert);color:#fff;box-shadow:none}
.btn-sm{padding:8px 15px;font-size:12.5px;border-radius:9px}
.btn:disabled{opacity:.5;cursor:default;transform:none;box-shadow:none}
.btn-google{
  border:1.5px solid var(--line);background:#fff;color:var(--ink);
}
.btn-google:hover{border-color:var(--accent)}

.table-wrap{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13px}
th{
  text-align:left;font-size:9.5px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);padding:12px 14px;
  border-bottom:1px solid var(--line);white-space:nowrap;
}
td{padding:11px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
tbody tr:last-child td{border-bottom:0}
tbody tr{transition:background .2s var(--ease)}
tbody tr:hover td{background:rgba(244,245,247,.7)}

.form-group{margin-bottom:14px}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.form-group label{
  display:block;font-size:11px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);margin-bottom:7px;
}
.form-group input,.form-group textarea,.form-group select{
  width:100%;padding:11px 14px;border:1px solid var(--line);border-radius:11px;
  background:#fff;color:var(--ink);font-family:var(--body);font-size:14px;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease);
}
.form-group textarea{resize:vertical;line-height:1.6;min-height:120px}
.form-group input:focus,.form-group textarea:focus,.form-group select:focus{
  outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);
}
.form-group input::placeholder,.form-group textarea::placeholder{color:#9aa0a8}
select{font-family:var(--body);color:var(--ink)}

.filter-tabs{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:16px;overflow-x:auto;-webkit-overflow-scrolling:touch}
.filter-tab{
  padding:7px 14px;border-radius:10px;font-size:12.5px;font-weight:600;
  color:var(--muted);border:1px solid var(--line);background:#fff;
  transition:all .22s var(--ease);white-space:nowrap;
}
.filter-tab:hover{color:var(--ink);border-color:#d7dae0}
.filter-tab.active{background:var(--accent-soft);color:var(--accent-dark);border-color:rgba(43,188,179,.32)}

.alert{padding:13px 16px;border-radius:12px;font-size:13px;margin-bottom:16px;line-height:1.55}
.alert-success{background:var(--accent-soft);color:var(--accent-dark);box-shadow:inset 0 0 0 1px rgba(43,188,179,.2)}
.alert-error{background:var(--alert-soft);color:var(--alert);box-shadow:inset 0 0 0 1px rgba(184,68,60,.18)}
.alert-warning{background:var(--warn-soft);color:var(--warn);box-shadow:inset 0 0 0 1px rgba(168,118,28,.18)}
.alert-info{background:var(--accent-soft);color:var(--accent-dark);box-shadow:inset 0 0 0 1px rgba(43,188,179,.2)}

.empty-state{padding:34px 18px;text-align:center}
.empty-state .icon{font-size:26px;opacity:.35;margin-bottom:10px}
.empty-state p{font-size:13px;color:var(--muted)}

.loading{display:flex;align-items:center;gap:11px;padding:30px 0;color:var(--muted);font-size:13px}
.spinner{
  width:17px;height:17px;border:2px solid var(--line);border-top-color:var(--accent);
  border-radius:50%;animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

.bar{height:5px;border-radius:3px;background:var(--bg-alt);overflow:hidden}
.bar i{display:block;height:100%;border-radius:3px;background:var(--gradient)}
.avatar{
  width:26px;height:26px;border-radius:9px;flex:none;background:var(--bg-alt);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:700;color:var(--muted);font-family:var(--display);
}
[hidden]{display:none!important}

/* --- the small utility layer -------------------------------------------------
   Not a framework. These exist because the same handful of declarations was
   repeated as inline style= across app.js — which meant every one was written
   against the OLD theme's variable names and had to be found by grep rather than
   changed in one place. Prefer a real component class where one fits.        */
.hint{font-size:13px;color:var(--muted);margin-bottom:16px;line-height:1.6}
.hint.sm{font-size:12px;margin-bottom:12px}
.row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.row.center{justify-content:center}
.stack{display:flex;flex-direction:column;gap:16px;align-items:center}
.meta{font-size:12px;color:var(--muted);white-space:nowrap}
.dim{color:var(--muted)}
.divide{border-top:1px solid var(--line);margin-top:20px;padding-top:20px}
.mt-s{margin-top:8px}
.mt-m{margin-top:12px}
.mt-l{margin-top:16px}
.mb-m{margin-bottom:16px}
.mb-l{margin-bottom:20px}
.mb-0{margin-bottom:0}
.grow{flex:1;min-width:0}
.tiny{font-size:11px}
.form-group input.mono,.form-group textarea.mono,.in.mono{font-family:var(--mono);font-size:12.5px}
.badge.mini{height:17px;font-size:9.5px;padding:0 6px;margin-left:6px}
.in{
  width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:10px;
  background:#fff;color:var(--ink);font-family:var(--body);font-size:13px;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease);
}
.in:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.in::placeholder{color:#9aa0a8}
.empty-cell{text-align:center;color:var(--muted);padding:28px}
/* the ticket rows navigate on click; they have to look like they do */
#ticketTableBody tr[data-ticket-id]{cursor:pointer}
.ink{color:var(--ink);font-weight:500}
.lnk{color:var(--accent-dark);font-weight:600}
.lnk:hover{text-decoration:underline}
.or{display:flex;align-items:center;gap:12px;margin-bottom:16px;color:var(--muted);font-size:12.5px}
.or::before,.or::after{content:"";flex:1;height:1px;background:var(--line)}
.btn-google{width:100%;background:#fff;color:var(--ink);border:1.5px solid var(--line);margin-bottom:16px}
.btn-google:hover{border-color:var(--accent)}
.btn-google svg{width:17px;height:17px}
.back{
  display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--muted);
  margin-bottom:16px;transition:color .2s var(--ease);
}
.back:hover{color:var(--accent-dark)}

/* ticket detail — the same components the admin's ticket page uses, because a
   ticket looks the same from both sides; only the internal notes differ, and a
   client never receives one */
.t-head{
  display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;
  padding-bottom:18px;border-bottom:1px solid var(--line);margin-bottom:20px;
}
.t-head h1{font-size:23px;letter-spacing:-.035em;line-height:1.25}
.t-head .sub{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:12.5px;color:var(--muted);margin-top:10px}
.t-desc{
  font-size:14px;line-height:1.7;color:var(--muted);white-space:pre-wrap;
  margin-bottom:22px;max-width:74ch;
}
.att{display:grid;gap:0}
.att-row{
  display:grid;grid-template-columns:20px minmax(0,1fr) auto auto auto;
  gap:12px;align-items:center;padding:9px 0;border-bottom:1px solid var(--line);font-size:12.5px;
}
.att-row:last-child{border-bottom:0}
.att-row .ic{font-size:15px;line-height:1}
.att-row .nm{
  color:var(--accent-dark);font-weight:500;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;cursor:pointer;
}
.att-row .nm:hover{text-decoration:underline}
.att-row .x{
  background:none;border:0;padding:0 2px;color:var(--muted);font-size:11px;
  cursor:pointer;transition:color .2s var(--ease);
}
.att-row .x:hover{color:var(--alert)}
.drop{
  border:1.5px dashed var(--line);border-radius:13px;padding:22px;text-align:center;
  cursor:pointer;transition:all .22s var(--ease);
}
.drop:hover,.drop.over{border-color:var(--accent);background:var(--accent-soft)}
.drop b{display:block;font-family:var(--body);font-size:13px;font-weight:600;color:var(--ink)}
.drop b u{text-decoration:none;color:var(--accent-dark)}
.drop span{display:block;font-size:11px;color:var(--muted);margin-top:5px}
.cmt{
  padding:14px 16px;border-radius:13px;border:1px solid var(--line);
  border-left:3px solid var(--line);margin-bottom:10px;
}
.cmt.is-you{border-left-color:var(--accent)}
.cmt.is-team{border-left-color:var(--accent-dark);background:var(--accent-soft)}
.cmt-h{display:flex;align-items:center;gap:9px;margin-bottom:7px;flex-wrap:wrap}
.cmt-h .who{font-size:12.5px;font-weight:600;letter-spacing:-.01em}
.cmt-h .tm{margin-left:auto;font-size:11px;color:var(--muted);white-space:nowrap}
.cmt-b{font-size:13.5px;line-height:1.7;color:var(--muted);white-space:pre-wrap}
.cmt-form{border-top:1px solid var(--line);padding-top:16px;margin-top:16px}
.cmt-form textarea{
  width:100%;min-height:80px;padding:12px 14px;border:1px solid var(--line);
  border-radius:12px;background:#fff;color:var(--ink);font-family:var(--body);
  font-size:13.5px;line-height:1.6;resize:vertical;
}
.cmt-form textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
@media (max-width:700px){
  .att-row{grid-template-columns:20px minmax(0,1fr) auto;row-gap:2px}
  .att-row .wh{display:none}
}

/* ================================================= 4. OVERVIEW — REASSURANCE
   Answer the question before the client has to scroll: is my thing on track,
   and does anyone still care about it. Say it in a sentence, then show the
   evidence. The sentence is derived, never written — see statusSentence()
   in app.js — because a hard-coded reassurance ages into a lie.            */
.p-hero{padding:6px 0 30px;max-width:760px}
.p-hero .eyebrow{margin-bottom:14px}
.p-hero h1{font-size:38px;letter-spacing:-.045em;line-height:1.08}
.p-hero h1 span{color:var(--accent)}
.p-hero .lead{font-size:16px;color:var(--muted);margin-top:18px;line-height:1.7;max-width:52ch}
.p-hero .lead b{color:var(--ink);font-weight:600}
.p-actions{display:flex;gap:11px;margin-top:26px;flex-wrap:wrap}

.p-grid{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:34px;padding:28px 0 34px;align-items:start}
.ring-wrap{
  display:flex;flex-direction:column;align-items:center;gap:14px;padding:22px;
  border:1px solid var(--line);border-radius:18px;background:#fff;
}
.ring{position:relative;width:132px;height:132px}
.ring svg{transform:rotate(-90deg)}
.ring .tr{stroke:var(--bg-alt)}
.ring .fg{stroke:url(#pg);stroke-linecap:round;transition:stroke-dashoffset .9s var(--ease)}
.ring .lbl{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.ring .lbl b{
  font-family:var(--display);font-size:30px;font-weight:800;letter-spacing:-.05em;
  line-height:1;font-variant-numeric:tabular-nums;
}
.ring .lbl span{
  font-size:10px;color:var(--muted);letter-spacing:.11em;text-transform:uppercase;
  margin-top:5px;font-weight:700;
}
.ring-wrap .sub{font-size:12px;color:var(--muted);text-align:center;line-height:1.5}
.ring-wrap .sub b{color:var(--ink);font-weight:600;display:block;font-size:13px;margin-bottom:3px}

/* the timeline — the same object portal/app.js already drew, re-tinted */
.tl{position:relative;padding-left:26px}
/* the spine is lit as far as the work has actually got. The mockup hard-codes
   62%; app.js passes the real figure in --lit, because a spine that always
   reaches the same point is a decoration, not a status. */
.tl::before{
  content:"";position:absolute;left:6px;top:8px;bottom:14px;width:2px;
  background:linear-gradient(180deg,
    var(--accent) 0%,var(--accent) var(--lit,0%),
    var(--line) var(--lit,0%),var(--line) 100%);
}
.tl-i{position:relative;padding:0 0 22px}
.tl-i:last-child{padding-bottom:0}
.tl-i::before{
  content:"";position:absolute;left:-26px;top:4px;width:14px;height:14px;border-radius:50%;
  background:#fff;border:2px solid var(--line);
}
.tl-i.done::before{background:var(--accent);border-color:var(--accent)}
.tl-i.done::after{
  content:"";position:absolute;left:-21.4px;top:8px;width:3.6px;height:6.6px;
  border:1.7px solid #fff;border-top:0;border-left:0;transform:rotate(42deg);
}
.tl-i.now::before{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft);animation:beat 2.4s var(--ease) infinite}
@keyframes beat{0%,100%{box-shadow:0 0 0 4px var(--accent-soft)}50%{box-shadow:0 0 0 8px rgba(43,188,179,.05)}}
.tl-i h4{font-size:14px;letter-spacing:-.02em}
.tl-i.done h4{color:var(--muted);font-weight:600}
.tl-i p{font-size:12px;color:var(--muted);margin-top:4px;line-height:1.6}
.tl-i .when{font-size:10.5px;color:var(--muted);margin-top:5px;font-variant-numeric:tabular-nums}
.tl-i.now .when{color:var(--accent-dark);font-weight:700}
.tl-i.now .when.late{color:var(--warn)}

.p-story{padding:26px 0 40px;border-top:1px solid var(--line)}
.story{display:grid;gap:0;margin-top:14px;max-width:720px}
.story-i{display:grid;grid-template-columns:78px 1fr;gap:18px;padding:11px 0;border-bottom:1px solid var(--line)}
.story-i:last-child{border-bottom:0}
.story-i .d{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;padding-top:2px;letter-spacing:.02em}
.story-i .b{font-size:13px;line-height:1.6;color:var(--muted)}
.story-i .b b,.story-i .b strong{color:var(--ink);font-weight:600}

/* ================================================== 5. "YOURS TO DO"
   Lifted from the Workspace direction and shown only when it has contents.
   The mockup's own stated cost is that an empty left column reads as neglect
   exactly when things are going well — so when there is nothing to do, this
   block is not rendered empty, it is not rendered at all, and the hero
   sentence carries the screen on its own.                                  */
.p-todo{padding:4px 0 6px}
.p-todo h3{
  font-size:12px;font-family:var(--body);font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted);margin-bottom:12px;
  display:flex;align-items:center;gap:8px;
}
.p-todo h3 u{text-decoration:none;color:var(--accent-dark)}
.todo{display:grid;gap:10px;max-width:820px}
.td{
  background:#fff;border:1px solid var(--line);border-radius:14px;padding:16px 18px;
  transition:all .25s var(--ease);
}
.td:hover{border-color:#d7dae0;box-shadow:0 10px 26px rgba(22,48,61,.06)}
.td.hero{border-color:rgba(43,188,179,.5);background:linear-gradient(180deg,var(--accent-soft) 0%,rgba(255,255,255,0) 62%)}
.td-t{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.td-t h4{font-size:14.5px;letter-spacing:-.02em}
.td p{font-size:12.5px;color:var(--muted);margin-top:7px;line-height:1.6;max-width:56ch}
.td-a{display:flex;gap:9px;margin-top:14px;align-items:center;flex-wrap:wrap}
.td-a .btn{padding:9px 17px;font-size:12.5px;border-radius:10px}
.td-a .note{font-size:11px;color:var(--muted)}
.td-meta{display:flex;gap:8px;align-items:center;margin-top:9px;font-size:11.5px;color:var(--muted);flex-wrap:wrap}
.td-meta b{color:var(--accent-dark);font-weight:600}

/* ========================== 6. THE SCREENS NOBODY RESTRUCTURED
   Plan, tickets, ticket detail and activity still render their existing
   markup. These rules re-tint that markup onto the palette; they are not a
   redesign, and they are the next thing to replace.                        */

/* --- dashboard project cards */
.hero-cards-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:18px;margin-bottom:26px}
.hero-card{
  background:#fff;border:1px solid var(--line);border-radius:18px;padding:20px;
  cursor:pointer;transition:all .28s var(--ease);
}
.hero-card:hover{border-color:rgba(43,188,179,.4);box-shadow:0 14px 34px -12px rgba(22,48,61,.14);transform:translateY(-2px)}
.hero-card-top{display:flex;align-items:center;justify-content:space-between;gap:16px}
.hero-card-info{display:flex;flex-direction:column;gap:8px;align-items:flex-start;min-width:0}
.hero-card-name{font-family:var(--display);font-size:16px;font-weight:700;letter-spacing:-.025em;line-height:1.3}
.hero-card-details{margin-top:16px}
.hero-card-ms{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.hero-card-ms-dots{display:flex;gap:4px}
.ms-dot{width:7px;height:7px;border-radius:50%;background:var(--line)}
.ms-dot.done{background:var(--accent)}
.hero-card-ms-label{font-size:11px;color:var(--muted)}
.hero-card-next{font-size:12.5px;color:var(--muted);margin-top:10px;line-height:1.5}
.hero-card-next strong{color:var(--ink);font-weight:600}
.hero-card-footer{display:flex;align-items:center;gap:9px;margin-top:12px;flex-wrap:wrap}
.hero-card-countdown{font-size:11px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
.hero-card-countdown.overdue{color:var(--warn)}
.progress-ring{flex:none}

/* --- phase bar */
.phase-bar{display:flex;align-items:flex-start;margin-bottom:26px;overflow-x:auto;padding-bottom:4px}
.phase-step{display:flex;flex-direction:column;align-items:center;gap:7px;flex:none;width:74px}
.phase-dot{
  width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:700;background:#fff;border:1.5px solid var(--line);color:var(--muted);
}
.phase-step.done .phase-dot{background:var(--accent);border-color:var(--accent);color:#fff}
.phase-step.active .phase-dot{border-color:var(--accent);color:var(--accent-dark);box-shadow:0 0 0 4px var(--accent-soft)}
.phase-label{font-size:9.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);text-align:center;line-height:1.3}
.phase-step.active .phase-label{color:var(--accent-dark)}
.phase-line{height:1.5px;background:var(--line);flex:1;min-width:14px;margin-top:12.5px}
.phase-line.done{background:var(--accent)}

/* --- project overview card (still used by the pages that keep it) */
.project-overview-card{
  display:flex;align-items:center;gap:26px;background:#fff;border:1px solid var(--line);
  border-radius:18px;padding:22px 24px;margin-bottom:22px;flex-wrap:wrap;
}
.project-overview-ring{flex:none}
.project-overview-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;flex:1;min-width:260px}
.stat-item{display:flex;flex-direction:column}
.stat-value{
  font-family:var(--display);font-size:24px;font-weight:800;letter-spacing:-.045em;
  line-height:1;font-variant-numeric:tabular-nums;
}
.stat-value.accent{color:var(--accent-dark)}
.stat-value.warning{color:var(--warn)}
.stat-value.danger{color:var(--alert)}
.stat-label{font-size:11px;color:var(--muted);margin-top:7px}
.project-overview-actions{display:flex;gap:9px;flex-wrap:wrap}
.project-content-grid{display:grid;grid-template-columns:1.4fr 1fr;gap:20px;align-items:start}

/* --- the older milestone timeline (project page keeps it under the new one) */
.timeline{display:flex;flex-direction:column}
.timeline-item{display:flex;gap:14px}
.timeline-track{display:flex;flex-direction:column;align-items:center;flex:none}
.timeline-node{
  width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:11px;background:#fff;border:2px solid var(--line);color:var(--muted);flex:none;
}
.timeline-node.completed{background:var(--accent);border-color:var(--accent);color:#fff}
.timeline-node.in_progress{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}
.timeline-connector{width:2px;flex:1;min-height:22px;background:var(--line)}
.timeline-connector.done{background:var(--accent)}
.timeline-content{padding-bottom:20px;min-width:0}
.timeline-title{font-family:var(--display);font-size:14px;font-weight:700;letter-spacing:-.02em}
.timeline-desc{font-size:12.5px;color:var(--muted);margin-top:4px;line-height:1.6}
.timeline-meta{display:flex;align-items:center;gap:9px;margin-top:7px;flex-wrap:wrap}
.timeline-date{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.timeline-notes{
  font-size:12px;color:var(--muted);margin-top:8px;padding:9px 12px;
  background:var(--bg-alt);border-radius:9px;line-height:1.6;
}

/* --- activity */
.activity-list{display:flex;flex-direction:column}
.activity-item{display:grid;grid-template-columns:26px 1fr auto;gap:12px;align-items:flex-start;padding:9px 0}
.activity-icon{
  width:26px;height:26px;border-radius:9px;background:var(--bg-alt);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--muted);flex:none;
}
.activity-text{font-size:12.5px;line-height:1.5;color:var(--muted)}
.activity-text strong{color:var(--ink);font-weight:600}
.activity-time{font-size:10.5px;color:var(--muted);white-space:nowrap;padding-top:3px;font-variant-numeric:tabular-nums}
.activity-count{
  font-size:10px;font-weight:700;background:var(--bg-alt);color:var(--muted);
  padding:1px 6px;border-radius:6px;margin-left:4px;
}
.activity-list.compact .activity-item{padding:7px 0}
.activity-dot{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}

/* --- dashboard widgets */
.dashboard-widgets{display:grid;grid-template-columns:1.3fr 1fr;gap:20px;align-items:start}
.dashboard-widgets-left,.dashboard-widgets-right{display:flex;flex-direction:column}
.widget-card{margin-bottom:18px}
.milestone-spotlight-list{display:flex;flex-direction:column}
.spotlight-item{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--line)}
.spotlight-item:last-child{border-bottom:0}
.spotlight-indicator{width:8px;height:8px;border-radius:50%;background:var(--line);flex:none}
.spotlight-indicator.in_progress{background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.spotlight-indicator.completed{background:var(--accent-dark)}
.spotlight-info{flex:1;min-width:0}
.spotlight-title{font-size:13px;font-weight:600;letter-spacing:-.01em}
.spotlight-meta{display:flex;gap:10px;font-size:11px;color:var(--muted);margin-top:3px;flex-wrap:wrap}
.ticket-stats-row{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;padding-bottom:4px}
.ticket-stat{display:flex;flex-direction:column}
.ticket-stat-num{
  font-family:var(--display);font-size:22px;font-weight:800;letter-spacing:-.045em;
  line-height:1;font-variant-numeric:tabular-nums;
}
.ticket-stat-num.accent{color:var(--accent-dark)}
.ticket-stat-num.warning{color:var(--warn)}
.ticket-stat-num.success{color:var(--accent-dark)}
.ticket-stat-label{font-size:11px;color:var(--muted);margin-top:6px}
.recent-tickets-list{display:flex;flex-direction:column;margin-top:12px;border-top:1px solid var(--line)}
.recent-ticket-item{
  display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--line);
  transition:color .2s var(--ease);
}
.recent-ticket-item:last-child{border-bottom:0}
.recent-ticket-item:hover .recent-ticket-title{color:var(--accent-dark)}
.recent-ticket-num{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;flex:none}
.recent-ticket-title{font-size:12.5px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.quick-actions{display:flex;flex-direction:column;gap:8px;margin-bottom:18px}
.quick-action-btn{
  padding:11px 15px;border:1px dashed var(--line);border-radius:12px;font-size:12.5px;
  font-weight:600;color:var(--muted);transition:all .22s var(--ease);
}
.quick-action-btn:hover{border-color:var(--accent);color:var(--accent-dark);border-style:solid}

/* --- ticket detail + comments */
.ticket-header{padding-bottom:16px;border-bottom:1px solid var(--line);margin-bottom:18px}
.ticket-title{font-family:var(--display);font-size:22px;font-weight:700;letter-spacing:-.035em;line-height:1.25}
.ticket-meta{display:flex;align-items:center;gap:9px;margin-top:11px;flex-wrap:wrap;font-size:11.5px;color:var(--muted)}
.ticket-body{font-size:14px;line-height:1.7;color:var(--muted);white-space:pre-wrap}
.comment-list{display:flex;flex-direction:column;gap:12px}
.comment{background:#fff;border:1px solid var(--line);border-radius:14px;padding:14px 16px}
.comment-header{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.comment-author{font-size:13px;font-weight:600;letter-spacing:-.01em}
.comment-date{font-size:11px;color:var(--muted);margin-left:auto;font-variant-numeric:tabular-nums}
.comment-body{font-size:13.5px;line-height:1.7;color:var(--muted);white-space:pre-wrap}
.att-download,.att-delete{
  font-size:11px;font-weight:600;color:var(--accent-dark);
  padding:4px 9px;border:1px solid var(--line);border-radius:8px;transition:all .2s var(--ease);
}
.att-download:hover{border-color:var(--accent)}
.att-delete{color:var(--alert)}
.att-delete:hover{background:var(--alert-soft);border-color:rgba(184,68,60,.3)}

/* --- plan */
.plan-content{font-size:14px;line-height:1.75}
.approve-section{
  margin-top:22px;padding:20px 22px;border:1px solid rgba(43,188,179,.4);border-radius:16px;
  background:linear-gradient(180deg,var(--accent-soft) 0%,rgba(255,255,255,0) 70%);
}

/* ========================================= 7. LOGIN, INVITE, MARKDOWN */
.login-page{
  min-height:100vh;display:flex;align-items:center;justify-content:center;
  padding:24px;position:relative;z-index:1;
}
.login-card{
  width:100%;max-width:400px;background:rgba(255,255,255,.72);
  backdrop-filter:blur(26px) saturate(180%);-webkit-backdrop-filter:blur(26px) saturate(180%);
  border-radius:22px;padding:34px 32px;
  box-shadow:
    0 26px 60px -20px rgba(22,48,61,.24),
    0 0 0 .5px rgba(255,255,255,.7),
    0 0 0 1px rgba(226,228,232,.8),
    inset 0 1px 0 rgba(255,255,255,.9);
}
.login-logo{
  display:block;width:170px;height:88px;margin:0 0 2px -17px;
  background:url("/assets/brand/kaymen-lockup.svg") no-repeat left center/contain;
}
.login-title{
  font-size:11px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:var(--muted);margin-bottom:24px;padding-left:0;
}

.md-rendered{font-size:13.5px;line-height:1.7;color:var(--muted)}
.md-rendered h1,.md-rendered h2,.md-rendered h3,.md-rendered h4{color:var(--ink);margin:20px 0 9px;letter-spacing:-.025em}
.md-rendered h1{font-size:19px}
.md-rendered h2{font-size:16px}
.md-rendered h3{font-size:14.5px}
.md-rendered h4{font-size:13px}
.md-rendered h1:first-child,.md-rendered h2:first-child,.md-rendered h3:first-child,.md-rendered h4:first-child{margin-top:0}
.md-rendered p{margin:0 0 11px}
.md-rendered p:last-child{margin-bottom:0}
.md-rendered strong{color:var(--ink);font-weight:600}
.md-rendered a{color:var(--accent-dark);font-weight:500}
.md-rendered ul,.md-rendered ol{margin:0 0 11px;padding-left:19px}
.md-rendered ul li{list-style:disc;margin-bottom:5px}
.md-rendered ol li{list-style:decimal;margin-bottom:5px}
.md-rendered li{padding-left:3px}
.md-rendered code{
  font-family:var(--mono);font-size:12px;background:var(--bg-alt);
  padding:1px 6px;border-radius:6px;color:var(--ink);
}
.md-rendered pre{background:var(--bg-alt);border:1px solid var(--line);border-radius:11px;padding:13px 15px;overflow-x:auto;margin:0 0 12px}
.md-rendered pre code{background:none;padding:0;font-size:12px;line-height:1.6}
.md-rendered hr{border:0;height:1px;background:var(--line);margin:18px 0}
.md-rendered .md-check{color:var(--muted)}
.md-rendered .md-check.done{color:var(--accent-dark)}

/* ============================================================= 8. MOBILE */
.mobile-top-bar{display:none}
.bottom-nav{display:none}

@media (max-width:1180px){
  .p-grid{grid-template-columns:minmax(0,1fr) 250px;gap:24px}
  .dashboard-widgets,.project-content-grid{grid-template-columns:1fr}
}

@media (max-width:900px){
  .sidebar{display:none}
  .main{padding:74px 18px 96px;max-width:none}
  .page-header h1{font-size:24px}
  /* the hero sentence is the whole screen here, so it gets the room */
  .p-hero{padding-top:0}
  .p-hero h1{font-size:27px}
  .p-hero .lead{font-size:14.5px}
  .p-grid{grid-template-columns:1fr;gap:26px}
  .ring-wrap{max-width:320px}
  .project-overview-stats{grid-template-columns:repeat(2,1fr)}
  .form-row{grid-template-columns:1fr}
  .story-i{grid-template-columns:62px 1fr;gap:12px}

  .mobile-top-bar{
    display:flex;position:fixed;top:12px;right:12px;z-index:90;gap:6px;padding:5px;
    border-radius:16px;background:rgba(255,255,255,.6);
    backdrop-filter:blur(24px) saturate(190%);-webkit-backdrop-filter:blur(24px) saturate(190%);
    box-shadow:0 12px 30px -10px rgba(22,48,61,.2),0 0 0 1px rgba(226,228,232,.75),inset 0 1px 0 rgba(255,255,255,.9);
  }
  .mtb-btn{
    width:34px;height:34px;border-radius:11px;display:flex;align-items:center;
    justify-content:center;color:var(--muted);font-size:15px;
    -webkit-tap-highlight-color:transparent;transition:all .2s var(--ease);
  }
  .mtb-btn svg{width:17px;height:17px;stroke-width:1.7}
  .mtb-btn:active{transform:scale(.88)}
  .mtb-btn.active{background:var(--accent-soft);color:var(--accent-dark)}

  /* the glass tabbar, same recipe as the site's and the admin's
     NOTE: when the collapsed-dot rail lands on the main site, this becomes the
     odd one out — roll that pattern here rather than keeping two mobile navs. */
  .bottom-nav{
    display:flex;position:fixed;left:12px;right:12px;bottom:14px;height:62px;z-index:80;
    border-radius:999px;padding:0 6px;align-items:center;
    background:rgba(255,255,255,.55);
    backdrop-filter:blur(34px) saturate(200%);-webkit-backdrop-filter:blur(34px) saturate(200%);
    box-shadow:
      0 20px 44px -16px rgba(22,48,61,.26),
      0 8px 18px -6px rgba(22,48,61,.12),
      0 0 0 1px rgba(226,228,232,.7),
      inset 0 1px 0 rgba(255,255,255,.9);
    padding-bottom:env(safe-area-inset-bottom);
  }
  .bottom-nav::before{
    content:"";position:absolute;inset:0;border-radius:999px;pointer-events:none;mix-blend-mode:screen;
    background:linear-gradient(180deg,rgba(255,255,255,.6) 0%,rgba(255,255,255,.12) 30%,rgba(255,255,255,0) 58%);
  }
  .bottom-nav-item{
    flex:1;height:52px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    color:var(--muted);position:relative;z-index:2;transition:color .2s var(--ease);
    -webkit-tap-highlight-color:transparent;
  }
  .bottom-nav-item:active{transform:scale(.88)}
  .bottom-nav-icon{width:19px;height:19px;display:flex;align-items:center;justify-content:center}
  .bottom-nav-icon svg{width:19px;height:19px;stroke-width:1.6}
  .bottom-nav-label{font-size:9.5px;font-weight:600;letter-spacing:.01em}
  .bottom-nav-item.active{color:var(--accent-dark)}
  .bottom-nav-item.active::before{
    content:"";position:absolute;width:52px;height:42px;border-radius:15px;z-index:-1;
    background:var(--accent-soft);box-shadow:inset 0 0 0 1px rgba(43,188,179,.22);
  }

  /* card tables — thead hidden, each cell labelled by its column */
  table.mobile-cards thead{display:none}
  table.mobile-cards,table.mobile-cards tbody,table.mobile-cards tr,table.mobile-cards td{display:block;width:100%}
  table.mobile-cards tr{
    border:1px solid var(--line);border-radius:14px;margin-bottom:10px;padding:4px 0;background:#fff;
  }
  table.mobile-cards td{
    display:flex;align-items:center;justify-content:space-between;gap:14px;
    border-bottom:1px solid var(--line);padding:9px 14px;text-align:right;
  }
  table.mobile-cards tr td:last-child{border-bottom:0}
  table.mobile-cards td::before{
    content:attr(data-label);font-size:9.5px;font-weight:700;letter-spacing:.11em;
    text-transform:uppercase;color:var(--muted);text-align:left;flex:none;
  }
  table.mobile-cards tbody tr:hover td{background:transparent}
}

@media (max-width:560px){
  .p-hero h1{font-size:24px}
  .hero-cards-grid{grid-template-columns:1fr}
  .ticket-stats-row{grid-template-columns:repeat(3,1fr);gap:8px}
  .login-card{padding:28px 22px}
  .phase-step{width:62px}
}
