/* ============================================================
   BuildFinder — site styles v2
   Design language ported from the Google Stitch mockups:
   deep midnight ink + honey amber, blueprint grid texture,
   Plus Jakarta Sans, 20px cards, soft layered shadows.
   ============================================================ */

:root {
    --ink:        #0a192f;   /* deep midnight — headings, primary surfaces */
    --ink-2:      #39475f;
    --ink-3:      #51607a;
    --amber:      #ffbf00;   /* honey amber — primary actions */
    --amber-dark: #b98600;
    --amber-soft: #fff3d1;
    --bg:         #e4e7ea;   /* light gray page background (owner's choice) */
    --card:       #ffffff;
    --surface-2:  #f3f4f5;
    --surface-3:  #edeeef;
    --line:       #e1e3e4;
    --line-2:     #c5c6cd;
    --muted:      #5b6673;
    --verified-bg:#e3f2fd;   --verified-fg:#1e88e5;
    --licensed-bg:#e8f5e9;   --licensed-fg:#2e7d32;
    --whatsapp:   #25d366;   --whatsapp-dark:#075e54;  --whatsapp-soft:#e4f9ec;
    --red:        #ba1a1a;   --red-bg:#ffdad6;
    --sage:       #87a96b;   /* an agreed request — the one colour the deal mockups added */
    /* A price rising is bad news for whoever is buying, so up is red and down is green —
       lightened here because they are only ever used on the ink-dark price strip, where
       #ba1a1a and #2e7d32 would be unreadable. */
    --price-up:   #ff9089;   --price-down:#6fdc9a;
    --radius:     20px;
    --radius-sm:  12px;
    /* The radius the mockups give a box nested INSIDE a card — the tinted strips, rows and
       framed lists in the deal room and the requests inbox. A token of its own, because the
       first attempt redefined --radius-sm on those two containers instead, and every .btn
       and .pms-input underneath them inherited it and quietly went square-ish. */
    --radius-box: 8px;
    --ring:       0 0 0 1px #e9ecef;
    --shadow-2:   0 4px 20px 0 rgba(10, 25, 47, .05);
    --shadow-3:   0 12px 30px -5px rgba(10, 25, 47, .12);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* The hidden attribute must always win, even over class rules that set display
   (e.g. .project-set uses display:flex). Without this, hidden project rows show. */
[hidden] { display: none !important; }

/* ---------- RTL (Arabic) ---------- */
/* Negative letter-spacing is a Latin-only refinement — it breaks Arabic letterforms. */
html[dir="rtl"] *, html[dir="rtl"] *::before, html[dir="rtl"] *::after { letter-spacing: 0 !important; }
/* Keep phone numbers, emails and figures readable inside RTL text. */
.ltr { direction: ltr; unicode-bidi: isolate; display: inline-block; }
html[dir="rtl"] .footer-col a:hover { transform: translateX(-2px); }
html[dir="rtl"] .goal-arrow { transform: translateX(-8px); }
html[dir="rtl"] .goal-arrow .ms, html[dir="rtl"] .goal-arrow { scale: -1 1; }

/* Material Symbols: the font is loaded in every page's head; this is what turns the word
   inside the span into its glyph. Always left-to-right — an icon name is not prose.
   `font-size: 24px` used to arrive from Google's own stylesheet, which we no longer load —
   the icons that set no size of their own (a button's open_in_new, the search glyph) would
   otherwise drop to the inherited 16px. */
.material-symbols-outlined {
    font-family: 'Material Symbols Outlined';
    font-size: 24px;
    font-weight: normal; font-style: normal; line-height: 1;
    letter-spacing: normal; text-transform: none; white-space: nowrap;
    display: inline-block; direction: ltr; word-wrap: normal;
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    -webkit-font-feature-settings: 'liga'; font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}

html { scroll-behavior: smooth; }

body {
    font-family: 'Plus Jakarta Sans', 'IBM Plex Sans Arabic', 'Segoe UI', system-ui, Tahoma, Arial, sans-serif;
    background-color: var(--bg);
    background-image:
        linear-gradient(rgba(10, 25, 47, .03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(10, 25, 47, .03) 1px, transparent 1px);
    background-size: 22px 22px;
    color: var(--ink);
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

.container { max-width: 1240px; margin: 0 auto; padding: 0 24px; }
.section   { padding: 44px 24px 10px; }
.muted     { color: var(--muted); }
a          { color: var(--ink-2); }

/* ---------- Material Symbols helper ---------- */
.ms {
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 19px;
    line-height: 1;
    display: inline-block;
    vertical-align: -4px;
    letter-spacing: normal;
    white-space: nowrap;
    direction: ltr;
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}
.ms-fill { font-variation-settings: 'FILL' 1, 'wght' 400; }

/* ---------- Header (frosted, sticky) ---------- */
.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(255, 255, 255, .82);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
}
.header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* min-height, NOT height. The narrow-screen rule below deliberately lets this wrap onto a
       second row, but a fixed height cannot grow to hold one — so the wrapped row spilled out
       of the box, and because the header is position:sticky it spilled OVER the page beneath,
       with none of the frosted background behind it. Measured at 480px and 380px: a 73px box
       painting 127px of content. min-height keeps the desktop header at exactly 72px and lets
       it grow only when it genuinely has to. */
    min-height: 72px;
}
.logo {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 800;
    font-size: 1.3rem;
    color: var(--ink);
    text-decoration: none;
    letter-spacing: -.02em;
}
.logo-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 12px;
    background: linear-gradient(135deg, var(--amber), #f0a500);
    box-shadow: 0 2px 0 0 rgba(10, 25, 47, .18);
    font-size: 1.1rem;
}

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 20px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font: inherit;
    font-weight: 700;
    font-size: .92rem;
    text-decoration: none;
    cursor: pointer;
    transition: transform .14s ease, box-shadow .14s ease, background .14s ease, border-color .14s ease;
    white-space: nowrap;
}

.btn-primary {
    background: var(--amber);
    color: var(--ink);
    box-shadow: 0 2px 0 0 rgba(10, 25, 47, .85);
}
.btn-primary:hover  { background: #ffc82e; transform: translateY(-1px); box-shadow: 0 3px 0 0 rgba(10, 25, 47, .85); }
.btn-primary:active { transform: translateY(2px); box-shadow: none; }

.btn-navy { background: var(--ink); color: #fff; }
.btn-navy:hover { background: var(--ink-2); transform: translateY(-1px); }

.btn-whatsapp { background: var(--whatsapp-soft); color: var(--whatsapp-dark); border-color: #bfeccd; }
.btn-whatsapp:hover { background: #d3f5df; transform: translateY(-1px); }

.btn-ghost { background: var(--card); color: var(--ink); border-color: var(--line-2); }
.btn-ghost:hover { background: var(--surface-2); transform: translateY(-1px); }

.btn-danger { background: var(--red-bg); color: var(--red); border-color: #f2c2be; }
.btn-danger:hover { background: #ffc9c4; }

.btn-sm    { padding: 7px 14px; font-size: .84rem; border-radius: 10px; }
.btn-block { width: 100%; }

/* A button that cannot be pressed must not look pressable. Nothing on the site said this
   until the deal room needed a "send" that waits for a price. */
.btn:disabled, .btn[disabled] {
    opacity: .5; cursor: not-allowed; box-shadow: none; transform: none;
}
.btn:disabled:hover, .btn[disabled]:hover { transform: none; box-shadow: none; }

/* ---------- Hero ---------- */
.hero {
    padding: 84px 24px 72px;
    text-align: center;
}
.hero h1 {
    font-size: clamp(2.1rem, 4.8vw, 3.3rem);
    font-weight: 800;
    letter-spacing: -.025em;
    line-height: 1.12;
    color: var(--ink);
    max-width: 900px;
    margin: 0 auto;
}
.hero .accent { color: transparent; background: linear-gradient(120deg, var(--amber-dark), var(--amber)); -webkit-background-clip: text; background-clip: text; }
.hero-sub {
    max-width: 620px;
    margin: 20px auto 40px;
    color: var(--muted);
    font-size: 1.08rem;
}
.hero-search {
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: 720px;
    margin: 0 auto;
    background: var(--card);
    border-radius: 16px;
    padding: 8px;
    padding-inline-start: 20px;
    box-shadow: var(--ring), var(--shadow-2);
    transition: box-shadow .18s ease;
}
.hero-search:focus-within { box-shadow: 0 0 0 2px var(--ink), var(--shadow-3); }
.hero-search-icon { color: var(--ink); display: inline-flex; }
.hero-search input {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    font: inherit;
    font-size: 1.02rem;
    color: var(--ink);
    background: transparent;
    height: 48px;
}
.hero-search input::placeholder { color: #9aa4b1; }

.quick-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 22px;
    color: var(--muted);
    font-size: .85rem;
    font-weight: 600;
}
.quick-chips button {
    background: var(--card);
    border: 1px solid var(--line);
    color: var(--ink);
    padding: 8px 16px;
    border-radius: 999px;
    cursor: pointer;
    font: inherit;
    font-size: .84rem;
    font-weight: 600;
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}
.quick-chips button:hover { border-color: var(--ink); transform: translateY(-1px); box-shadow: var(--shadow-2); }

/* ---------- Trust strip ---------- */
.trust-strip {
    background: var(--card);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: 22px 24px;
}
.trust-strip-inner {
    max-width: 1240px;
    margin: 0 auto;
    display: flex;
    justify-content: space-around;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
}
.trust-item {
    display: flex;
    align-items: center;
    gap: 12px;
    font-weight: 700;
    font-size: .92rem;
    color: var(--ink);
}
.trust-item .ms { font-size: 26px; color: var(--ink); }

/* ---------- Section titles ---------- */
.section-title {
    font-size: 1.55rem;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--ink);
}
.section-sub { color: var(--muted); margin: 6px 0 26px; }

/* ---------- Guided search: bento goal cards ---------- */
.bento {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
        "g1 g1 g4"
        "g2 g3 g4"
        "g5 g6 g7";
    grid-auto-rows: 200px;
    gap: 18px;
}
.goal-card {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: linear-gradient(135deg, var(--ink), var(--ink-2));
    box-shadow: var(--shadow-2);
    cursor: pointer;
    font: inherit;
    text-align: start;
    padding: 0;
    display: flex;
    align-items: flex-end;
    transition: transform .2s ease, box-shadow .2s ease;
}
.goal-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-3); }
.goal-card.active { outline: 3px solid var(--amber); outline-offset: 2px; }
.goal-g1 { grid-area: g1; }
.goal-g2 { grid-area: g2; }
.goal-g3 { grid-area: g3; }
.goal-g4 { grid-area: g4; }
.goal-g5 { grid-area: g5; }
.goal-g6 { grid-area: g6; }
.goal-g7 { grid-area: g7; }
.goal-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    transition: transform .5s ease;
}
.goal-card:hover .goal-bg { transform: scale(1.05); }
.goal-shade {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(0, 0, 0, .82), rgba(0, 0, 0, .30) 55%, transparent);
}
.goal-content { position: relative; z-index: 2; padding: 22px; }
.goal-title { display: block; color: #fff; font-weight: 800; font-size: 1.12rem; letter-spacing: -.01em; margin-bottom: 4px; }
.goal-sub   { display: block; color: rgba(255, 255, 255, .88); font-size: .84rem; font-weight: 500; }
.goal-arrow {
    position: absolute;
    top: 20px;
    inset-inline-end: 20px;
    z-index: 2;
    color: #fff;
    opacity: 0;
    transform: translateX(8px);
    transition: opacity .25s ease, transform .25s ease;
}
.goal-card:hover .goal-arrow { opacity: 1; transform: translateX(0); }

/* ---------- Guided search level 2: project chips ---------- */
.project-picker {
    margin-top: 18px;
    background: var(--card);
    border-radius: var(--radius);
    padding: 18px 20px;
    box-shadow: var(--ring), var(--shadow-2);
}
.project-set { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.project-set-label {
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--muted);
    margin-inline-end: 6px;
}
.project-chip {
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 9px 18px;
    font: inherit;
    font-size: .88rem;
    font-weight: 600;
    color: var(--ink);
    cursor: pointer;
    transition: background .14s ease, border-color .14s ease, color .14s ease, transform .12s ease;
}
.project-chip:hover  { border-color: var(--ink); background: #fff; transform: translateY(-1px); }
.project-chip.active { background: var(--ink); border-color: var(--ink); color: #fff; }

/* ---------- Category tiles ---------- */
.tile-group { margin-bottom: 26px; }
.tile-group-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .78rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    margin: 0 0 12px;
}
.tile-group-title .ms { font-size: 18px; color: var(--line-2); }
.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    gap: 12px;
}
.tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    padding: 20px 10px;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 16px;
    font: inherit;
    cursor: pointer;
    text-align: center;
    box-shadow: var(--shadow-2);
    transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.tile:hover  { transform: translateY(-3px); box-shadow: var(--shadow-3); border-color: var(--ink); }
.tile.active { border-color: var(--amber); box-shadow: 0 0 0 3px rgba(255, 191, 0, .35); }
.tile-icon { font-size: 1.85rem; line-height: 1; }
.tile-name { font-weight: 700; font-size: .86rem; color: var(--ink); }

/* ---------- Results layout: sidebar + list ---------- */
.results-layout {
    display: grid;
    grid-template-columns: 292px minmax(0, 1fr);
    gap: 24px;
    align-items: start;
}
.filters-panel {
    position: sticky;
    top: 92px;
    background: var(--card);
    border-radius: var(--radius);
    padding: 22px;
    box-shadow: var(--ring), var(--shadow-2);
}
.filters-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 18px;
}
.filters-head h2 { font-size: 1.05rem; font-weight: 800; letter-spacing: -.01em; }
.filters-reset {
    background: none;
    border: none;
    font: inherit;
    font-size: .78rem;
    font-weight: 700;
    color: var(--muted);
    cursor: pointer;
}
.filters-reset:hover { color: var(--ink); text-decoration: underline; }

.filters-toggle { display: none; }

.filter-group { display: flex; flex-direction: column; gap: 7px; margin-bottom: 16px; }
.filter-group label,
.filter-label {
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--muted);
}
.filter-group select,
.form-field input,
.form-field select,
.form-field textarea {
    width: 100%;
    padding: 11px 12px;
    border: 1px solid var(--line-2);
    border-radius: 10px;
    font: inherit;
    font-size: .92rem;
    color: var(--ink);
    background: #fff;
    outline: none;
    transition: border-color .12s ease, box-shadow .12s ease;
}
.filter-group select:focus,
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
    border-color: var(--ink);
    box-shadow: 0 0 0 3px rgba(255, 191, 0, .30);
}

.filter-group-check {
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: 12px 0;
    margin-bottom: 16px;
    gap: 2px;
}
.filter-check {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 600;
    font-size: .88rem;
    cursor: pointer;
    padding: 5px 0;
}
.filter-check input { width: 17px; height: 17px; accent-color: var(--ink); cursor: pointer; }

/* ---------- Results meta ---------- */
.results-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 2px 2px 16px;
    font-weight: 700;
    color: var(--muted);
    font-size: .92rem;
}
.scenario-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--amber-soft);
    border: 1px solid #f0d489;
    color: #6d5000;
    padding: 5px 13px;
    border-radius: 999px;
    font-size: .8rem;
    font-weight: 700;
}
.scenario-chip button {
    border: none;
    background: none;
    cursor: pointer;
    font: inherit;
    font-weight: 800;
    color: inherit;
    padding: 0 2px;
}
.scenario-chip button:hover { color: #4d3a0c; }

/* ---------- Provider cards ---------- */
.cards { display: grid; grid-template-columns: 1fr; gap: 18px; transition: opacity .15s ease; }
.cards.loading { opacity: .45; pointer-events: none; }

.card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-2);
}

.pro-card {
    position: relative;
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-2);
    padding: 24px;
    display: grid;
    grid-template-columns: 270px minmax(0, 1fr);
    gap: 24px;
    transition: box-shadow .2s ease, transform .2s ease;
}
.pro-card:hover { box-shadow: var(--shadow-3); transform: translateY(-2px); }

.pro-distance {
    position: absolute;
    top: 16px;
    inset-inline-end: 16px;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: rgba(255, 255, 255, .85);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(10, 25, 47, .12);
    border-radius: 999px;
    padding: 5px 12px;
    font-size: .78rem;
    font-weight: 800;
    color: var(--ink);
    box-shadow: var(--shadow-2);
}
.pro-distance .ms { font-size: 15px; }

.pro-id {
    display: flex;
    flex-direction: column;
    gap: 12px;
    border-inline-end: 1px solid var(--line);
    padding-inline-end: 24px;
}
.pro-head { display: flex; gap: 13px; align-items: flex-start; }
.avatar {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--ink), var(--ink-2));
    color: #fff;
    font-weight: 800;
    font-size: 1.3rem;
    border: 2px solid var(--line);
}
.pro-name { font-size: 1.06rem; font-weight: 800; letter-spacing: -.01em; line-height: 1.3; }
.pro-name a { color: var(--ink); text-decoration: none; }
.pro-name a:hover { color: var(--amber-dark); }
.pro-line {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: .8rem;
    font-weight: 600;
    color: var(--muted);
    margin-top: 3px;
}
.pro-line .ms { font-size: 15px; }
.pro-badges { display: flex; flex-wrap: wrap; gap: 7px; }
.pro-rating { display: flex; align-items: center; gap: 6px; margin-top: auto; font-size: .95rem; }
.rate-star { color: var(--amber); font-size: 21px; }

.badge-verified,
.badge-licensed {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: .73rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 999px;
    vertical-align: middle;
}
.badge-verified { background: var(--verified-bg); color: var(--verified-fg); }
.badge-licensed { background: var(--licensed-bg); color: var(--licensed-fg); }
.badge-verified .ms, .badge-licensed .ms { font-size: 14px; }

.pro-body { display: flex; flex-direction: column; gap: 13px; }
.pro-stats { display: flex; flex-wrap: wrap; gap: 10px; }
.stat {
    display: flex;
    flex-direction: column;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 7px 13px;
    min-width: 92px;
}
.stat-label { font-size: .62rem; font-weight: 800; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.stat-value { font-size: .89rem; font-weight: 700; color: var(--ink); }

.pro-desc {
    font-size: .92rem;
    color: var(--muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.thumbs { display: flex; gap: 8px; }
.thumbs img {
    width: calc((100% - 16px) / 3);
    max-width: 170px;
    height: 92px;
    object-fit: cover;
    border-radius: 10px;
    border: 1px solid var(--line);
}

.pro-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
    display: inline-block;
    background: var(--card);
    border: 1px solid var(--line-2);
    color: var(--muted);
    font-size: .76rem;
    font-weight: 600;
    padding: 3px 11px;
    border-radius: 8px;
}
.chip-new {
    background: var(--licensed-bg);
    border-color: #bfe4c4;
    color: var(--licensed-fg);
    border-radius: 999px;
    font-weight: 700;
}
.chips { display: flex; flex-wrap: wrap; gap: 6px; }

.pro-actions { display: flex; gap: 10px; margin-top: auto; justify-content: flex-end; flex-wrap: wrap; }
.pro-actions .btn { padding: 10px 18px; font-size: .86rem; }

/* ---- "Select for a request" — gathering several professionals into one send ----
   A real checkbox dressed as a chip: keyboards and screen readers get the checkbox,
   everyone else sees a button that fills in when it is on. The state itself lives in
   home.js (`picked`), because these cards are rebuilt on every search. */
.pro-pick {
    display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 10px 16px; font-size: .86rem; font-weight: 700;
    border: 1px dashed var(--line-2); border-radius: var(--radius-box);
    color: var(--ink-2); background: var(--card); user-select: none;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.pro-pick:hover { border-color: var(--amber); color: var(--amber-dark); }
.pro-pick .ms { font-size: 1.15rem; }
.pro-pick input {
    /* The checkbox stays real and focusable; the chip is its visible face. */
    position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none;
}
.pro-pick:has(input:focus-visible) { outline: 2px solid var(--amber); outline-offset: 2px; }
.pro-pick.on {
    background: var(--amber-soft); border-style: solid;
    border-color: var(--amber); color: var(--amber-dark);
}

/* The bar that appears once anything is picked. Fixed, so the send button is in reach
   however far down the results the last tick happened. */
.pick-bar {
    position: fixed; bottom: 0; inset-inline: 0; z-index: 60;
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    padding: 12px clamp(16px, 4vw, 40px);
    background: var(--ink); color: #fff;
    box-shadow: 0 -6px 24px rgba(10, 25, 47, .25);
}
.pick-bar-n { font-weight: 800; white-space: nowrap; }
.pick-bar-names {
    flex: 1 1 200px; min-width: 0; font-size: .84rem; color: rgba(255, 255, 255, .75);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pick-bar-actions { display: flex; gap: 10px; flex-wrap: wrap; }
/* The site's .btn-ghost is white-on-white against this dark bar — repaint all three of
   its faces, not just the text, or it renders as a blank white pill. */
.pick-bar .btn-ghost {
    background: transparent; color: #fff; border-color: rgba(255, 255, 255, .4);
}
.pick-bar .btn-ghost:hover { background: rgba(255, 255, 255, .12); color: #fff; }

/* The tip shown when arriving from "send the same request to more professionals". */
.pick-hint {
    display: flex; align-items: center; gap: 10px;
    margin: 0 0 18px; padding: 12px 16px;
    background: var(--amber-soft); border: 1px solid var(--amber);
    border-radius: var(--radius-box); color: var(--ink); line-height: 1.7;
}
.pick-hint .ms { color: var(--amber-dark); flex: none; }

/* ---------- Empty state ---------- */
.empty { text-align: center; padding: 70px 20px; }
.empty-icon { font-size: 2.6rem; margin-bottom: 10px; }
.empty h3 { color: var(--ink); margin-bottom: 6px; font-weight: 800; }

/* ---------- Company profile ---------- */
.profile-hero {
    display: flex;
    gap: 26px;
    align-items: flex-start;
    margin-bottom: 34px;
}
.profile-avatar {
    flex: none;
    width: 132px;
    height: 132px;
    border-radius: 24px;
    background:
        linear-gradient(rgba(10, 25, 47, .04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(10, 25, 47, .04) 1px, transparent 1px),
        #fff;
    background-size: 14px 14px;
    box-shadow: var(--ring), var(--shadow-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3.4rem;
    font-weight: 800;
    color: var(--ink);
}
.profile-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; }
.profile-name {
    font-size: clamp(1.6rem, 3.4vw, 2.4rem);
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--ink);
    line-height: 1.15;
}
.profile-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px 16px;
    color: var(--muted);
    font-size: .93rem;
    font-weight: 600;
}
.profile-meta .ms { font-size: 17px; vertical-align: -3px; }
.meta-pill {
    background: var(--surface-2);
    border: 1px solid var(--line);
    padding: 4px 13px;
    border-radius: 9px;
    font-weight: 700;
    color: var(--ink-2);
    font-size: .84rem;
}
.profile-rating { display: inline-flex; align-items: center; gap: 5px; color: var(--ink); font-weight: 800; }

.mobile-actions { display: none; gap: 10px; margin: 0 0 22px; }
.mobile-actions .btn { flex: 1; }

.profile-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: 26px;
    align-items: start;
}
.profile-main { display: flex; flex-direction: column; gap: 36px; }
.profile-block h2 {
    font-size: 1.25rem;
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--ink);
    margin-bottom: 14px;
}
.profile-about { font-size: 1.02rem; color: var(--ink-3); line-height: 1.7; }

.service-cards { display: flex; flex-wrap: wrap; gap: 10px; }
.service-card {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 12px 17px;
    font-size: .9rem;
    font-weight: 700;
    color: var(--ink);
    box-shadow: var(--shadow-2);
}
.service-card .service-ic { font-size: 1.3rem; line-height: 1; }

.work-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 190px;
    gap: 14px;
}
.work-item {
    position: relative;
    overflow: hidden;
    border-radius: 16px;
    box-shadow: var(--shadow-2);
    border: 1px solid var(--line);
    display: block;
}
.work-item:first-child { grid-column: span 2; grid-row: span 2; }
.work-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .5s ease;
}
.work-item:hover img { transform: scale(1.05); }
.work-caption {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: flex-end;
    padding: 16px;
    background: linear-gradient(to top, rgba(0, 0, 0, .65), transparent 45%);
    color: #fff;
    font-size: .85rem;
    font-weight: 700;
    opacity: 0;
    transition: opacity .25s ease;
}
.work-item:hover .work-caption { opacity: 1; }

.contact-card {
    position: sticky;
    top: 92px;
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-2);
    padding: 24px;
}
.contact-card h3 { font-size: 1.05rem; font-weight: 800; margin-bottom: 18px; letter-spacing: -.01em; }
.contact-cta-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 12px 0 20px; }
.contact-divider { height: 1px; background: var(--line); margin: 0 0 18px; }
.contact-rows { display: flex; flex-direction: column; gap: 15px; margin-bottom: 20px; }
.contact-row { display: flex; gap: 11px; align-items: flex-start; font-size: .92rem; word-break: break-word; }
.contact-row .ms { color: var(--muted); font-size: 20px; margin-top: 1px; }
.contact-label {
    display: block;
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--muted);
    margin-bottom: 2px;
}

.map-preview {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 128px;
    border-radius: 14px;
    border: 1px solid var(--line);
    overflow: hidden;
    background:
        linear-gradient(rgba(10, 25, 47, .06) 1px, transparent 1px),
        linear-gradient(90deg, rgba(10, 25, 47, .06) 1px, transparent 1px),
        #f4f6f8;
    background-size: 18px 18px;
    text-decoration: none;
    transition: box-shadow .18s ease;
}
.map-preview:hover { box-shadow: var(--shadow-3); }
.map-pin { font-size: 40px; color: var(--red); font-variation-settings: 'FILL' 1; }
.map-open {
    position: absolute;
    bottom: 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 5px 13px;
    font-size: .78rem;
    font-weight: 700;
    color: var(--ink);
    box-shadow: var(--shadow-2);
}
.map-open .ms { font-size: 14px; }

.similar-wrap { margin-top: 48px; padding-top: 34px; border-top: 1px solid var(--line); }
.similar-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 16px;
}
.similar-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-2);
    padding: 22px 18px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    transition: transform .16s ease, box-shadow .16s ease;
}
.similar-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-3); }
.similar-card .avatar { width: 60px; height: 60px; font-size: 1.4rem; margin-bottom: 4px; }
.similar-name { font-size: .98rem; font-weight: 800; color: var(--ink); }
.similar-cat { font-size: .8rem; color: var(--muted); font-weight: 600; }
.similar-card .btn { margin-top: 10px; width: 100%; }

/* ---------- Admin & forms ---------- */
.notice {
    padding: 13px 18px;
    border-radius: 14px;
    margin-bottom: 18px;
    font-size: .92rem;
    font-weight: 600;
    background: var(--card);
    box-shadow: var(--ring), var(--shadow-2);
}
.notice-warn { background: var(--amber-soft); border: 1px solid #f0d489; color: #6d5000; box-shadow: none; }
.notice-ok   { background: var(--licensed-bg); border: 1px solid #bfe4c4; color: #1d5f24; box-shadow: none; }
.notice-err  { background: var(--red-bg); border: 1px solid #f2c2be; color: #93000a; box-shadow: none; }

.form-card { padding: 26px; margin-bottom: 24px; }
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 15px;
    margin-bottom: 15px;
}
.form-field { display: flex; flex-direction: column; gap: 7px; margin-bottom: 15px; }
.form-grid .form-field { margin-bottom: 0; }
.form-field > label { font-size: .82rem; font-weight: 700; color: var(--ink-2); }
.form-field-check { justify-content: flex-end; gap: 4px; }
.form-field-check label { display: flex; align-items: center; gap: 8px; font-weight: 600; cursor: pointer; font-size: .9rem; }
.form-field-check input { width: 16px; height: 16px; accent-color: var(--ink); }
.form-field textarea { resize: vertical; }
.field-hint { font-size: .82rem; color: var(--muted); margin: -4px 0 16px; }

.check-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 8px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 12px;
}
.check-item {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .9rem;
    font-weight: 600;
    cursor: pointer;
    padding: 5px 7px;
    border-radius: 8px;
}
.check-item:hover { background: #fff; }
.check-item input { accent-color: var(--ink); }

.table-wrap { overflow-x: auto; }
.admin-table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.admin-table th {
    text-align: start;
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--muted);
    padding: 10px 12px;
    border-bottom: 2px solid var(--line);
}
.admin-table td { padding: 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.admin-table tr:hover td { background: var(--surface-2); }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; align-items: center; }

/* ---------- Photos admin ---------- */
.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(175px, 1fr));
    gap: 14px;
}
.gallery figure { display: flex; flex-direction: column; gap: 7px; }
.gallery a { display: block; }
.gallery img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 12px;
    border: 1px solid var(--line);
    transition: transform .16s ease, box-shadow .16s ease;
}
.gallery a:hover img { transform: scale(1.02); box-shadow: var(--shadow-3); }
.gallery figcaption { font-size: .78rem; color: var(--muted); font-weight: 600; }
.photo-item form { margin-top: 2px; }
.upload-form input[type="file"] { padding: 9px; background: var(--surface-2); }

/* ---------- Setup page ---------- */
.setup-wrap { display: flex; justify-content: center; padding: 70px 20px; }
.setup-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-3);
    padding: 42px;
    max-width: 580px;
    width: 100%;
    text-align: center;
}
.setup-icon { font-size: 2.6rem; margin-bottom: 8px; }
.setup-card h1 { color: var(--ink); letter-spacing: -.02em; margin-bottom: 6px; font-weight: 800; }
.setup-list {
    text-align: start;
    margin: 22px 0;
    padding: 16px 20px;
    padding-inline-start: 38px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 14px;
    line-height: 2;
    font-size: .92rem;
    font-weight: 500;
}
.setup-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* ---------- Footer ---------- */
.site-footer {
    margin-top: 64px;
    background: var(--card);
    border-top: 1px solid var(--line);
    padding: 44px 24px 40px;
}
.footer-grid {
    max-width: 1240px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    gap: 30px;
}
.footer-brand { font-weight: 800; font-size: 1.15rem; color: var(--ink); letter-spacing: -.01em; margin-bottom: 8px; }
.footer-tag { color: var(--muted); font-size: .88rem; max-width: 320px; }
.footer-col { display: flex; flex-direction: column; gap: 10px; }
.footer-col a {
    color: var(--muted);
    text-decoration: none;
    font-size: .9rem;
    font-weight: 600;
    transition: color .14s ease, transform .14s ease;
}
.footer-col a:hover { color: var(--amber-dark); transform: translateX(2px); }
.footer-col-title {
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ink-3);
    margin-bottom: 2px;
}

/* Legacy footer markup (admin / photos pages) */
.site-footer p { text-align: center; color: var(--muted); font-size: .9rem; }
.site-footer p strong { color: var(--ink); }
.site-footer .muted { font-size: .82rem; margin-top: 4px; }

/* ---------- Legacy aliases still used by JS / older pages ---------- */
.distance-tag { color: var(--amber-dark); font-weight: 700; }
.stars { color: var(--amber); letter-spacing: 2px; }

/* ---------- Responsive ---------- */
@media (max-width: 1020px) {
    .results-layout { grid-template-columns: 1fr; }
    .filters-panel { position: static; display: none; }
    .filters-panel.open { display: block; }
    .filters-toggle {
        display: inline-flex;
        margin-bottom: 14px;
    }
    .profile-grid { grid-template-columns: 1fr; }
    .contact-card { position: static; }
    .mobile-actions { display: flex; }
}
@media (max-width: 900px) {
    .bento {
        grid-template-columns: repeat(2, 1fr);
        grid-template-areas:
            "g1 g1"
            "g2 g3"
            "g4 g5"
            "g6 g7";
        grid-auto-rows: 165px;
    }
    .pro-card { grid-template-columns: 1fr; }
    .pro-id { border-inline-end: none; border-bottom: 1px solid var(--line); padding-inline-end: 0; padding-bottom: 18px; }
    .pro-actions { justify-content: stretch; }
    .pro-actions .btn { flex: 1; }
}
@media (max-width: 640px) {
    /* the nav has 3 buttons since the calculator link — let the header wrap.
       The padding is what stops a wrapped header looking cramped: with two rows the 72px
       min-height is already exceeded, so the rows would otherwise sit hard against the
       frosted edge. It is inside this query on purpose — a desktop header must stay exactly
       72px tall, and padding here would make it 92. */
    .header-inner { flex-wrap: wrap; row-gap: 6px; padding-block: 10px; }
    .site-header nav { flex-wrap: wrap; }

    /* AND IT STOPS BEING PINNED THE MOMENT IT STOPS BEING ONE ROW.
       A sticky header has to earn the screen it keeps. On a desktop that is 73px of a tall
       window for a bar that is always in reach. Here it wraps to two rows and then three —
       103px, then 148px, which is 18% of a 380px phone held permanently — and what it holds
       is a language toggle, one back link, the account chip and Sign out. Those are exit
       routes, not tools anybody needs while reading a page: navigation on this site lives on
       the account page, and every page's real actions are in its content. So below the width
       where it wraps, the header scrolls away like anything else and gives the page back.
       Nothing becomes unreachable — it is one scroll-to-top away, which is the gesture
       phones already have. */
    .site-header { position: static; }
    .hero { padding: 56px 18px 52px; }
    .hero-search { flex-wrap: nowrap; padding-left: 14px; }
    .hero-search .btn { padding: 11px 16px; }
    .section { padding: 34px 14px 6px; }
    .tiles { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); }
    .work-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 150px; }
    .profile-hero { flex-direction: column; }
    .profile-avatar { width: 96px; height: 96px; font-size: 2.4rem; border-radius: 18px; }
    .footer-grid { grid-template-columns: 1fr; }
    .trust-strip-inner { flex-direction: column; align-items: flex-start; gap: 12px; }
    .thumbs img { height: 74px; }
}

/* ==========================================================
   Construction cost calculator (calculator.php)
   ========================================================== */
.calc-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.calc-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--card);
    border-radius: 999px;
    padding: 7px 14px;
    font-size: .78rem;
    font-weight: 700;
    color: var(--ink-2);
    box-shadow: var(--ring), var(--shadow-2);
    white-space: nowrap;
}
.calc-pill .ms { font-size: 15px; color: var(--amber-dark); }

.calc-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 16px 0 8px; }
.calc-tab {
    padding: 10px 18px;
    border-radius: 999px;
    background: var(--card);
    box-shadow: var(--ring);
    font-weight: 700;
    font-size: .92rem;
    color: var(--ink-2);
    text-decoration: none;
    transition: background .14s ease, color .14s ease, box-shadow .14s ease;
}
.calc-tab:hover { box-shadow: var(--ring), var(--shadow-2); }
.calc-tab.active { background: var(--ink); color: #fff; box-shadow: 0 2px 0 var(--amber); }
.calc-mode-desc { color: var(--muted); font-size: .9rem; margin: 0 4px 6px; }

.calc-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 22px;
    align-items: start;
    margin-top: 12px;
}
.calc-form .form-card { margin-bottom: 16px; }
.calc-sec { font-size: 1.05rem; font-weight: 800; color: var(--ink); margin: 0 0 14px; }

/* segmented radio pills (building type, soil) */
.seg { display: flex; flex-wrap: wrap; gap: 8px; }
/* the real radio is hidden but must not take space — the shared
   ".form-field input { width:100% }" rule would otherwise stretch it
   across the page and cause horizontal scrolling */
.seg input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.seg label {
    padding: 9px 14px;
    border: 1.5px solid var(--line-2);
    border-radius: 10px;
    cursor: pointer;
    font-weight: 600;
    font-size: .88rem;
    background: #fff;
    color: var(--ink-2);
    transition: all .13s ease;
}
.seg input:checked + label { background: var(--ink); color: #fff; border-color: var(--ink); }
.seg input:focus-visible + label { outline: 2px solid var(--amber); outline-offset: 2px; }

/* finishing level / renovation scope cards */
.level-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
}
.level-card input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.level-card label {
    display: flex;
    flex-direction: column;
    gap: 3px;
    height: 100%;
    padding: 12px 13px;
    border: 1.5px solid var(--line);
    border-radius: 12px;
    cursor: pointer;
    background: #fff;
    transition: all .13s ease;
}
.level-card label:hover { border-color: var(--line-2); box-shadow: var(--shadow-2); }
.level-card input:checked + label { border-color: var(--amber); background: var(--amber-soft); }
.level-name { font-weight: 800; font-size: .92rem; color: var(--ink); }
.level-desc { font-size: .76rem; color: var(--muted); line-height: 1.45; }
.level-price { font-size: .8rem; font-weight: 700; color: var(--amber-dark); margin-top: 5px; }

.dims-pair { display: flex; align-items: center; gap: 8px; }
.dims-pair input { width: 100%; }
.dims-x { color: var(--muted); font-weight: 700; }

.rate-reset {
    border: 0;
    background: var(--amber-soft);
    color: var(--amber-dark);
    font: inherit;
    font-size: .74rem;
    font-weight: 700;
    padding: 2px 9px;
    border-radius: 999px;
    cursor: pointer;
    margin-inline-start: 8px;
}

/* sliders (land area, build ratio) — slider + synced number field */
.slider-pair { display: flex; align-items: center; gap: 14px; }
.slider-pair input[type="range"] {
    flex: 1;
    padding: 0;
    border: 0;
    background: transparent;
    accent-color: var(--amber);
    cursor: pointer;
}
.slider-pair input[type="number"] { width: 96px; text-align: center; font-weight: 700; }

.check-inline {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700 !important;
    font-size: .9rem !important;
    color: var(--ink-2);
    cursor: pointer;
}
.check-inline input { width: 17px; height: 17px; accent-color: var(--ink); }
.field-sub { font-size: .78rem; font-weight: 700; color: var(--muted); display: block; margin: 8px 0 6px; }

/* extras — card grid with live "+ cost" per card */
.extras-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
    gap: 10px;
}
.extra-card {
    border: 1.5px solid var(--line);
    border-radius: 12px;
    background: #fff;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transition: all .14s ease;
}
.extra-card:hover { border-color: var(--line-2); box-shadow: var(--shadow-2); }
.extra-card.on { border-color: var(--amber); background: var(--amber-soft); }
.extra-check {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700;
    font-size: .9rem;
    cursor: pointer;
    color: var(--ink);
}
.extra-check input { width: 17px; height: 17px; accent-color: var(--ink); }
.extra-check .ms { font-size: 19px; color: var(--ink-3); }
.extra-card.on .extra-check .ms { color: var(--amber-dark); }
.extra-cost { font-size: .8rem; font-weight: 800; color: var(--muted); }
.extra-cost.on { color: var(--amber-dark); }
.extra-field { width: 100%; margin-bottom: 0 !important; }

/* live results panel (sticky column = panel + note under it) */
.calc-side { position: sticky; top: 92px; }
.calc-results {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-2);
    overflow: hidden;
}
.calc-empty { text-align: center; color: var(--muted); padding: 44px 20px; }
.calc-empty .ms { color: var(--line-2); }
.calc-empty p { margin-top: 10px; font-weight: 600; font-size: .92rem; }

/* dark total header (the Stitch "التكلفة التقديرية الإجمالية" block) */
.calc-hero { background: var(--ink); color: #fff; padding: 20px 22px 18px; }
.calc-hero-label { font-size: .78rem; font-weight: 800; color: var(--amber); margin-bottom: 6px; }
.calc-hero-range { font-size: 1.65rem; font-weight: 800; line-height: 1.2; }
.calc-hero-cur { font-size: .76rem; font-weight: 600; color: rgba(255, 255, 255, .72); margin-top: 4px; }

.calc-inner { padding: 16px 22px 22px; }
.calc-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 2px 0 4px; }
.calc-stat { background: var(--surface-2); border-radius: 12px; padding: 10px 12px; text-align: center; }
.calc-stat span { font-size: .7rem; font-weight: 700; color: var(--muted); display: block; margin-bottom: 2px; }
.calc-stat b { font-size: .95rem; color: var(--ink); }
.calc-h3 {
    font-size: .88rem;
    font-weight: 800;
    color: var(--ink);
    margin: 16px 0 10px;
    padding-bottom: 7px;
    border-bottom: 1px solid var(--line);
}

.bar-row { margin-bottom: 10px; }
.bar-top { display: flex; justify-content: space-between; gap: 10px; font-size: .78rem; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }
.bar-amt { font-weight: 800; color: var(--ink); white-space: nowrap; }
.bar-track { height: 8px; background: var(--surface-3); border-radius: 99px; overflow: hidden; }
.bar-fill {
    height: 100%;
    background: var(--amber);
    border-radius: 99px;
    transition: width .5s ease;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}
.bar-fill.c1 { background: var(--ink); }
.bar-fill.c3 { background: #6d8d52; }
.bar-fill.c4 { background: var(--ink-3); }

/* duration info box */
.calc-duration {
    display: flex;
    align-items: center;
    gap: 12px;
    background: #e7edf7;
    border-radius: 12px;
    padding: 12px 14px;
    margin-top: 14px;
}
.calc-duration .ms { color: var(--ink); font-size: 22px; }
.calc-duration span { display: block; font-size: .72rem; font-weight: 700; color: var(--muted); }
.calc-duration b { font-size: .92rem; color: var(--ink); }

/* CTA: navy button with amber text (Stitch style) */
.btn-cta { background: var(--ink); color: var(--amber); font-weight: 800; }
.btn-cta:hover { background: #13284a; color: var(--amber); }
.btn-cta .ms { font-size: 18px; }

.calc-side-note { margin: 14px 0 0; font-size: .8rem; line-height: 1.7; }

.calc-line {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    font-size: .84rem;
    font-weight: 600;
    color: var(--ink-2);
    padding: 7px 0;
    border-bottom: 1px dashed var(--line);
}
.calc-actions { margin-top: 16px; display: flex; flex-direction: column; gap: 9px; }
.calc-cta-sub { font-size: .75rem; color: var(--muted); margin: -3px 0 0; text-align: center; }
.calc-mini-disc { font-size: .72rem; color: var(--muted); margin-top: 12px; }

/* reference tables / checklist / FAQ */
.calc-tables {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 18px;
    margin-top: 28px;
}
.calc-tables .form-card { margin-bottom: 0; }
.check-card { margin-top: 18px; }
.calc-check { padding-inline-start: 22px; line-height: 1.9; font-size: .94rem; color: var(--ink-2); }
.calc-check li { margin-bottom: 4px; }

.faq-wrap { margin-top: 28px; }
.faq-item {
    background: var(--card);
    border-radius: 14px;
    box-shadow: var(--ring), var(--shadow-2);
    margin-bottom: 10px;
    overflow: hidden;
}
.faq-item summary {
    padding: 15px 20px;
    font-weight: 700;
    font-size: .96rem;
    color: var(--ink);
    cursor: pointer;
    list-style: none;
    display: flex;
    justify-content: space-between;
    gap: 12px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: '+'; font-weight: 800; color: var(--amber-dark); }
.faq-item[open] summary::after { content: '−'; }
.faq-item p { padding: 0 20px 16px; color: var(--ink-2); font-size: .92rem; line-height: 1.75; }
.calc-disclaimer { margin-top: 26px; font-weight: 500; line-height: 1.8; }

/* mobile sticky mini-total */
.calc-mini {
    display: none;
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 60;
    background: var(--ink);
    color: #fff;
    padding: 10px 18px;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    box-shadow: 0 -6px 18px rgba(10, 25, 47, .25);
}
.calc-mini-label { display: block; font-size: .66rem; font-weight: 700; color: rgba(255, 255, 255, .65); }
.calc-mini b { font-size: 1.05rem; font-weight: 800; }

/* print header line (hidden on screen) */
.print-head { display: none; font-size: .9rem; line-height: 1.7; margin-bottom: 14px; }

@media (max-width: 1020px) {
    /* minmax(0, 1fr), not 1fr — the same trap the two-column rule above already avoids for
       its first track, and then walked straight back into here. A bare `fr` has a min-content
       floor, so on a small phone the single column was held open by the widest field group
       inside it and the page scrolled sideways (measured: 6px at 360, 46px at 320). */
    .calc-layout { grid-template-columns: minmax(0, 1fr); }
    .calc-side { position: static; }
    .calc-mini:not([hidden]) { display: flex; }
    body.calc-page { padding-bottom: 64px; }
}

@media print {
    body.calc-page .site-header,
    body.calc-page .site-footer,
    body.calc-page .calc-head .calc-pill,
    body.calc-page .calc-tabs,
    body.calc-page .calc-mode-desc,
    body.calc-page .calc-form,
    body.calc-page .calc-actions,
    body.calc-page .calc-tables,
    body.calc-page .check-card,
    body.calc-page .faq-wrap,
    body.calc-page .calc-mini { display: none !important; }
    body.calc-page { background: #fff; }
    body.calc-page .calc-layout { display: block; }
    body.calc-page .calc-side { position: static; }
    body.calc-page .calc-results {
        box-shadow: none;
        border: 1px solid #bbb;
        border-radius: 8px;
    }
    body.calc-page .print-head { display: block; padding: 16px 22px 0; }
    body.calc-page .calc-hero {
        print-color-adjust: exact;
        -webkit-print-color-adjust: exact;
        border-bottom: 2px solid #bbb;
    }
    body.calc-page .calc-disclaimer { margin-top: 14px; border: 1px solid #ddd; }
}

/* ============================================================
   Accounts: login / register / profile
   ============================================================ */

/* Header chip for the signed-in user */
/* position:relative so the count can hang off its corner — see .chip-dot. */
.user-chip { max-width: 210px; position: relative; }
/* How many things are waiting. On the chip rather than beside it, because the chip is the
   door to the list: the number and the way to act on it are one control.
   inset-inline-end, not right — in Arabic the header runs the other way and the badge has
   to follow the corner of the chip, not stay on a fixed side of the screen.
   The ring is the header's own white, so the badge reads as a disc sitting ON the bar
   rather than a red smudge touching the chip's edge. Hard-coded rather than var(--card)
   because it is matching .site-header's rgba(255,255,255,.82), not a card. */
.chip-dot {
    position: absolute;
    top: -7px;
    inset-inline-end: -7px;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    box-sizing: border-box;
    border-radius: 999px;
    border: 2px solid #fff;
    background: var(--red);
    color: #fff;
    font-size: .68rem;
    font-weight: 800;
    line-height: 16px;
    text-align: center;
    pointer-events: none;   /* the chip underneath stays one click target */
}
.user-chip .chip-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--ink);
    color: var(--amber);
    font-size: .72rem;
    font-weight: 800;
    flex: 0 0 auto;
}
.user-chip .chip-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Split-screen login / register (design ported from the Stitch login mockups):
   a big architectural photo panel with trust badges + a clean form panel. */
.auth-body  { background: var(--bg); }
.auth-split { display: flex; min-height: 100vh; }

.auth-photo {
    flex: 1.35;
    position: relative;
    display: flex;
    align-items: flex-end;
    padding: 48px;
    background: var(--ink) url('../img/auth/side-desktop.jpg') center / cover no-repeat;
    overflow: hidden;
}
/* Navy overlay + subtle blueprint grid on top of the photo */
.auth-photo::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px),
        linear-gradient(180deg, rgba(10, 25, 47, .35), rgba(10, 25, 47, .74));
    background-size: 20px 20px, 20px 20px, 100% 100%;
}
.auth-photo-content { position: relative; z-index: 1; max-width: 560px; color: #fff; }
.auth-photo-content h1 {
    font-size: clamp(1.7rem, 3.2vw, 2.7rem);
    font-weight: 800;
    letter-spacing: -.02em;
    line-height: 1.22;
    margin: 0 0 14px;
    color: #fff;
}
.auth-photo-content p { margin: 0; color: rgba(255, 255, 255, .88); font-size: 1.05rem; line-height: 1.7; }
.trust-pills { display: flex; gap: 12px; margin-top: 26px; flex-wrap: wrap; }
.trust-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-radius: 999px;
    background: rgba(10, 25, 47, .35);
    border: 1px solid rgba(255, 255, 255, .18);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    color: #fff;
    font-size: .85rem;
    font-weight: 700;
}
.trust-pill .ms { font-size: 19px; }
.tp-amber { color: var(--amber); }
.tp-green { color: #aed18f; }

.auth-panel {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--card);
    padding: 40px 28px;
}
.auth-panel-inner { width: 100%; max-width: 430px; }
.auth-panel-wide .auth-panel-inner { max-width: 560px; }
.auth-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 38px;
}
.auth-h    { font-size: 1.55rem; font-weight: 800; letter-spacing: -.02em; margin: 0 0 6px; }
.auth-lead { color: var(--muted); margin: 0 0 22px; }
.auth-lead a { color: var(--ink); font-weight: 700; }
.auth-form .form-field { margin-bottom: 14px; }

/* Inputs with a leading icon (and optional trailing eye button) */
.a-field { position: relative; display: flex; align-items: center; }
/* Physical sides, not logical: .ms carries `direction: ltr` for the ligature, so an
   inset-inline-start on the glyph resolves to the left even in Arabic — which parked both
   field icons on the left while the input reserved its 46px on the right. */
.a-field > .ms {
    position: absolute;
    left: 14px;
    color: var(--ink-3);
    pointer-events: none;
    font-size: 21px;
}
html[dir="rtl"] .a-field > .ms { left: auto; right: 14px; }
/* Physical, and mirrored off the PAGE, because the glyph above is. Logical padding here
   resolves against the input's own direction, and `class="ltr"` on the username, telephone
   and email boxes makes that direction LTR even on an Arabic page — which reserved the 46px
   on the left while the icon sat on the right. Icon and gutter must answer to the same
   thing, and the glyph cannot answer to anything but the page. */
.a-field input {
    width: 100%;
    height: 54px;
    padding-left: 46px;
    padding-right: 14px;
    border: 1px solid var(--line-2);
    border-radius: 15px;
    background: var(--card);
    font: inherit;
    color: var(--ink);
    outline: none;
    transition: box-shadow .15s, border-color .15s;
}
html[dir="rtl"] .a-field input { padding-left: 14px; padding-right: 46px; }
.a-field input:focus { border-color: var(--amber); box-shadow: 0 0 0 2px var(--amber); }
/* A password box has a glyph on one side and the eye button on the other, so it reserves
   46px both ways and needs no mirror — but it must out-specify the rule above, which would
   otherwise win on an Arabic page and take the eye button's space back. */
.a-field input.has-toggle,
html[dir="rtl"] .a-field input.has-toggle { padding-left: 46px; padding-right: 46px; }
.pw-toggle {
    position: absolute;
    inset-inline-end: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 10px;
    background: none;
    color: var(--ink-3);
    cursor: pointer;
}
.pw-toggle:hover { color: var(--ink); background: var(--surface-2); }
.pw-toggle .ms { font-size: 21px; }

.auth-remember { margin: 2px 0 16px; }
.btn-auth { height: 54px; border-radius: 15px; font-size: 1rem; font-weight: 800; }
.btn-auth .ms { font-size: 20px; }
.auth-secure {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin: 30px 0 0;
    color: var(--muted);
    font-size: .8rem;
}
.auth-secure .ms { font-size: 15px; }

/* Small screens: the photo becomes a top banner and the form card
   slides over it with rounded corners (like the mobile mockup). */
@media (max-width: 920px) {
    .auth-split { flex-direction: column; }
    .auth-photo {
        flex: none;
        min-height: 30vh;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 34px 24px 58px;
        background-image: url('../img/auth/side-mobile.jpg');
    }
    .auth-photo-content p,
    .trust-pills { display: none; }
    .auth-panel {
        border-radius: 24px 24px 0 0;
        margin-top: -28px;
        position: relative;
        z-index: 2;
        align-items: flex-start;
        padding-top: 34px;
        box-shadow: 0 -6px 24px rgba(10, 25, 47, .10);
    }
    .auth-top { margin-bottom: 26px; }
}

/* Account-type picker on the registration page */
.role-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 560px) { .role-pick { grid-template-columns: 1fr; } }
.role-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px 16px;
    border: 2px solid var(--line);
    border-radius: 14px;
    cursor: pointer;
    background: var(--card);
    transition: border-color .15s, background .15s;
}
/* Keep hidden radios 1×1px — a full-width input here breaks the page layout */
.role-card input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}
.role-card:has(input:checked) { border-color: var(--amber); background: var(--amber-soft); }
.role-card:hover { border-color: var(--line-2); }
.role-ic   { font-size: 1.3rem; }
.role-name { font-weight: 800; }
.role-desc { color: var(--muted); font-size: .84rem; }

/* Profile page */
.prof-head {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 22px;
}
.prof-tut {
    margin-inline-start: auto; flex: none;
    display: inline-flex; align-items: center; gap: 8px;
    min-height: 52px; padding: 0 24px; font-size: 1rem;
}
.prof-tut .material-symbols-outlined { font-size: 1.5rem; }
.prof-head { flex-wrap: wrap; }
@media (max-width: 640px) {
    .prof-tut { flex: 1 1 100%; justify-content: center; margin-inline-start: 0; }
}
.prof-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 58px;
    height: 58px;
    border-radius: 18px;
    background: var(--ink);
    color: var(--amber);
    font-size: 1.5rem;
    font-weight: 800;
    flex: 0 0 auto;
}
.prof-hello { font-size: 1.5rem; letter-spacing: -.02em; margin: 0 0 4px; }
.role-badge {
    display: inline-block;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 700;
    background: var(--surface-2);
    border: 1px solid var(--line-2);
    color: var(--ink-2);
}
.role-badge.role-admin      { background: var(--amber-soft); border-color: var(--amber); color: var(--amber-dark); }
.role-badge.role-contractor { background: #e7edf7; border-color: #b8c6de; color: var(--ink); }
.prof-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    align-items: start;
}
@media (max-width: 860px) { .prof-grid { grid-template-columns: 1fr; } }
.prof-admin-links { display: flex; gap: 10px; flex-wrap: wrap; }

/* "My work" — the two doors out of the account page: projects and requests.
   They are the only navigation into the workspace, so they are big enough to
   be obvious on a phone and carry the number of rows waiting inside. */

/* The card's heading, with room for a control opposite it. `align-items: flex-start` so a
   two-line sub-heading does not drag the button down the card with it. */
.prof-work-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
}
.prof-work-head > div:first-child { flex: 1 1 260px; min-width: 0; }

/* DEVELOPMENT ONLY — the link to the testing dashboard, drawn for the user1 account alone.
   It goes when test01/ goes (project documentation §14b, row 6b). */
.prof-qa {
    flex: none; display: inline-flex; align-items: center; gap: 6px;
    border-style: dashed;               /* says "this is a tool, not part of the site" */
}
.prof-qa .material-symbols-outlined { font-size: 1.15rem; }

.prof-links {
    display: grid;
    gap: 14px;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.prof-link {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    text-decoration: none;
    color: inherit;
    transition: box-shadow .15s, transform .15s, border-color .15s;
}
.prof-link:hover {
    border-color: var(--amber);
    box-shadow: var(--shadow-2);
    transform: translateY(-2px);
}
.prof-link-ic {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 14px;
    background: var(--card);
    border: 1px solid var(--line);
    font-size: 1.25rem;
}
/* ---- Notifications, on the account page ----
   A list of jobs, not a feed of news: every row is a link to the place the work is, and it
   is gone from the list the moment that work is done. So the row is styled as a target —
   the whole line is the hit area, not just the words. */
.note-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.note-line {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 14px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    /* The severity edge. border-inline-start, not border-left — in Arabic the list runs the
       other way and the stripe has to stay at the start of the line, not on the left of the
       screen. */
    border-inline-start: 3px solid var(--line-2);
    border-radius: var(--radius-box);
    color: var(--ink); text-decoration: none;
    transition: background .15s, border-color .15s, transform .15s;
}
.note-line:hover { background: var(--card); border-color: var(--line-2); transform: translateX(0); }
.note-row.is-action  .note-line { border-inline-start-color: var(--amber); }
.note-row.is-warning .note-line { border-inline-start-color: var(--red); }
.note-row.is-info    .note-line { border-inline-start-color: var(--line-2); }
.note-ic { font-size: 20px; color: var(--muted); flex: 0 0 auto; }
.note-row.is-warning .note-ic { color: var(--red); }
.note-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.note-txt strong { font-size: .95rem; color: var(--ink); overflow-wrap: anywhere; }
.note-txt span   { font-size: .82rem; color: var(--muted); line-height: 1.5; }
/* Same round count the workspace lists use, so a number in a circle means one thing on
   this site. Only drawn when it stands for more than one. */
.note-n {
    flex: 0 0 auto; min-width: 26px; padding: 2px 8px; border-radius: 999px;
    background: var(--ink); color: var(--amber); font-size: .78rem; font-weight: 800;
    text-align: center;
}
.note-at { flex: 0 0 auto; font-size: .72rem; color: var(--muted); }
.note-empty, .note-capped { margin: 6px 0 0; font-size: .86rem; }

@media (max-width: 560px) {
    /* The clock is the first thing to go: on a narrow line the job matters and the minute
       it arrived does not. */
    .note-at { display: none; }
    .note-line { gap: 10px; padding: 10px 12px; }
}

.prof-link-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.prof-link-txt strong { font-size: 1rem; color: var(--ink); }
.prof-link-txt span   { font-size: .82rem; color: var(--muted); line-height: 1.5; }
.prof-link-n {
    flex: 0 0 auto;
    margin-inline-start: auto;
    min-width: 32px;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--ink);
    color: var(--amber);
    font-size: .9rem;
    font-weight: 800;
    text-align: center;
}

/* ============================================================
   THE MATERIAL PRICE STRIP (home page, above the header)
   The site's first self-running animation. Only `transform`
   moves, so it runs on the compositor and costs a phone
   nothing; the list is drawn twice and shifted by exactly
   half, which is what makes the loop seamless instead of
   snapping back. Duration is set in JS from the measured
   width, so Arabic and English scroll at the same speed
   rather than for the same number of seconds.
   ============================================================ */
.ticker {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 40px;
    padding: 0 14px;
    background: var(--ink);
    color: #e8ecf3;
    font-size: .86rem;
    overflow: hidden;
}
.ticker-label {
    flex: 0 0 auto;
    font-weight: 800;
    color: var(--amber);
    white-space: nowrap;
}
.ticker-cta {
    flex: 0 0 auto;
    color: var(--amber);
    text-decoration: none;
    font-weight: 700;
    white-space: nowrap;
}
.ticker-cta:hover { text-decoration: underline; }

.ticker-viewport { flex: 1 1 auto; overflow: hidden; }
.ticker-track {
    display: inline-flex;
    white-space: nowrap;
    will-change: transform;
    animation: ticker-scroll 40s linear infinite;
}
/* Reading direction decides which way it crawls — a strip running against the language is
   more distracting than no strip at all. */
[dir="rtl"] .ticker-track { animation-name: ticker-scroll-rtl; }

/* You cannot read a price you cannot catch. */
.ticker:hover .ticker-track,
.ticker:focus-within .ticker-track { animation-play-state: paused; }

.ticker-item {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 0 18px;
    border-inline-end: 1px solid rgba(255, 255, 255, .14);
}
.ticker-price { font-weight: 800; color: #fff; }
.ticker-unit  { color: #9fb0c9; font-size: .8rem; }
.ticker-chg   { font-weight: 700; }
.ticker-chg.up   { color: var(--price-up); }
.ticker-chg.down { color: var(--price-down); }
.ticker-date  { color: #9fb0c9; }

/* Read aloud, never drawn: "▲1.2%" is announced as "black up-pointing triangle" otherwise. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@keyframes ticker-scroll     { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes ticker-scroll-rtl { from { transform: translateX(0); } to { transform: translateX(50%); } }

/* The strip always moves on its own, at the speed set in calc-admin — the owner's explicit
   call (2026-08-10): no manual scrollbar, no per-visitor freeze. Hovering or focusing the
   strip still pauses it (below), which is how anyone can stop and read a price without the
   page offering a scrollbar to drag. */

@media (max-width: 640px) {
    .ticker      { font-size: .8rem; gap: 8px; padding: 0 10px; }
    .ticker-cta  { display: none; }        /* the calculator is one tap away in the page anyway */
    .ticker-item { padding: 0 12px; }
}

/* ============================================================
   PROJECT MANAGEMENT (PMS)
   The shared client-contractor workspace: project cards, deal
   cards, the workspace tabs, stages, timeline, payments, papers.
   Everything here is prefixed .pms- and uses the same tokens as
   the rest of the site, so it inherits RTL and the colour scheme.
   ============================================================ */

/* ---- Project + deal cards (projects.html, deals.html) ---- */
.pms-card {
    display: block;
    padding: 18px 20px;
    margin-bottom: 14px;
    text-decoration: none;
    color: inherit;
    transition: box-shadow .15s, transform .15s;
}
.pms-card:hover { box-shadow: var(--shadow-3); transform: translateY(-2px); }
.pms-deal { padding: 24px; margin-bottom: 24px; }

/* ---- The requests inbox: one card per request ----
   A glyph tile, the body, and a coloured bar down the leading edge. The bar is positioned
   rather than a border so it meets the card's 20px corner radius cleanly, and it is
   inline-start so Arabic puts it on the right without a second rule. */
.pms-list-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 14px; flex-wrap: wrap; margin: 26px 0 16px;
}
.pms-list-head .section-title { margin: 0; }

.pms-deal-card {
    position: relative; overflow: hidden; cursor: pointer;
    display: grid; grid-template-columns: auto 1fr; gap: 24px; align-items: start;
    padding-inline-start: 32px;
    transition: box-shadow .2s, transform .2s, opacity .2s, filter .2s;
}
.pms-deal-card:hover { box-shadow: var(--ring), var(--shadow-3); transform: translateY(-4px); }
.pms-deal-card:hover h3 { color: var(--amber-dark); }
.pms-deal-body { min-width: 0; }
/* A request title carries a whole card, so it takes the mockups' 20px heading. Scoped to
   the inbox: the same class titles the smaller blocks on the groups page. */
.pms-deal-card .pms-card-top h3 { font-size: 1.25rem; }

/* Urgency as transparency: full weight when it is your move, a step back when it is
   settled, two when the other side is holding it. The list recedes as it stops needing you. */
.pms-deal-card.is-lower  { opacity: .9; }
.pms-deal-card.is-lowest { opacity: .75; }
.pms-deal-card.is-dead   { opacity: .5; filter: grayscale(1); }
/* A dead request steps out of the list without becoming unreadable to anyone who goes
   looking for it. */
.pms-deal-card.is-dead:hover { opacity: 1; filter: none; }
.pms-deal-card.is-dead h3 { text-decoration: line-through; color: var(--muted); }

.pms-edge {
    position: absolute; inset-block: 0; inset-inline-start: 0; width: 8px;
    background: var(--line-2);
}
.pms-edge-pending, .pms-edge-discussion { background: var(--amber); }
.pms-edge-quoted    { background: #b9c7e4; }
.pms-edge-accepted  { background: var(--sage); }
.pms-edge-declined, .pms-edge-cancelled { background: var(--red-bg); }

.pms-deal-tile {
    width: 64px; height: 64px; border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-2); border: 1px solid var(--line);
}
.pms-deal-tile .material-symbols-outlined { font-size: 30px; color: var(--ink); }

.pms-deal-state { margin: 6px 0 0; font-size: .875rem; color: var(--muted); }
.pms-deal-state b {
    display: inline-flex; align-items: center; gap: 4px; color: var(--ink); font-weight: 700;
}
/* Only a settled state gets a filled glyph. An outline reads as "still running"; a solid
   one as "decided" — and a filled request_quote at this size is just a dark blob. */
.pms-deal-state .material-symbols-outlined { font-size: 17px; }
.pms-deal-state b.st-accepted .material-symbols-outlined,
.pms-deal-state b.st-declined .material-symbols-outlined,
.pms-deal-state b.st-cancelled .material-symbols-outlined {
    font-variation-settings: 'FILL' 1;
}
.pms-deal-state b.st-accepted  { color: #1a7a4c; }
.pms-deal-state b.st-declined,
.pms-deal-state b.st-cancelled { color: var(--red); }

@media (max-width: 560px) {
    .pms-deal-card { grid-template-columns: 1fr; gap: 12px; }
    .pms-deal-tile { width: 48px; height: 48px; }
    .pms-deal-tile .material-symbols-outlined { font-size: 24px; }
}

/* The empty inbox: a glyph in a soft disc rather than an emoji that renders differently
   on every platform and cannot take a colour. */
.pms-empty-disc {
    width: 64px; height: 64px; margin: 0 auto 14px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-3);
}
.pms-empty-disc .material-symbols-outlined { font-size: 30px; color: var(--muted); }

.pms-card-top {
    display: flex; align-items: center; gap: 12px;
    flex-wrap: wrap; justify-content: space-between;
}
.pms-card-top h3 { margin: 0; font-size: 1.05rem; color: var(--ink); }

.pms-card-meta {
    display: flex; flex-wrap: wrap; gap: 6px 18px;
    margin-top: 8px; font-size: .85rem; color: var(--muted);
}
.pms-card-foot {
    display: flex; justify-content: space-between;
    font-size: .8rem; color: var(--ink-2); margin-top: 6px;
}
/* The client's own words on an inbox card, set as a quotation the way the mockups do:
   a rule down the leading edge and italics, so it never reads as our copy. */
.pms-deal-msg {
    margin: 16px 0 0; padding: 16px;
    background: var(--surface-2); border-radius: var(--radius-box);
    border-inline-start: 2px solid var(--line-2);
    font-size: 1rem; font-style: italic; color: var(--ink-2);
}
.pms-warn {
    margin: 10px 0 0; padding: 10px 14px;
    background: var(--amber-soft); border: 1px solid var(--amber);
    border-radius: var(--radius-sm); font-size: .85rem; color: var(--amber-dark);
}
.pms-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }

/* send-request.html — who the request is going to. Fixed by the address the page was
   opened from, so it reads as a fact, not as a field you could change. */
.send-to {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 18px;
    padding: 12px 16px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
}
.send-to-l { font-size: .82rem; color: var(--muted); }
.send-to strong { font-size: 1.02rem; color: var(--ink); }
.send-to .muted { font-size: .84rem; }
.send-to a { margin-inline-start: auto; }

/* The quiet line under the single-company header that teaches the many-at-once path. */
.send-more-link {
    display: flex; align-items: center; gap: 8px;
    margin: -8px 0 18px; font-size: .85rem; color: var(--muted);
}
.send-more-link .ms { font-size: 1.1rem; color: var(--amber-dark); }
.send-more-link a { color: var(--ink-2); font-weight: 600; text-decoration: underline; }
.send-more-link a:hover { color: var(--amber-dark); }

/* ---- Sending to several: the chips naming who, each removable ---- */
.send-multi {
    margin-bottom: 20px; padding: 14px 16px;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--radius-box);
}
.send-multi .send-to-l { display: block; margin-bottom: 9px; }
.send-multi .form-hint { margin: 10px 0 0; }
.send-chip {
    display: inline-flex; align-items: center; gap: 6px;
    margin: 0 0 6px; margin-inline-end: 6px;
    padding: 6px; padding-inline-start: 12px;
    background: var(--card); border: 1px solid var(--line-2); border-radius: 999px;
    font-size: .88rem; font-weight: 700; color: var(--ink);
}
.send-chip-x {
    display: flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; cursor: pointer;
    border: 0; border-radius: 999px; background: var(--surface-3); color: var(--ink-3);
}
.send-chip-x:hover { background: var(--red-bg); color: var(--red); }
.send-chip-x .material-symbols-outlined { font-size: .95rem; }

/* ---- After the send: one row per request, each leading into its room ---- */
.sent-list { margin: 6px 0 18px; }
.sent-row {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 4px; border-bottom: 1px solid var(--line);
}
.sent-row:last-child { border-bottom: 0; }
.sent-ok { color: var(--licensed-fg); flex: none; }
.sent-name { flex: 1 1 auto; min-width: 0; font-weight: 700; color: var(--ink); }
.sent-skip-h { margin: 14px 0 4px; font-size: .95rem; color: var(--ink-2); }
.sent-skip-names { margin: 6px 0 0; font-size: .9rem; color: var(--muted); }
.sent-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }

/* ---- Status pills ---- */
.pms-status {
    font-size: .74rem; font-weight: 700; white-space: nowrap;
    border-radius: 20px; padding: 4px 12px;
    background: var(--surface-3); color: var(--muted);
}
.pms-status-active,
.pms-status-pending    { background: var(--amber-soft); color: var(--amber-dark); }
.pms-status-completed,
.pms-status-accepted   { background: #e3f7ec; color: #1a7a4c; }
.pms-status-cancelled,
.pms-status-declined   { background: var(--red-bg); color: var(--red); }
.pms-status-on_hold    { background: #e7edf7; color: var(--ink); }

/* ---- Progress bar ---- */
.pms-bar {
    height: 8px; border-radius: 8px; overflow: hidden;
    background: var(--surface-3); margin-top: 12px;
}
.pms-bar i {
    display: block; height: 100%; border-radius: 8px;
    background: linear-gradient(90deg, var(--amber), var(--amber-dark));
    transition: width .4s;
}

/* ---- Project groups (projects.html, group.html) ----
   A folder is deliberately plain: a dashed border instead of the solid project card,
   so it never gets mistaken for a workspace of its own. */
.grp-hint { margin: 4px 0 16px; font-size: .88rem; }

/* ---- The client's own notebook, above the first stage ----
   Deliberately unlike a stage card: a tinted panel with a dashed edge, so it reads as the
   client's own margin note rather than as part of the agreed plan. Nobody else is ever sent
   the data, so none of this needs a print rule or a role guard — it cannot render for them. */
.pms-mx {
    padding: 18px 20px; margin-bottom: 18px;
    background: var(--surface-2); border: 1px dashed var(--line-2);
}
.pms-mx-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
}
.pms-mx-head h3 {
    display: flex; align-items: center; gap: 8px; margin: 0; font-size: 1.02rem;
}
.pms-mx-head h3 .material-symbols-outlined { font-size: 20px; color: var(--amber-dark); }
.pms-mx-sum { font-size: .85rem; color: var(--muted); }
.pms-mx-sum b { font-size: 1.05rem; color: var(--ink); margin-inline-start: 4px; }
.pms-mx-sub { margin: 4px 0 12px; font-size: .84rem; color: var(--muted); }
.pms-mx-empty { margin: 0 0 12px; font-size: .86rem; color: var(--muted); }

.pms-mx-list { list-style: none; margin: 0 0 12px; padding: 0; }
.pms-mx-row {
    display: flex; align-items: center; gap: 12px;
    padding: 9px 12px; border-radius: var(--radius-box);
    background: var(--card); border: 1px solid var(--line); margin-bottom: 6px;
}
.pms-mx-t { flex: 1; min-width: 0; font-size: .9rem; overflow-wrap: anywhere; }
.pms-mx-a { white-space: nowrap; font-size: .95rem; color: var(--ink); }
.pms-mx-row .pms-item-tools { flex: 0 0 auto; }
/* The row's own controls come forward on hover, like the checklist's — and unlike the
   checklist's, they are reachable here because this rule names the row that holds them. */
.pms-mx-row:hover .pms-item-tools { opacity: 1; }

.pms-mx-add { display: flex; gap: 8px; flex-wrap: wrap; }
.pms-mx-add input {
    padding: 8px 12px; border: 1px solid var(--line-2); border-radius: var(--radius-box);
    font: inherit; font-size: .88rem; background: var(--card); color: var(--ink);
}
.pms-mx-add input:first-child { flex: 1; min-width: 160px; }
.pms-mx-add input[type="number"] { width: 120px; }
.pms-mx-add input:focus { outline: none; border-color: var(--amber); }

.pms-mx-editing { display: flex; gap: 8px; width: 100%; flex-wrap: wrap; align-items: center; }
.pms-mx-editing input {
    padding: 6px 10px; border: 1px solid var(--amber); border-radius: var(--radius-box);
    font: inherit; font-size: .88rem;
}
.pms-mx-editing .mx-e-t { flex: 1; min-width: 140px; }
.pms-mx-editing .mx-e-a { width: 110px; }

/* The same total on the Budget tab, visibly outside the contract figures. */
.pms-mx-money {
    padding: 16px 18px; margin-bottom: 18px;
    background: var(--surface-2); border: 1px dashed var(--line-2);
}
.pms-mx-money h3 {
    display: flex; align-items: center; gap: 8px; margin: 0 0 4px;
    font-size: .82rem; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted);
}
.pms-mx-money h3 .material-symbols-outlined { font-size: 18px; }
.pms-mx-money > b { font-size: 1.5rem; color: var(--ink); }
.pms-mx-money p { margin: 4px 0 0; font-size: .82rem; color: var(--muted); }

/* ---- The commercial registration, on the account page and the public profile ---- */
.cr-block {
    margin: 0 0 18px; padding: 16px 18px;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    background: var(--surface-2);
}
.cr-block legend {
    padding: 0 8px; font-size: .82rem; font-weight: 700;
    letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.cr-block .field-hint { margin: 0 0 12px; }

/* The logo, shown at roughly the size the agreement prints it, so what is in the box is
   what will be on the contract. `contain` on a white ground, because a logo is a shape on
   a background of its own choosing and cropping one is worse than letterboxing it. */
.logo-row { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.logo-preview {
    width: 76px; height: 76px; flex: 0 0 auto;
    object-fit: contain; background: #fff;
    border: 1px solid var(--line-2); border-radius: var(--radius-sm); padding: 4px;
}
.cr-state {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    margin: 4px 0 0; font-size: .85rem; color: var(--ink-2);
}
.cr-state a { font-weight: 600; color: var(--amber-dark); }
.cr-state.is-soon { color: var(--amber-dark); }
.cr-state.is-late { color: var(--red); }

/* Never styled before this — a handful of upload hints already used the class and simply
   rendered as plain text. */
.hint { display: block; margin-top: 4px; font-size: .78rem; color: var(--muted); }

/* =====================================================================================
   The company page redesign — "My company page", matched to the owner's approved Stitch
   mockup (Documents/stitch-designs/CompanyProfileEditor.html). Everything here is scoped
   under .co-card / #companyCard, so none of it touches Account details, Change password
   or Photos — the other cards this same page draws — or any other page on the site.

   The mockup showed six SEPARATE elevated cards on a grey ground. #companyCard is one
   <form> — there is exactly one Save button for the whole company, so it has to stay one
   element — but .co-card strips the outer card's own white/shadow chrome and each .co-sec
   inside it becomes its own elevated card instead, which reads the same way stacked as six
   independent ones would, without needing six independent forms. */
.co-card { background: none; box-shadow: none; padding: 0; }

.co-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 22px; }
.co-head-ic {
    flex: 0 0 auto; width: 44px; height: 44px; border-radius: 14px;
    background: var(--ink); color: var(--amber);
    display: flex; align-items: center; justify-content: center;
}
.co-head-ic .material-symbols-outlined { font-size: 24px; }
.co-head-tx h2 { margin: 0 0 2px; }
.co-head-tx p  { margin: 0; }

.co-sec {
    background: var(--card); border-radius: var(--radius);
    box-shadow: var(--ring), var(--shadow-2);
    padding: 22px 24px; margin-bottom: 18px;
}
.co-sec-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 18px; }
.co-sec-head-split { justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.co-sec-head-tx { display: flex; align-items: flex-start; gap: 12px; }
.co-sec-ic {
    flex: 0 0 auto; width: 38px; height: 38px; border-radius: 11px;
    background: var(--surface-2); color: var(--ink);
    display: flex; align-items: center; justify-content: center; font-size: 21px;
}
.co-sec-head h3 { margin: 0; font-size: 1.05rem; }
.co-sec-head p  { margin: 3px 0 0; font-size: .82rem; color: var(--muted); }
.co-sec-p { margin: -8px 0 16px; color: var(--muted); font-size: .9rem; line-height: 1.6; }

/* Layered on the existing .form-grid: same fields, just told how many columns to prefer
   on a wide screen. Falls back to the grid's own auto-fill below that, same as every other
   form on the site. */
.co-grid-3 { grid-template-columns: repeat(3, 1fr); }
.co-grid-2 { grid-template-columns: repeat(2, 1fr); }
.co-grid-span { grid-column: 1 / -1; }
@media (max-width: 860px) { .co-grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .co-grid-3, .co-grid-2 { grid-template-columns: 1fr; } }

/* ---- Budget: four buttons standing in for the <select> they drive ---- */
.co-seg { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px; }
.co-seg-btn {
    flex: 1 1 130px; padding: 10px 12px; border-radius: 12px;
    border: 1px solid var(--line); background: var(--surface-2); color: var(--ink);
    font: inherit; font-size: .88rem; font-weight: 600; cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}
.co-seg-btn:hover { border-color: var(--line-2); }
.co-seg-btn.is-on {
    background: var(--ink); color: var(--amber); border-color: var(--ink);
    font-weight: 800;
}

/* ---- Map coordinates ---- */
.co-map-layout { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 760px) { .co-map-layout { grid-template-columns: 1fr; } }
.co-hint-box {
    display: flex; align-items: flex-start; gap: 10px; margin: 10px 0 0;
    padding: 12px 14px; background: var(--surface-2); border-radius: var(--radius-sm);
    font-size: .82rem; color: var(--ink-2); line-height: 1.6;
}
.co-hint-box .material-symbols-outlined { flex: 0 0 auto; font-size: 20px; color: var(--amber-dark); }
/* A real, working preview — not a fabricated street address. It opens whatever the two
   boxes actually hold, so it can never show a place that does not match what will be
   saved. Hidden until both numbers are present; wired in account.js. */
.co-map-preview {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; height: 100%; min-height: 100px;
    background: var(--surface-2); border: 1px dashed var(--line-2); border-radius: var(--radius-sm);
    color: var(--ink-2); text-decoration: none; font-size: .82rem; font-weight: 700;
    text-align: center; padding: 14px; transition: background .15s, border-color .15s;
}
.co-map-preview:hover { background: var(--card); border-color: var(--amber-dark); color: var(--amber-dark); }
.co-map-preview .material-symbols-outlined { font-size: 26px; color: var(--amber-dark); }

/* ---- Services: grouped clusters of selectable tiles ----
   The tile IS a checkbox — a <label> wrapping a real <input type=checkbox>, the same
   pattern .role-card already uses on register.html, kept for the same reason: full
   keyboard and screen-reader behaviour for free, and the existing submit handler's
   `#catGrid input:checked` read (now `#catGroups input:checked`) needs no change at all. */
.co-cat-count {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border-radius: 999px; background: var(--surface-2);
    font-size: .8rem; font-weight: 700; color: var(--ink-2);
}
.co-cat-group { margin-bottom: 20px; }
.co-cat-group:last-child { margin-bottom: 0; }
.co-cat-group-h {
    font-size: .74rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
    color: var(--muted); margin: 0 0 10px;
}
.co-cat-tiles {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px;
}
.co-cat-tile {
    position: relative; display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 12px 14px; border-radius: 14px;
    background: var(--surface-2); border: 1px solid var(--line);
    cursor: pointer; transition: background .15s, border-color .15s, transform .15s, box-shadow .15s;
}
.co-cat-tile:hover { border-color: var(--line-2); transform: translateY(-1px); }
/* The checkbox itself: present for keyboard/AT, invisible on screen — same technique
   .role-card already uses, kept 1x1px rather than display:none so it stays a real,
   focusable, Tab-reachable control. */
.co-cat-tile input {
    position: absolute; opacity: 0; width: 1px; height: 1px;
}
.co-cat-tile:has(input:focus-visible) { outline: 2px solid var(--amber); outline-offset: 2px; }
.co-cat-tile:has(input:checked) {
    background: var(--ink); border-color: var(--ink); color: #fff;
    box-shadow: var(--shadow-2);
}
.co-cat-tile-tx { display: flex; align-items: center; gap: 10px; min-width: 0; }
.co-cat-tile-ic { font-size: 1.3rem; flex: 0 0 auto; }
.co-cat-tile-nm { font-weight: 700; font-size: .9rem; overflow-wrap: anywhere; }
.co-cat-tile-mk { flex: 0 0 auto; font-size: 19px; color: var(--line-2); }
.co-cat-tile:has(input:checked) .co-cat-tile-mk { color: var(--amber); }

/* ---- Description: a textarea that says how much room is left ---- */
.co-desc-wrap { position: relative; }
.co-desc-wrap textarea { padding-bottom: 30px; }
.co-desc-count {
    position: absolute; bottom: 10px; inset-inline-end: 12px;
    font-size: .74rem; color: var(--muted);
    background: rgba(255, 255, 255, .85); padding: 1px 6px; border-radius: 6px;
    pointer-events: none;
}

/* ---- Logo + Commercial registration, side by side ---- */
.co-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 860px) { .co-pair { grid-template-columns: 1fr; } }
.co-pair .co-sec { margin-bottom: 0; display: flex; flex-direction: column; }

.co-logo-box { display: flex; align-items: center; gap: 18px; background: var(--surface-2); border-radius: var(--radius-sm); padding: 16px; }
.co-logo-square {
    flex: 0 0 auto; width: 88px; height: 88px; border-radius: 18px;
    background: #fff; border: 1px solid var(--line-2);
    display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.co-logo-square img { width: 100%; height: 100%; object-fit: contain; padding: 6px; }
.co-logo-placeholder { font-size: 30px; color: var(--line-2); }
.co-logo-side { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.co-logo-btns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.co-confidential {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
    padding: 5px 10px; border-radius: 999px; background: var(--surface-3);
    font-size: .74rem; font-weight: 700; color: var(--ink-2);
}
.co-confidential .material-symbols-outlined { font-size: 15px; }

.co-cr-box { background: var(--surface-2); border-radius: var(--radius-sm); padding: 16px; }
.co-cr-file { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.co-cr-file-ic {
    flex: 0 0 auto; width: 40px; height: 40px; border-radius: 10px;
    background: var(--red-bg); color: var(--red);
    display: flex; align-items: center; justify-content: center; font-size: 20px;
}
.co-cr-file-tx { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.co-cr-file-tx bdi { font-weight: 700; font-size: .88rem; overflow-wrap: anywhere; }
.co-cr-file-tx span { font-size: .76rem; color: var(--muted); }
.co-cr-dl {
    flex: 0 0 auto; border: 0; background: none; padding: 6px 4px; cursor: pointer;
    font: inherit; font-size: .82rem; font-weight: 700; color: var(--amber-dark);
}
.co-cr-dl:hover { text-decoration: underline; }
.co-cr-empty { margin: 0 0 14px; font-size: .85rem; }

.co-foot {
    position: sticky; bottom: 16px; z-index: 5;
    display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
    background: rgba(255, 255, 255, .96); backdrop-filter: blur(6px);
    border: 1px solid var(--line); border-radius: var(--radius);
    box-shadow: var(--shadow-3); padding: 14px 18px; margin-top: 4px;
}
.co-foot-note { margin: 0; max-width: 640px; font-size: 1rem; }
@media (max-width: 640px) { .co-foot { position: static; flex-direction: column; align-items: stretch; } }

/* The public chip: a state, never the document and never the date. */
.badge-cr {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 4px 10px; border-radius: 999px;
    background: var(--licensed-bg); color: var(--licensed-fg);
    font-size: .78rem; font-weight: 600;
}
.badge-cr .ms { font-size: 14px; }
.badge-cr.is-late { background: var(--red-bg); color: var(--red); }

/* ---- Filing a project under a group, from the workspace header ----
   A small panel anchored under the chip rather than a modal: the site has never had one,
   and a client's folders are a handful of rows. Positioned with physical sides plus an RTL
   override — the chip sits at the trailing end of a flex row, so a logical inset here would
   follow the wrong box. */
.pms-grp-pick { position: relative; display: inline-flex; }
.pms-grp-pick .btn.is-filed { border-color: var(--amber); color: var(--amber-dark); }

.pms-grp-pop {
    position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;
    min-width: 232px; max-width: 300px; padding: 10px;
    background: var(--card); border: 1px solid var(--line-2);
    border-radius: var(--radius-sm); box-shadow: var(--shadow-3);
    display: flex; flex-direction: column; gap: 2px;
}
html[dir="rtl"] .pms-grp-pop { left: auto; right: 0; }

.pms-grp-pop-h {
    margin: 0 0 6px; padding: 0 6px;
    font-size: .72rem; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--muted);
}
.pms-grp-opt {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 8px 10px; border: 0; border-radius: 8px;
    background: none; font: inherit; font-size: .88rem; color: var(--ink);
    text-align: start; cursor: pointer;
}
.pms-grp-opt:hover:not(:disabled) { background: var(--surface-2); }
.pms-grp-opt .material-symbols-outlined { font-size: 18px; color: var(--muted); }
/* The folder it is already in: shown so the answer to "where is this?" is in the same
   place as the answer to "where else could it be?", but not offered as a choice. */
.pms-grp-opt.is-here { color: var(--amber-dark); cursor: default; }
.pms-grp-opt.is-here .material-symbols-outlined { color: var(--amber-dark); }
.pms-grp-opt.is-out { color: var(--muted); }
.pms-grp-hint { margin: 0; padding: 4px 6px 8px; font-size: .82rem; color: var(--muted); }
.pms-grp-goto {
    display: flex; align-items: center; gap: 6px;
    margin-top: 6px; padding: 8px 10px;
    border-top: 1px solid var(--line); font-size: .82rem; color: var(--ink-2);
}
.pms-grp-goto .material-symbols-outlined { font-size: 16px; }

.grp-block {
    display: block; padding: 16px 20px; margin-bottom: 14px;
    background: var(--surface-2); border: 1px dashed var(--line);
    text-decoration: none; color: inherit;
    transition: box-shadow .15s, transform .15s, border-color .15s;
}
.grp-block:hover { box-shadow: var(--shadow-3); transform: translateY(-2px); border-color: var(--amber); }
.grp-block .pms-card-top h3 { display: flex; align-items: center; gap: 6px; }

.grp-mini-row {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 0; border-top: 1px solid var(--line);
    font-size: .85rem;
}
.grp-mini-row span:first-child { flex: 1; color: var(--ink); font-weight: 600; }
.grp-mini-more { padding-top: 6px; font-size: .8rem; text-align: center; }
.grp-standalone-h { font-size: 1.1rem; margin: 24px 0 12px; color: var(--ink); }

/* group.html — one folder's own children: a full card each, its own progress bar, and
   a detach action underneath rather than layered on top of the card's own link. */
.grp-child { margin-bottom: 14px; }
.grp-child .pms-card { margin-bottom: 6px; }
.grp-detach-btn { width: 100%; }

/* ---- The workspace header ---- */
.pms-head { display: flex; gap: 18px; flex-wrap: wrap; align-items: flex-start; padding: 20px 22px; }
.pms-head-main { flex: 1; min-width: 240px; }
.pms-head-main h1 { margin: 0 0 8px; font-size: 1.3rem; color: var(--ink); }
.pms-head-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pms-parties {
    display: flex; gap: 6px 18px; flex-wrap: wrap;
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--line); font-size: .85rem; color: var(--ink-2);
}

/* ---- Tabs ---- */
.pms-tabs {
    display: flex; gap: 6px; flex-wrap: wrap;
    margin: 22px 0 16px; padding-bottom: 2px;
}
.pms-tab {
    border: 1px solid var(--line); background: var(--card);
    border-radius: var(--radius-sm); padding: 9px 16px;
    font-family: inherit; font-size: .88rem; font-weight: 600;
    color: var(--ink-2); cursor: pointer; transition: all .15s;
}
.pms-tab:hover  { border-color: var(--line-2); }
.pms-tab.active { background: var(--ink); border-color: var(--ink); color: #fff; }

/* ---- Dashboard ---- */
/* The figures and the story side by side: on a wide screen the numbers answer "where are
   we" while the feed answers "how did we get here", and both deserve to be visible. */
.pms-dash { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 1000px) { .pms-dash { grid-template-columns: 1fr; } }
.pms-dash-side .pms-feed-card { position: sticky; top: 84px; margin-bottom: 0; }
.pms-feed-card .pms-feed { max-height: 620px; overflow-y: auto; }

.pms-kpis {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    margin-bottom: 18px;
}
/* Beside the activity column there is room for two, and a 2×2 block of equal cards reads
   as one set of figures where three-then-one reads as a leftover. */
@media (min-width: 1001px) {
    .pms-dash-main .pms-kpis { grid-template-columns: repeat(2, 1fr); }
}
/* Time is not money: the schedule bar is ink so it is never read as budget spent. */
.pms-bar.is-time i { background: var(--ink); }
.pms-kpi {
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 16px 18px;
    box-shadow: 0 4px 20px rgba(10, 25, 47, .05);
}
.pms-kpi-hd  { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.pms-kpi-ic  { color: var(--line-2); font-size: 22px; flex-shrink: 0; }
.pms-kpi-lbl  { font-size: .78rem; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.pms-kpi-val  { font-size: 1.6rem; font-weight: 800; color: var(--ink); line-height: 1.1; }
.pms-kpi-next { font-size: .98rem; font-weight: 700; color: var(--ink); line-height: 1.35; margin-top: 4px; }
.pms-kpi-sub .material-symbols-outlined { font-size: 15px; vertical-align: -3px; margin-inline-end: 3px; }

/* Money the client still has to look at is the reason they opened the page. */
.pms-kpi-alert {
    display: flex; align-items: center; gap: 7px; margin-top: 12px;
    padding: 9px 11px; border-radius: var(--radius-sm);
    background: var(--amber-soft); border: 1px solid rgba(255, 191, 0, .35);
    font-size: .78rem; font-weight: 700; color: var(--amber-dark);
}
.pms-kpi-alert .material-symbols-outlined { font-size: 18px; }
.pms-kpi-sub  { font-size: .76rem; color: var(--muted); margin-top: 5px; line-height: 1.6; }
.pms-await    { color: var(--amber-dark); }

.pms-block { padding: 18px 20px; margin-bottom: 16px; }
.pms-block h3 { margin: 0 0 12px; font-size: 1rem; color: var(--ink); }

.pms-expiry { list-style: none; margin: 0; padding: 0; font-size: .88rem; }
.pms-expiry li { padding: 7px 0; border-bottom: 1px solid var(--line); color: var(--ink-2); }
.pms-expiry li:last-child { border-bottom: none; }
.pms-expiry li.is-late { color: var(--red); font-weight: 600; }

/* A thread rather than a list: one spine down the side, a ring on it per event, and the
   newest ringed in amber so the eye lands on what just happened. */
.pms-feed { list-style: none; margin: 0; padding: 0; position: relative; }
.pms-feed::before {
    content: ""; position: absolute; top: 12px; bottom: 12px;
    inset-inline-start: 6px; width: 2px; background: var(--surface-3);
}
.pms-feed li { display: flex; gap: 14px; padding: 10px 0; font-size: .88rem; position: relative; }
.pms-feed-dot {
    width: 14px; height: 14px; border-radius: 50%; margin-top: 3px; flex-shrink: 0;
    background: var(--card); border: 2px solid var(--line-2); position: relative; z-index: 1;
}
.pms-feed li.is-latest .pms-feed-dot { border-color: var(--amber); }
.pms-feed time { display: block; font-size: .72rem; color: var(--muted); margin-top: 3px; }

/* ---- Finishing the job: the one card on the dashboard for a once-only act ---- */
.pms-handover {
    display: flex; gap: 16px; align-items: flex-start;
    border-inline-start: 4px solid var(--amber);
}
.pms-handover-ic {
    width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
    background: var(--amber-soft); color: var(--amber-dark);
    display: flex; align-items: center; justify-content: center;
}
.pms-handover-txt { flex: 1; min-width: 0; }
.pms-handover-txt h3 { margin-bottom: 6px; }
.pms-handover-txt p { margin: 0 0 10px; color: var(--ink-2); font-size: .9rem; }

/* ---- The two parties, as faces ---- */
.pms-avatar {
    width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: .82rem; font-weight: 800;
}
.pms-party-client { background: #d6e3ff; color: #0d1c32; }
.pms-party-co     { background: var(--amber-soft); color: var(--amber-dark); }
.pms-party { display: flex; align-items: center; gap: 10px; }
.pms-party-txt { display: flex; flex-direction: column; line-height: 1.25; }
.pms-party-txt small { font-size: .7rem; color: var(--muted); font-weight: 600; }
.pms-party-txt b { font-size: .88rem; color: var(--ink); }

/* ---- A panel with its own title, used by Documents and Tasks ---- */
.pms-panel-card { padding: 22px 24px; }
.pms-panel-hd { margin-bottom: 18px; }
.pms-panel-hd h3 { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; font-size: 1.05rem; }
.pms-panel-hd h3 .material-symbols-outlined { color: var(--amber-dark); font-size: 22px; }
.pms-panel-hd .section-sub { margin: 0; }

/* A quiet round icon button — the row tools on documents and tasks. */
.pms-iconbtn {
    border: none; background: none; cursor: pointer; padding: 5px;
    border-radius: 50%; color: var(--muted); line-height: 0;
}
.pms-iconbtn:hover { background: var(--surface-3); color: var(--ink); }
.pms-iconbtn.is-danger:hover { background: var(--red-bg); color: var(--red); }
.pms-iconbtn .material-symbols-outlined { font-size: 19px; }

/* ---- Stages ---- */
.pms-stage { padding: 0; margin-bottom: 12px; overflow: hidden; }
/* The header is a row holding two controls: the one that opens the stage, and the one that
   renames it. The padding and the gap live on the toggle, which is what used to BE the
   header — so the row reads exactly as it did before the rename control existed. */
.pms-stage-hd { display: flex; align-items: center; }
.pms-stage-toggle {
    display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0;
    padding: 14px 18px; background: none; border: none;
    font-family: inherit; text-align: start; cursor: pointer;
}
.pms-stage-edit {
    flex: 0 0 auto; border: none; background: none; cursor: pointer;
    margin-inline-end: 12px; padding: 7px; border-radius: 8px;
    color: var(--muted); line-height: 0;
}
.pms-stage-edit:hover { color: var(--amber-dark); background: var(--surface-3); }
.pms-stage-edit .material-symbols-outlined { font-size: 19px; }
.pms-stage-ic {
    width: 42px; height: 42px; border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; background: var(--surface-2); flex-shrink: 0;
}
.pms-stage-info { flex: 1; min-width: 0; }
.pms-stage-nm {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    font-size: .95rem; font-weight: 700; color: var(--ink);
}
.pms-stage-sub { display: block; font-size: .76rem; color: var(--muted); margin-top: 3px; }
.pms-status-stage-pending { background: var(--surface-3); color: var(--muted); }
.pms-status-stage-doing   { background: var(--amber-soft); color: var(--amber-dark); }
.pms-status-stage-done    { background: #e3f7ec; color: #1a7a4c; }

.pms-ring {
    width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
}
.pms-ring b {
    width: 36px; height: 36px; border-radius: 50%; background: var(--card);
    display: flex; align-items: center; justify-content: center;
    font-size: .68rem; font-weight: 800; color: var(--ink);
}

.pms-stage-body { display: none; padding: 0 18px 16px; border-top: 1px solid var(--line); }
.pms-stage.open .pms-stage-body { display: block; }

.pms-items, .pms-docs { list-style: none; margin: 0; padding: 0; }
.pms-item, .pms-doc {
    display: flex; align-items: center; gap: 12px;
    padding: 9px 0; border-bottom: 1px solid var(--line); font-size: .9rem;
}
.pms-item:last-child, .pms-doc:last-child { border-bottom: none; }
.pms-item > span, .pms-doc-main { flex: 1; min-width: 0; }
/* Only the wording is struck through — a finished item's dates, cost and buttons are
   still live information, and a line through a button reads as "disabled". */
.pms-item.done > .pms-item-lbl { color: var(--muted); text-decoration: line-through; }
.pms-doc.done .pms-doc-nm { color: var(--muted); }
.pms-doc-main { display: flex; flex-direction: column; gap: 3px; }
.pms-doc-nm { font-weight: 600; color: var(--ink); }
.pms-doc-sub { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

.pms-check {
    width: 24px; height: 24px; flex-shrink: 0; cursor: pointer;
    border: 2px solid var(--line-2); border-radius: 7px; background: var(--card);
    color: #fff; font-size: .78rem; font-weight: 800; line-height: 1;
    display: flex; align-items: center; justify-content: center; transition: all .15s;
}
.pms-check:disabled { cursor: default; }
.done > .pms-check { background: #1a9e63; border-color: #1a9e63; }

.pms-x {
    border: none; background: none; cursor: pointer;
    color: var(--line-2); font-size: .9rem; padding: 4px 6px;
}
.pms-x:hover { color: var(--red); }

.pms-addrow { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 14px; }
.pms-addrow label { display: flex; align-items: center; gap: 6px; font-size: .8rem; color: var(--muted); }
.pms-input {
    flex: 1; min-width: 130px; padding: 9px 12px;
    border: 1.5px solid var(--line); border-radius: var(--radius-sm);
    font-family: inherit; font-size: .88rem; background: var(--card);
}
.pms-input:focus { outline: none; border-color: var(--amber); }
.pms-dates { border-top: 1px dashed var(--line); padding-top: 12px; }
.pms-file-btn { position: relative; cursor: pointer; }

.pms-pill {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: .7rem; font-weight: 700; border-radius: 20px; padding: 3px 10px;
    background: var(--surface-2); color: var(--muted); white-space: nowrap;
}
.pms-pill .material-symbols-outlined { font-size: 14px; }
.pms-pill.is-soon { background: var(--amber-soft); color: var(--amber-dark); }
.pms-pill.is-late { background: var(--red-bg); color: var(--red); }
.pms-by { font-size: .7rem; color: var(--muted); }

/* ---- Documents: one row per piece of paper, in one of three lives ---- */
.pms-docs .pms-doc {
    gap: 14px; padding: 12px 14px; margin-bottom: 8px; border-bottom: none;
    border: 1px solid transparent; border-radius: var(--radius-sm);
    background: var(--surface-2); transition: background .15s, border-color .15s;
}
.pms-docs .pms-doc:hover { background: var(--card); border-color: var(--line); }
.pms-doc.is-missing  { background: none; border: 1px dashed var(--line-2); }
.pms-doc.is-expired  { background: rgba(186, 26, 26, .06); border-color: rgba(186, 26, 26, .3); }
.pms-doc.is-expired .pms-doc-nm { color: var(--red); }

.pms-doc-mark { border: none; background: none; cursor: pointer; padding: 0; line-height: 0; color: var(--line-2); }
.pms-doc-mark:disabled { cursor: default; }
.pms-doc-mark .material-symbols-outlined { font-size: 26px; }
.pms-doc.done .pms-doc-mark { color: #1a9e63; }
/* The fill axis has to be set on the element that draws the glyph, not its parent. */
.pms-doc.done .pms-doc-mark .material-symbols-outlined { font-variation-settings: 'FILL' 1; }
.pms-doc.is-expired .pms-doc-mark { color: var(--red); }

.pms-chip-file {
    display: inline-flex; align-items: center; gap: 4px;
    background: var(--surface-3); color: var(--ink-2);
    border-radius: 20px; padding: 2px 9px; font-size: .68rem; font-weight: 600;
}
.pms-chip-file .material-symbols-outlined { font-size: 14px; }
/* A claim sent before the document became compulsory — a statement, not a button, so it
   reads as "there is nothing here to open" rather than inviting a click that cannot work. */
.pms-chip-file.is-missing {
    background: var(--red-bg); color: var(--red); border-color: var(--red-bg); cursor: default;
}

/* Row tools wait until the row is pointed at — ten rows of buttons is a wall. */
.pms-doc-tools { display: inline-flex; gap: 2px; opacity: 0; transition: opacity .15s; }
.pms-doc:hover .pms-doc-tools, .pms-doc-tools:focus-within { opacity: 1; }
.pms-file-btn .material-symbols-outlined { font-size: 17px; vertical-align: -4px; margin-inline-end: 4px; }

/* ---- Tasks ---- */
.pms-tasks { list-style: none; margin: 14px 0 0; padding: 0; }
.pms-task {
    display: flex; align-items: center; gap: 12px; padding: 10px 12px;
    border-radius: var(--radius-sm); border-bottom: 1px solid var(--line); font-size: .9rem;
}
.pms-task:last-child { border-bottom: none; }
.pms-task:hover { background: var(--surface-2); }
.pms-task.done { background: var(--surface-2); }
.pms-task-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pms-task-nm { color: var(--ink); }
.pms-task.done .pms-task-nm { color: var(--muted); text-decoration: line-through; }
.pms-task-x { opacity: 0; transition: opacity .15s; }
.pms-task:hover .pms-task-x, .pms-task-x:focus { opacity: 1; }
.pms-task-add { margin: 0 0 4px; }

.pms-empty-warm {
    text-align: center; padding: 30px 20px; margin-top: 14px;
    border: 1px dashed var(--line-2); border-radius: var(--radius);
}
.pms-empty-warm .material-symbols-outlined { font-size: 34px; color: var(--amber); }
.pms-empty-warm h4 { margin: 8px 0 4px; font-size: 1rem; color: var(--ink); }
.pms-empty-warm p { margin: 0; font-size: .88rem; }

/* ---- Payments table ---- */
.pms-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
/* The four figures that frame the table. The two describing money in motion carry a
   coloured edge — they are the only two that ever change. */
.pms-sums {
    display: grid; gap: 12px; margin-bottom: 18px;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
.pms-sum {
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius-sm); padding: 12px 14px;
    display: flex; flex-direction: column; gap: 2px;
    box-shadow: 0 4px 20px rgba(10, 25, 47, .05);
}
.pms-sum-lbl { font-size: .72rem; font-weight: 600; color: var(--muted); }
.pms-sum-val { font-size: 1.12rem; font-weight: 800; color: var(--ink); line-height: 1.25; }
.pms-sum small { font-size: .68rem; color: var(--muted); }
.pms-sum.is-paid     { border-inline-start: 4px solid #1a9e63; background: #f4fbf7; }
.pms-sum.is-paid .pms-sum-val { color: #14603b; }
.pms-sum.is-awaiting { border-inline-start: 4px solid var(--amber); background: var(--amber-soft); }
.pms-sum.is-awaiting .pms-sum-val { color: var(--amber-dark); }

/* The payments themselves live in one card, so the table reads as a document. */
.pms-ex-card { padding: 0; overflow: hidden; }
.pms-table thead th { background: var(--surface-2); font-size: .74rem; letter-spacing: .02em; }
.pms-table td { vertical-align: middle; }
.pms-table tbody tr { transition: background .15s; }
.pms-table tbody tr:hover { background: var(--surface-2); }
.pms-ex-nm { font-weight: 600; color: var(--ink); }
.pms-table td.num { font-weight: 700; }
/* Work nobody has claimed yet steps back; the one payment waiting on somebody stands out. */
.pms-table tr.pms-ex-planned td { color: var(--muted); }
.pms-table tr.pms-ex-submitted { background: rgba(255, 191, 0, .09); }
.pms-table tr.pms-ex-submitted:hover { background: rgba(255, 191, 0, .16); }
.pms-table tr.pms-ex-submitted td.num { color: var(--ink); }
.pms-ex-files { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 5px; }
.pms-chip-file.is-btn { border: 1px solid var(--line); cursor: pointer; font-family: inherit; }
.pms-chip-file.is-btn:hover { background: var(--surface-2); color: var(--ink); }

.pms-note { display: block; font-size: .74rem; color: var(--muted); margin-top: 3px; }

/* The row's buttons are laid out by a div INSIDE the cell, never by the cell itself: a <td>
   told to be a flex container stops generating a table-cell box, so it leaves the row's own
   alignment behind — its background band and bottom border end short of every other cell's,
   which reads as one column sitting higher than the rest. */
.pms-cell-actions { vertical-align: middle; }
.pms-row-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

/* A payment's documents at the moment of deciding: proper buttons beside the answer they
   belong to, in the paper-blue of a thing to read rather than a thing to commit to. */
.pms-btn-doc { background: #eef3fb; color: var(--ink); border-color: #c9d8ee; }
.pms-btn-doc:hover { background: #e1eaf8; transform: translateY(-1px); }
.pms-btn-doc .material-symbols-outlined { font-size: 18px; }
/* The client's transfer receipt, in the green the paid status already wears. A paid row
   shows BOTH documents at once, and two identical blue buttons side by side are two
   chances to open the wrong one. */
.pms-btn-doc.is-receipt { background: #e9f6ef; border-color: #b9dfcb; }
.pms-btn-doc.is-receipt:hover { background: #dcf0e5; }
.pms-btn-doc.is-receipt .material-symbols-outlined { color: #1a7a4c; }

/* ---- The documents attached to a request ----
   One row per file: a button that opens it, and one that takes it away. The same block
   serves the client's property papers and the contractor's quotation, on the request page
   and in the room, so the two sides handle their paperwork the same way. */
.pms-files-block { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 6px 0 2px; }
.pms-files { list-style: none; margin: 0; padding: 0; flex-basis: 100%; }
.pms-files li { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pms-file-open {
    display: inline-flex; align-items: center; gap: 6px; min-width: 0;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--radius-sm); padding: 6px 10px;
    font: inherit; font-size: .78rem; color: var(--ink-2); cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}
.pms-file-open:hover { background: var(--card); border-color: var(--line-2); color: var(--ink); }
.pms-file-open .material-symbols-outlined { font-size: 17px; color: var(--muted); }
.pms-file-nm { font-weight: 600; overflow-wrap: anywhere; }
.pms-file-sz { color: var(--muted); }
/* A file chosen but not sent looks unfinished on purpose — dashed, and it says so. */
.pms-files.is-pending .pms-file-open { border-style: dashed; background: none; }
.pms-file-new { font-size: .7rem; font-weight: 700; color: var(--amber-dark); }
.pms-files-left { font-size: .72rem; color: var(--muted); }
.pms-file-add .material-symbols-outlined { font-size: 17px; }
.pms-file-add input:disabled { pointer-events: none; }
/* A picker whose input is disabled must not look pressable either — the label itself
   carries no :disabled state, so the class does it. */
.pms-file-add:has(input:disabled) { opacity: .5; cursor: not-allowed; }

/* The figure and the pencil that changes it, on one line. The flex is on this span and not
   on the <td>, which must stay a table cell to keep the row's alignment. */
/* nowrap, or the pencil makes the cell narrow enough for "430,000 SAR" to break in two. */
.pms-amt { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.pms-amt-edit {
    border: none; background: none; cursor: pointer; padding: 3px;
    border-radius: 6px; line-height: 0; color: var(--muted);
    opacity: .45; transition: opacity .15s, color .15s, background .15s;
}
.pms-table tbody tr:hover .pms-amt-edit { opacity: 1; }
.pms-amt-edit:hover { color: var(--amber-dark); background: var(--surface-3); }
.pms-amt-edit:focus-visible { opacity: 1; }
.pms-amt-edit .material-symbols-outlined { font-size: 16px; }

/* ---- A figure the client has not agreed to yet ----
   Marked down the way a shop marks a price down, because that is the one layout everybody
   already knows how to read: the figure that applies now, large and in the colour that means
   "look at this", with the one it replaced struck through beneath it. The owner asked for
   exactly this and named the reference (2026-09-08).
   Column, not row: the Amount cell is narrow and right-aligned, and two prices side by side
   read as one number twice as long. */
.pms-amt-tag { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.pms-amt-new { color: var(--red); font-size: 1.02rem; line-height: 1.25; white-space: nowrap; }
.pms-amt-old {
    color: var(--muted); font-size: .82rem; white-space: nowrap;
    /* line-through, not a border: it has to follow the text if it ever wraps. */
    text-decoration: line-through; text-decoration-thickness: 1.5px;
}
.pms-amt-ok { margin-top: 4px; }
/* The contractor's side of the same tag: no button, because it is not their answer. */
.pms-amt-wait {
    margin-top: 2px; font-size: .7rem; font-weight: 600;
    color: var(--amber-dark); text-align: end; max-width: 130px; line-height: 1.4;
}

/* A figure that has moved and been agreed: it reads normally, but in its own colour and
   with a pointer, because it is the way into the history. Not underlined — that would put
   a line through a number, which is what the struck-out price above means. */
.pms-amt-link {
    border: 0; background: none; padding: 0; cursor: pointer;
    font: inherit; font-weight: 700; color: var(--amber-dark);
    border-bottom: 1px dotted currentColor;
}
.pms-amt-link:hover { color: var(--ink); }

/* ---- The amount-history dialog (project.html) ----
   Its own classes, not test01's .tf-* ones: that folder is deleted before the site opens to
   the public, and this must not go with it. */
.pms-dlg {
    width: min(480px, 94vw); padding: 0; border: 0; border-radius: var(--radius);
    background: var(--card); color: var(--ink); box-shadow: var(--shadow-3);
    /* Centred by hand — an explicit width otherwise leaves a modal <dialog> pinned to the
       inline-start edge, which in an RTL page is the right-hand side. */
    inset: 0; margin: auto;
}
.pms-dlg::backdrop { background: rgba(10, 25, 47, .55); }
.pms-dlg-head {
    display: flex; align-items: flex-start; gap: 14px; justify-content: space-between;
    padding: 20px 22px 14px; border-bottom: 1px solid var(--line);
}
.pms-dlg-head h2 { margin: 0 0 4px; font-size: 1.08rem; }
.pms-dlg-head h2:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }
.pms-dlg-head p { margin: 0; font-size: .84rem; color: var(--muted); line-height: 1.6; }
.pms-dlg-x {
    flex: none; width: 34px; height: 34px; display: flex; align-items: center;
    justify-content: center; cursor: pointer;
    border: 0; border-radius: 999px; background: var(--surface-3); color: var(--ink-2);
}
.pms-dlg-x:hover { background: var(--red-bg); color: var(--red); }
.pms-dlg-body { padding: 14px 22px; max-height: 60vh; overflow-y: auto; }
.pms-dlg-foot { padding: 12px 22px 18px; display: flex; justify-content: flex-end; }
.pms-dlg-table { width: 100%; border-collapse: collapse; font-size: .86rem; }
.pms-dlg-table th, .pms-dlg-table td { padding: 8px 6px; text-align: start; }
.pms-dlg-table thead th { font-size: .74rem; color: var(--muted); font-weight: 700; }
.pms-dlg-table tbody tr { border-top: 1px solid var(--line); }
.pms-dlg-table tbody th { font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.pms-dlg-table td.num { font-weight: 700; white-space: nowrap; }
.pms-dlg-table .is-pending td, .pms-dlg-table .is-pending th { color: var(--amber-dark); }

/* A document chosen but not yet sent: what it is, how big, and the two things you might
   want to do about it before it goes. Its own line under the buttons — it is a statement
   about the row, not another control competing with Send. */
.pms-pick {
    flex-basis: 100%; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    font-size: .74rem; color: var(--ink-2);
}
.pms-pick .material-symbols-outlined { font-size: 16px; color: var(--muted); }
.pms-pick-nm { font-weight: 600; overflow-wrap: anywhere; }
.pms-pick-sz { color: var(--muted); }
.pms-pick .pms-mini { font-size: .72rem; color: var(--amber-dark); }
.pms-pick .pms-mini.is-drop { color: var(--red); }
.pms-pick .pms-mini.is-drop:hover { color: var(--red); background: var(--red-bg); }

/* Why Approve cannot be pressed yet — and, on the contractor's side, why Send cannot.
   On its own line under the buttons, because a disabled button receives no mouse events
   and a tooltip on one is a message nobody ever reads. */
.pms-gate {
    flex-basis: 100%; display: flex; align-items: center; gap: 4px;
    font-size: .72rem; font-weight: 600; color: var(--amber-dark);
}
.pms-gate .material-symbols-outlined { font-size: 14px; }
.pms-total td { background: var(--surface-2); }
.pms-status[class*="pms-status-ex-"] { display: inline-flex; align-items: center; gap: 4px; }
.pms-status[class*="pms-status-ex-"] .material-symbols-outlined { font-size: 15px; }
.pms-status-ex-planned   { background: var(--surface-3); color: var(--muted); }
.pms-status-ex-submitted { background: var(--amber-soft); color: var(--amber-dark); }
.pms-status-ex-approved  { background: #e7edf7; color: var(--ink); }
.pms-status-ex-rejected  { background: var(--red-bg); color: var(--red); }
.pms-status-ex-paid      { background: #e3f7ec; color: #1a7a4c; }

/* ---- Timeline (CSS grid; RTL mirrors itself) ---- */
.pms-gantt-wrap { padding: 18px; overflow-x: auto; }
.pms-gantt { display: grid; gap: 6px 0; align-items: center; min-width: 520px; }
.pms-gantt-lbl {
    position: sticky; inset-inline-start: 0; z-index: 2;
    grid-column: 1; padding-inline-end: 12px;
    background: var(--card); font-size: .8rem; font-weight: 600;
    color: var(--ink-2); white-space: nowrap;
}
.pms-gantt-month {
    grid-row: 1; font-size: .68rem; font-weight: 700; color: var(--muted);
    text-align: center; padding-bottom: 6px;
    border-inline-end: 1px solid var(--line);
}
.pms-gantt-bar {
    position: relative; height: 24px; border-radius: 7px;
    background: var(--ink); border: 1px solid var(--ink);
    display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.pms-gantt-bar i {
    position: absolute; inset-inline-start: 0; top: 0; height: 100%;
    background: linear-gradient(90deg, var(--amber), var(--amber-dark));
}
.pms-gantt-bar b { position: relative; font-size: .66rem; color: #fff; font-weight: 700; }
/* Today is the one thing on this chart everybody looks for first, so it is a lit line
   with a label on it rather than a hairline you have to hunt for. */
.pms-gantt-today {
    grid-row: 1 / -1; position: relative; pointer-events: none;
    /* The chart centres its rows; without this the line shrinks to its label's height and
       floats to the middle of the chart instead of running the whole way down it. */
    align-self: stretch;
}
/* The line is drawn as a hairline child, not as the cell's own border: a glow on the cell
   would trace all 13px of the grid column and read as two lines with a band between. */
.pms-gantt-today::before {
    content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: 0;
    width: 2px; background: var(--amber);
    box-shadow: 0 0 9px rgba(255, 191, 0, .9);
}
.pms-gantt-today span {
    position: absolute; top: -9px; inset-inline-start: 0;
    transform: translateX(-50%); white-space: nowrap;
    background: var(--amber); color: var(--ink);
    font-size: .6rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
    border-radius: 20px; padding: 2px 9px;
    box-shadow: 0 2px 6px rgba(10, 25, 47, .18);
}
html[dir="rtl"] .pms-gantt-today span { transform: translateX(50%); }

/* Opening a stage where it stands, instead of giving it the whole chart. */
.pms-gantt-lbl { display: flex; align-items: center; gap: 6px; }
.pms-gantt-nm { flex: 1; min-width: 0; }
.pms-gantt-tools { display: inline-flex; gap: 2px; align-items: center; flex-shrink: 0; }
.pms-gantt-toggle, .pms-gantt-open {
    display: inline-flex; align-items: center; gap: 2px; cursor: pointer;
    border: 1px solid rgba(255, 191, 0, .35); background: var(--amber-soft);
    color: var(--amber-dark); border-radius: 20px; padding: 1px 7px;
    font: inherit; font-size: .68rem; font-weight: 800; line-height: 1.5;
}
.pms-gantt-open { padding: 3px 5px; }
.pms-gantt-toggle:hover, .pms-gantt-open:hover { background: var(--amber); color: var(--ink); }
.pms-gantt-toggle.is-open { background: var(--amber); color: var(--ink); }
.pms-gantt-toggle .material-symbols-outlined,
.pms-gantt-open .material-symbols-outlined { font-size: 15px; }

/* An item inside an opened stage: indented, slimmer, and visibly subordinate. */
.pms-gantt-sub { padding-inline-start: 22px; font-weight: 500; color: var(--muted); }
.pms-gantt-bar.is-sub { height: 16px; }
.pms-gantt-bar.is-sub b { font-size: .6rem; }
button.pms-drill-mark {
    border: none; background: none; cursor: pointer; font: inherit;
    font-size: .68rem; font-weight: 800; color: var(--amber-dark); padding: 1px 4px;
    border-radius: 20px;
}
button.pms-drill-mark:hover { background: var(--amber-soft); }

/* ============================================================
   The deal room — negotiating, pricing, agreeing
   ============================================================ */

.pms-room-head {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 16px; flex-wrap: wrap; margin-bottom: 14px;
}
.pms-room-head-right { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Two columns on a desktop, one on a phone — the plan and the talk stay together.
   The proportions follow the state: nothing to negotiate yet puts the weight on what was
   asked; a live quote needs room for the plan and the conversation; a closed request is a
   record with a margin beside it. */
/* 24px between cards, and 8px on the boxes nested inside them — the two measurements every
   one of the eight mockups agrees on (they disagree about the card radius, so the site's own
   20px stands). The tile is the one nested box the mockups draw at 12px. */

/* EVERY track is minmax(0, …), never a bare `fr`.
   A bare `1fr` is `minmax(auto, 1fr)`, and `auto` as a MINIMUM means min-content — so the
   column refuses to shrink below the widest unbreakable thing inside it and the whole room
   overflows sideways instead. Measured at 380px: a 337px grid holding a 460.75px column,
   and the page scrolling 475px wide. minmax(0, …) lets the track shrink and hands the
   wrapping back to the cards, which can do it; the `fr` proportions are unchanged. */
.pms-room { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
.pms-room.st-pending { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
.pms-room.st-open    { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
/* A settled request keeps the document-like split, but not so lopsided that the payment
   plan — which lives in the second column — has to wrap every row it holds. */
.pms-room.st-closed  { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
/* min-width:0 for the same reason one step down: a flex ITEM's default min-width is auto,
   which is min-content, so a column that is allowed to shrink would still be held open from
   the inside by its own cards. Both halves of the pair are needed. */
.pms-room-col { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
@media (max-width: 900px) {
    .pms-room, .pms-room.st-pending, .pms-room.st-open, .pms-room.st-closed {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* The room's cards had no padding of their own since Phase 3 — every inner box faked the
   inset and bare text sat on the border. The mockups pad the card itself (p-6, p-8 wide).
   Scoped to .card so project.html's bare .pms-panel tab wrappers stay untouched. */
.card.pms-panel { padding: 24px; }
@media (min-width: 901px) { .card.pms-panel { padding: 32px; } }

/* Every mockup sets a card heading at 20px/700 and leaves 24px under it. Ours was 16px with
   12px under — the panels read as a dense list rather than as separate documents. */
.pms-panel h2 {
    font-size: 1.25rem; line-height: 1.4; margin: 0 0 24px;
    display: flex; align-items: center; gap: 8px;
}
.pms-panel h2 > .material-symbols-outlined { font-size: 22px; color: var(--amber-dark); }
/* This part of the request is settled — the panel says so without a word. Matched at the
   same weight as the heading-glyph rule above, which would otherwise paint it amber. */
.pms-panel h2 > .pms-panel-tick {
    margin-inline-start: auto;
    color: #1a7a4c; font-size: 22px; font-variation-settings: 'FILL' 1;
}

.pms-room-ref {
    margin: 6px 0 0; font-size: .78rem; color: var(--muted);
    letter-spacing: .04em; text-transform: uppercase;
}
.pms-status .material-symbols-outlined { font-size: 15px; vertical-align: -3px; margin-inline-end: 3px; }

/* ---- The band across the top of a finished request ---- */
.pms-room-banner {
    display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
    padding: 16px; margin-bottom: 24px; border-radius: var(--radius-box);
    background: var(--surface-3); border: 1px solid var(--line-2);
}
.pms-room-banner.is-good { background: #e3f7ec; border-color: #a9dcc0; }
.pms-room-banner.is-dead { background: var(--surface-2); }
.pms-banner-ic { font-size: 26px; font-variation-settings: 'FILL' 1; color: var(--muted); }
.pms-room-banner.is-good .pms-banner-ic { color: #1a7a4c; }
.pms-banner-txt { flex: 1; min-width: 220px; }
.pms-banner-txt h3 { margin: 0; font-size: 1.02rem; color: var(--ink); }
.pms-banner-txt p  { margin: 3px 0 0; font-size: .86rem; color: var(--ink-2); }
.pms-banner-acts { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pms-banner-acts .material-symbols-outlined { font-size: 17px; }

/* ---- Waiting: the viewer's own half of it, never the other side's ---- */
.pms-persp { padding: 24px; text-align: center; }
.pms-persp h3 { margin: 0 0 6px; font-size: 1.02rem; color: var(--ink); }
.pms-persp p  { margin: 0; font-size: .88rem; color: var(--ink-2); }
.pms-persp-ic {
    width: 64px; height: 64px; margin: 0 auto 14px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center; background: var(--surface-3);
}
.pms-persp-ic .material-symbols-outlined { font-size: 32px; color: var(--ink); }
/* The side that can act gets the amber edge and a button, not an illustration. */
.pms-persp.is-act {
    text-align: start; border-inline-start: 4px solid var(--amber);
}
.pms-persp.is-act .btn { margin-top: 14px; }
.pms-persp-who { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }

.pms-avatar {
    width: 40px; height: 40px; flex: 0 0 auto; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--ink); color: #fff; font-weight: 700; font-size: .82rem;
}

/* ---- A panel with nothing in it yet ----
   A card holding the space it will fill, not an apology. Opacity and a flatter shadow,
   never a dashed border — dashes read as "drop a file here". */
.pms-ghost {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 10px; padding: 30px 20px; text-align: center; opacity: .6;
    background: var(--surface-2); border-radius: var(--radius-box);
}
.pms-ghost .material-symbols-outlined { font-size: 44px; color: var(--line-2); }
.pms-ghost p { margin: 0; font-size: .86rem; color: var(--muted); }

/* ---- Why you cannot write yet ---- */
.pms-lock {
    display: flex; align-items: center; gap: 8px; margin-top: 12px;
    padding: 10px 14px; border-radius: var(--radius-box);
    background: var(--surface-2); border: 1px solid var(--line);
    font-size: .84rem; color: var(--muted);
}
.pms-lock .material-symbols-outlined { font-size: 18px; }

/* ---- Who put their name to this, and when ---- */
.pms-sig {
    display: flex; align-items: center; gap: 12px;
    padding: 16px; border-radius: var(--radius-box);
    border: 1px solid var(--line); margin-bottom: 12px;
}
.pms-sig.is-signed { background: #e3f7ec; border-color: #a9dcc0; }
.pms-sig b { font-size: .92rem; color: var(--ink); }
.pms-sig-when {
    display: flex; align-items: center; gap: 4px;
    font-size: .78rem; color: #1a7a4c; margin-top: 2px;
}
.pms-sig:not(.is-signed) .pms-sig-when { color: var(--muted); }
.pms-sig-when .material-symbols-outlined { font-size: 15px; }

.pms-kv { display: flex; flex-direction: column; gap: 6px; }
.pms-kv > div { display: flex; justify-content: space-between; gap: 12px; font-size: .85rem; }
.pms-kv > div > span { color: var(--muted); }

/* Whose move it is, on an inbox card. */
.pms-turn {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 10px; border-radius: 999px; white-space: nowrap;
    background: var(--surface-3); color: var(--muted); font-size: .72rem; font-weight: 600;
    border: 1px solid var(--line);
}
.pms-turn.now {
    background: var(--amber-soft); color: var(--amber-dark); border-color: var(--amber);
}
.pms-turn .material-symbols-outlined { font-size: 14px; }
.pms-turn.now .material-symbols-outlined { font-variation-settings: 'FILL' 1; }

/* ---- What was asked for ---- */
/* The client's own words, set apart as a quotation — it is the one thing on this page
   nobody on our side wrote. */
.pms-quoted {
    position: relative; margin: 0 0 24px;
    padding: 20px; padding-inline-start: 56px;
    background: var(--surface-2); border-radius: var(--radius-box);
    border: 1px solid var(--line);
}
.pms-quoted p { margin: 0; font-size: 1rem; font-style: italic; color: var(--ink-2); }
/* Positioned with physical sides on purpose. The glyph classes carry `direction: ltr` so
   the ligature name renders, which means an inset-inline-* on the glyph itself resolves
   left-to-right even on an Arabic page — and the mark lands on the text instead of in the
   padding reserved for it. */
.pms-quoted-mark {
    position: absolute; inset-block-start: 14px; left: 16px;
    font-size: 36px; color: var(--line-2); opacity: .8;
}
html[dir="rtl"] .pms-quoted-mark { left: auto; right: 16px; }

/* Six short facts read better as pairs than as a column of rows. */
.pms-req-dl { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.pms-req-wide {
    grid-column: 1 / -1; border-top: 1px solid var(--line);
    padding-top: 16px; margin-top: 4px;
}
.pms-fact dt {
    font-size: .75rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: var(--muted); margin-bottom: 4px;
}
.pms-fact dd { margin: 0; font-size: 1rem; font-weight: 600; color: var(--ink); }
.pms-req-acts { margin-top: 18px; display: flex; flex-direction: column; gap: 8px; }

/* ---- The offer ---- */
.pms-eyebrow {
    font-size: .7rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: var(--muted);
}
.pms-quote-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pms-quote-ver {
    font-size: .68rem; font-weight: 700; color: var(--muted);
    background: var(--surface-3); border-radius: 6px; padding: 2px 8px;
}
/* One number, said once and said large. */
.pms-quote-big { margin: 2px 0 24px; line-height: 1.1; }
.pms-quote-big b { font-size: 2rem; font-weight: 800; color: var(--ink); }
.pms-quote-big span { font-size: 1.25rem; font-weight: 700; color: var(--muted); }

.pms-warr {
    display: flex; align-items: center; gap: 12px; margin-bottom: 24px;
    padding: 16px; border-radius: var(--radius-box);
    background: var(--amber-soft); border: 1px solid #f2dfa6;
}
.pms-warr .material-symbols-outlined {
    font-size: 24px; color: var(--amber-dark); font-variation-settings: 'FILL' 1;
}
.pms-warr b { display: block; font-size: .9rem; color: var(--ink); }
.pms-warr span { font-size: .82rem; color: var(--ink-2); }
.pms-warr.is-none { background: var(--surface-2); border-color: var(--line); }
.pms-warr.is-none .material-symbols-outlined { color: var(--muted); font-variation-settings: 'FILL' 0; }

.pms-keyterms {
    padding: 16px; border-radius: var(--radius-box);
    border: 1px solid var(--line); margin-bottom: 24px;
}
.pms-keyterms > p {
    display: flex; align-items: center; gap: 6px; margin: 0 0 8px;
    font-size: .8rem; font-weight: 700; color: var(--ink);
}
.pms-keyterms .material-symbols-outlined { font-size: 16px; color: var(--muted); }
.pms-keyterms ul { margin: 0; padding-inline-start: 20px; }
.pms-keyterms li { font-size: .875rem; color: var(--ink-2); margin-bottom: 4px; }

/* The way into the draft, immediately above the decision it informs. */
.pms-read-agr {
    display: flex; align-items: center; justify-content: center; gap: 6px;
    margin-bottom: 12px; padding: 8px;
    font-size: .85rem; font-weight: 600; color: var(--ink-2);
    border: 1px dashed var(--line-2); border-radius: var(--radius-box);
}
.pms-read-agr:hover { color: var(--amber-dark); border-color: var(--amber); }
.pms-read-agr .material-symbols-outlined { font-size: 17px; }
/* The annexed terms wear the same shape as the agreement link they sit under — they are
   the same act, reading what is being agreed to. A <button> needs the reset an <a> does
   not; `width: 100%` because a button does not fill its parent the way an anchor does. */
button.pms-read-agr {
    width: 100%; background: none; font-family: inherit; cursor: pointer;
    text-align: center; overflow-wrap: anywhere;
}

.pms-quote-acts { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }

/* The contractor's half of a quoted request: what they offered, and the one thing they
   can still do about it. */
.pms-submitted {
    margin-top: 24px; padding: 16px; border-radius: var(--radius-box);
    background: var(--surface-2); border: 1px solid var(--line);
}
.pms-submitted-top { display: flex; align-items: center; gap: 12px; }
.pms-submitted-ic {
    width: 40px; height: 40px; flex: 0 0 auto; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--amber); color: var(--ink);
}
.pms-submitted-ic .material-symbols-outlined { font-size: 21px; font-variation-settings: 'FILL' 1; }
.pms-submitted-top b { display: block; font-size: .95rem; color: var(--ink); }
.pms-submitted-top span { font-size: .84rem; color: var(--muted); }
.pms-submitted-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin-top: 12px; padding-top: 12px;
    border-top: 1px solid var(--line);
}
.pms-submitted-row b { display: block; font-size: 1.2rem; font-weight: 800; color: var(--ink); }
.pms-submitted-row .material-symbols-outlined { font-size: 17px; }

/* ---- The priced plan ---- */
/* The mockups give each part of the plan its own tinted row — 16px of padding, 16px apart,
   never a bare list against the card. */
.pms-plan { display: flex; flex-direction: column; gap: 16px; }

.pms-ms-row {
    display: flex; align-items: flex-start; gap: 16px;
    padding: 16px; border-radius: var(--radius-box);
    background: var(--surface-2);
    border: 1px solid transparent; transition: border-color .15s, background .15s;
}
.pms-ms-row:hover { border-color: var(--line-2); }
.pms-ms-num {
    width: 32px; height: 32px; flex: 0 0 auto; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: .75rem; font-weight: 700;
    background: var(--surface-3); color: var(--muted); border: 1px solid var(--line-2);
}
/* The first payment is the one that falls due first — it leads the column. */
.pms-ms-num.is-first { background: var(--ink); color: #fff; border-color: var(--ink); }
.pms-ms-txt { flex: 1; min-width: 0; }
.pms-ms-txt > b { font-size: .875rem; color: var(--ink); }
.pms-ms-txt > p { margin: 3px 0 0; }
.pms-ms-when {
    display: flex; align-items: center; gap: 5px; margin: 5px 0 0;
    font-size: .78rem; color: var(--muted);
}
.pms-ms-when .material-symbols-outlined { font-size: 15px; }
.pms-ms-amt { text-align: end; white-space: nowrap; }
.pms-ms-amt b { font-size: 1.25rem; font-weight: 700; color: var(--ink); }
.pms-ms-amt span { display: block; font-size: .75rem; color: var(--muted); margin-top: 2px; }
.pms-ms-row .pms-item-tools { align-self: center; flex: 0 0 auto; }
/* On a small phone the row runs out of room: the number, the wording, the amount and four
   buttons come to more than 360px, and the buttons are the one part that cannot shrink
   (flex: 0 0 auto, by design — a 29px target must not become 20px). So the row wraps and
   they take their own line, aligned to the trailing edge. Measured: without this the tool
   group sits 16px past the edge and the whole page scrolls sideways. */
@media (max-width: 420px) {
    .pms-ms-row { flex-wrap: wrap; }
    .pms-ms-row .pms-item-tools { margin-inline-start: auto; }
}
.pms-ms-row .pms-mini .material-symbols-outlined { font-size: 17px; }
.pms-ms-row .pms-mini:hover .material-symbols-outlined { color: var(--amber-dark); }
.pms-ms-row .pms-mini[data-del]:hover .material-symbols-outlined { color: var(--red); }

.pms-plan table { width: 100%; border-collapse: collapse; }
.pms-plan td { padding: 8px 6px; border-bottom: 1px solid var(--line); vertical-align: top; }
.pms-plan-amt { text-align: end; white-space: nowrap; font-weight: 600; }
.pms-plan-act { text-align: end; white-space: nowrap; }
/* The total is separated from the parts by a heavier rule, the way an invoice does it. */
.pms-plan-total, .pms-quote-total {
    display: flex; justify-content: space-between; align-items: center;
    gap: 12px; font-size: .875rem; font-weight: 600;
    letter-spacing: .04em; text-transform: uppercase;
    margin-top: 24px; padding: 16px 16px 0;
    border-top: 2px solid var(--line);
}
.pms-plan-total b, .pms-quote-total b {
    font-size: 1.5rem; letter-spacing: 0; text-transform: none;
    color: var(--navy, var(--ink));
}
/* The add/edit form sits inside a dashed frame — the one part of the plan that is a place
   to write rather than a thing already agreed. */
.pms-ms-form {
    margin-top: 16px; padding: 16px;
    border: 1px dashed var(--line-2); border-radius: var(--radius-box);
    background: var(--surface-2);
}
.pms-ms-form h3 { font-size: .9rem; margin: 0 0 10px; }

/* The running total, beside the heading, while the plan can still be changed. */
.pms-plan-chip {
    display: inline-flex; align-items: center; gap: 8px;
    margin-inline-start: auto; font-size: .8rem;
}
.pms-plan-chip b { font-size: .95rem; color: var(--ink); }
.pms-editing-chip {
    font-size: .68rem; font-weight: 700; color: var(--muted);
    background: var(--surface-3); border: 1px solid var(--line-2);
    border-radius: 999px; padding: 2px 9px;
}
/* Both the chip and the tick want the same slot; the tick only appears when the plan has
   rows, at which point the chip is what should give way. */
.pms-plan-chip + .pms-panel-tick { margin-inline-start: 8px; }

/* ---- The stages of the work ----
   The scope panel, above the priced plan. Same vocabulary as the rows above so the two
   lists read as one document: tinted rows, 16px padding, the tools at the trailing edge.

   EVERY gap next to a glyph here is flex `gap`, never a directional margin.
   .material-symbols-outlined forces `direction: ltr` on ITSELF (see :4365 below), so its
   own inline-end is the right-hand side in BOTH languages — a margin-inline-end on a glyph
   puts the space on the wrong side in Arabic. This trap has now caught this project three
   times; `gap` has no side at all, which is why it is the only thing used here. */
.pms-st-hint { margin: 0 0 14px; }
.pms-st-list { display: flex; flex-direction: column; gap: 10px; }

.pms-st-row {
    border-radius: var(--radius-box); background: var(--surface-2);
    border: 1px solid transparent; transition: border-color .15s;
}
.pms-st-row:hover { border-color: var(--line-2); }
.pms-st-row.is-open { border-color: var(--line-2); background: var(--surface-2); }

.pms-st-bar { display: flex; align-items: center; gap: 8px; padding-inline-end: 10px; }

/* The whole heading is the control that opens the stage — a far bigger target than a
   chevron, which is what makes this usable one-handed at 380px. */
.pms-st-toggle {
    flex: 1; min-width: 0;
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px; background: none; border: 0; cursor: pointer;
    text-align: start; font: inherit; color: inherit;
    border-radius: var(--radius-box);
}
.pms-st-toggle:hover .pms-st-txt > b { color: var(--amber-dark); }
.pms-st-toggle:focus-visible { outline: 2px solid var(--amber); outline-offset: -2px; }

.pms-st-glyph {
    width: 34px; height: 34px; flex: 0 0 auto; border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem; background: var(--surface-3); border: 1px solid var(--line-2);
}
.pms-st-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pms-st-txt > b { font-size: .875rem; color: var(--ink); }
.pms-st-share {
    flex: 0 0 auto; font-size: .78rem; font-weight: 700; color: var(--muted);
    white-space: nowrap;
}
.pms-st-chev { flex: 0 0 auto; font-size: 20px; color: var(--muted); }

/* The running share total beside the heading. Red until it comes to 100 — a scope that
   does not add up cannot be sent, so saying so early is kinder than saying so at the door. */
.pms-st-sum { font-size: .8rem; font-weight: 700; }
/* --licensed-fg is this palette's only green; there is no --green token, and inventing one
   for a single label would put a second green in the site. */
.pms-st-sum.is-ok  { color: var(--licensed-fg); }
.pms-st-sum.is-off { color: var(--red); }

.pms-st-items {
    display: flex; flex-direction: column; gap: 2px;
    padding: 0 16px 12px; margin-top: -2px;
}
.pms-st-item {
    display: flex; align-items: center; gap: 10px;
    padding: 7px 10px; border-radius: 8px;
    border-top: 1px solid var(--line);
}
.pms-st-item:hover { background: var(--surface-3); }
.pms-st-tick { flex: 0 0 auto; display: inline-flex; color: var(--muted); }
.pms-st-tick .material-symbols-outlined { font-size: 16px; }
.pms-st-label { flex: 1; min-width: 0; font-size: .82rem; color: var(--ink); }

.pms-st-row .pms-item-tools { flex: 0 0 auto; }
.pms-st-row .pms-mini .material-symbols-outlined { font-size: 17px; }
.pms-st-row .pms-mini:hover .material-symbols-outlined { color: var(--amber-dark); }
.pms-st-row .pms-mini[data-st-del]:hover .material-symbols-outlined,
.pms-st-row .pms-mini[data-it-del]:hover .material-symbols-outlined { color: var(--red); }

.pms-st-additem {
    display: flex; align-items: center; gap: 6px;
    margin-top: 6px; padding: 7px 10px; border-radius: 8px;
    background: none; border: 1px dashed var(--line-2); cursor: pointer;
    font: inherit; font-size: .8rem; color: var(--muted);
}
.pms-st-additem:hover { color: var(--amber-dark); border-color: var(--amber); }
.pms-st-additem .material-symbols-outlined { font-size: 17px; }

/* The action row under a list. Shared by both panels on purpose: the payment plan's "Add a
   part of the work" and the scope's "Add a stage" are the same control doing the same job on
   the same screen, and they would read as two different features if they were styled apart.
   Two names rather than one, because each panel keeps its own. */
.pms-st-acts, .pms-plan-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.pms-st-acts .btn, .pms-plan-acts .btn { display: inline-flex; align-items: center; gap: 6px; }
.pms-st-acts .material-symbols-outlined,
.pms-plan-acts .material-symbols-outlined { font-size: 18px; }

.pms-st-itform { margin-top: 8px; padding: 12px; }

/* The way down to this panel from the quote card, which stacks above it on a phone. */
.pms-st-jump { margin-top: 10px; }
/* The site header is sticky, so an anchor that scrolls this card to y=0 puts its own heading
   underneath it — the client would arrive at a list whose title he cannot see, on the one
   screen where the jump is load-bearing.

   88px clears the 73–84px the header occupies while it is still pinned. Below 640 it is not
   pinned at all any more (see the header rule), so there is nothing to clear and the only job
   left is not to put the heading flush against the top edge. Measured, not guessed — and this
   replaces a three-step staircase that existed only to dodge a header overflowing its own box
   (U-2), which is now fixed rather than dodged. */
#stageCard { scroll-margin-top: 88px; }
@media (max-width: 640px) { #stageCard { scroll-margin-top: 12px; } }

/* The scope moved while somebody was reading it. */
.pms-warn-line {
    display: flex; align-items: center; gap: 8px; margin: 0 0 12px;
    padding: 10px 12px; border-radius: var(--radius-box);
    background: var(--amber-soft);
    border: 1px solid var(--amber);
    font-size: .8rem; font-weight: 600; color: var(--amber-dark);
}
.pms-warn-line .material-symbols-outlined { font-size: 18px; }

/* A disabled action explains itself rather than just refusing. */
.pms-why {
    display: flex; align-items: center; gap: 6px; margin: 8px 0 0;
    font-size: .8rem; color: var(--red);
}
.pms-why .material-symbols-outlined { font-size: 16px; }

/* ---- The conversation ---- */
.pms-thread {
    display: flex; flex-direction: column; gap: 10px;
    max-height: 520px; overflow-y: auto; padding: 4px;
}

/* The day, said once, above the first thing said on it. */
.pms-day { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.pms-day::before, .pms-day::after {
    content: ''; flex: 1; height: 1px; background: var(--line);
}
.pms-day span {
    font-size: .72rem; font-weight: 600; color: var(--muted);
    background: var(--surface-3); border-radius: 999px; padding: 3px 12px;
}

.pms-bubble-row {
    display: flex; align-items: flex-end; gap: 8px; max-width: 85%; align-self: flex-start;
}
.pms-bubble-row.mine { align-self: flex-end; flex-direction: row-reverse; }
.pms-bubble-av {
    width: 30px; height: 30px; font-size: .68rem;
    background: var(--surface-3); color: var(--ink-2);
}
.pms-bubble-row.mine .pms-bubble-av { background: var(--amber-dark); color: #fff; }
/* An avatar is the first thing worth losing on a narrow screen. */
@media (max-width: 640px) { .pms-bubble-av { display: none; } }

.pms-bubble {
    background: var(--surface-3); border: 1px solid var(--line);
    border-radius: 16px; padding: 16px;
    font-size: 1rem; line-height: 1.5; overflow-wrap: anywhere; min-width: 0;
    /* The corner nearest the speaker is squared off — the tail of the bubble. */
    border-end-start-radius: 4px;
}
/* The reader's own words sit on their side of the thread — mirrored under RTL for free.
   The border stays but goes invisible, so both kinds of bubble size identically. */
.pms-bubble.mine {
    background: var(--amber-soft); border-color: transparent;
    border-end-start-radius: 16px; border-end-end-radius: 4px;
}
.pms-bubble-who { font-size: .72rem; font-weight: 700; color: var(--muted); margin-bottom: 4px; }
.pms-bubble-at {
    display: block; margin-top: 6px; font-size: .68rem; color: var(--muted); text-align: end;
}

/* Something the room did, rather than something somebody said. */
.pms-line {
    align-self: center; display: inline-flex; align-items: center; gap: 6px;
    font-size: .76rem; color: var(--muted); text-align: center;
    padding: 5px 12px; border-radius: 8px;
    background: var(--surface-2); border: 1px solid var(--line);
}
.pms-line .material-symbols-outlined { font-size: 15px; }
/* The offer moving is the one event worth colouring. */
.pms-line.is-quote {
    background: var(--amber-soft); border-color: #f2dfa6; color: var(--amber-dark);
}
/* The composer is one rounded field with the send button inside it — the input never had
   padding of its own (it sits outside .form-field), so it is given some here. */
.pms-msg-row {
    display: flex; align-items: center; gap: 6px; margin-top: 12px; padding: 5px;
    background: var(--card); border: 1px solid var(--line-2); border-radius: 999px;
    transition: border-color .15s, box-shadow .15s;
}
.pms-msg-row:focus-within {
    border-color: var(--ink); box-shadow: 0 0 0 3px rgba(255, 191, 0, .30);
}
.pms-msg-row input {
    flex: 1; min-width: 0; padding: 8px 14px;
    border: none; background: none; font: inherit; color: var(--ink);
}
.pms-msg-row input:focus { outline: none; }
.pms-msg-row .btn {
    flex: 0 0 auto; width: 38px; height: 38px; padding: 0; border-radius: 50%;
}
.pms-msg-row .btn .material-symbols-outlined { font-size: 19px; }

/* ---- Deal states the inbox and the room share ---- */
.pms-status-discussion { background: #e7edf7; color: var(--ink); }
.pms-status-quoted     { background: var(--amber-soft); color: var(--amber-dark); }
.pms-status-ex-confirmed { background: #d6f0e1; color: #14603b; }

/* The warranty that runs after a confirmed handover. */
.pms-warranty {
    margin-top: 10px; padding: 10px 14px; border-radius: 10px;
    background: #e3f7ec; color: #1a7a4c; font-size: .9rem;
}
.pms-warranty.is-over { background: var(--surface-3); color: var(--muted); }

/* ============================================================
   agreement.html — the generated contract
   An A4 sheet on the page background. Everything that is not the document disappears when
   it is printed, and the sheet itself loses its shadow and its margins.
   ============================================================ */

/* The way into the agreement from the workspace's paperwork tab. */
.pms-agr-link { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.pms-agr-link > .material-symbols-outlined { font-size: 26px; color: var(--amber-dark); }
.pms-agr-link > div { flex: 1; }
.pms-agr-link b { font-size: .98rem; color: var(--ink); }
.pms-agr-link .section-sub { margin: 2px 0 0; }

.agr-bar { background: var(--card); border-bottom: 1px solid var(--line); padding: 10px 0; }
.agr-bar-in { display: flex; gap: 8px; justify-content: flex-end; align-items: center; }
.agr-bar .material-symbols-outlined { font-size: 18px; }

.agr-sheet {
    max-width: 210mm; margin: 28px auto; padding: 20mm 18mm;
    background: #fff; color: var(--ink);
    box-shadow: var(--shadow-2); border: 1px solid var(--line);
    font-size: .92rem; line-height: 1.7;
}

.agr-head {
    display: flex; justify-content: space-between; align-items: flex-end;
    gap: 24px; flex-wrap: wrap;
    padding-bottom: 24px; margin-bottom: 48px; border-bottom: 2px solid var(--ink);
}
/* The letterhead: the contractor's mark, then their name. A company name is not a title —
   it is not uppercased and it is allowed to be long, so the size steps down from the 3rem
   the site's own name used to wear and wraps rather than overflowing. */
/* The brand gives way, the date block does not: a long company name wraps inside its own
   half rather than shoving the date and reference onto a line of their own. */
.agr-brand { display: flex; align-items: center; gap: 18px; min-width: 0; flex: 1 1 300px; }
.agr-logo {
    width: 76px; height: 76px; flex: 0 0 auto;
    object-fit: contain; object-position: center;
}
.agr-head h1 {
    margin: 0; font-size: 2.1rem; font-weight: 800;
    letter-spacing: -.02em; line-height: 1.1; overflow-wrap: anywhere;
}
.agr-head p {
    margin: 8px 0 0; font-size: 1.25rem; letter-spacing: .025em;
    text-transform: uppercase; color: var(--muted);
}
.agr-meta {
    display: grid; grid-template-columns: auto auto; gap: 4px 16px;
    align-items: baseline; flex: 0 0 auto;
}
.agr-meta dt {
    font-size: .875rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}
.agr-meta dd { margin: 0; font-weight: 700; }

/* An annexed document, named inside the contract. On screen it opens; on paper it is the
   name and nothing else, because a printed agreement still has to record exactly which
   documents were attached to it — see the print block at the foot of this file. */
.agr-annex {
    background: none; border: none; padding: 0; font: inherit; color: var(--ink);
    text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
    overflow-wrap: anywhere; text-align: start;
}
.agr-annex:hover { color: var(--amber-dark); }

.agr-sec { margin-bottom: 48px; }
.agr-sec h2 {
    font-size: 1.5rem; font-weight: 700; margin: 0 0 16px;
    padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.agr-sec p { margin: 0 0 10px; }
.agr-asked { color: var(--ink-2); }

/* ---- The offer, read before it is signed ----
   The band and the watermark both live inside the sheet, so both survive printing. A draft
   that comes off the printer looking like a finished contract is the one outcome worth
   engineering against. */
.agr-draft-band {
    display: flex; align-items: flex-start; gap: 12px;
    margin: 0 0 28px; padding: 14px 16px;
    background: var(--amber-soft); border: 1px solid var(--amber);
    border-radius: var(--radius-sm);
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
.agr-draft-band .material-symbols-outlined { font-size: 22px; color: var(--amber-dark); }
.agr-draft-band b { display: block; font-size: .95rem; color: var(--ink); }
.agr-draft-band p { margin: 3px 0 0; font-size: .85rem; color: var(--ink-2); }

.agr-sheet.is-draft { position: relative; }
/* Set on the sheet rather than a child so it cannot be scrolled away from, and drawn behind
   the text so it never costs a word of legibility. */
.agr-sheet.is-draft::before {
    content: attr(data-draft);
    position: absolute; inset-block-start: 34%; inset-inline-start: 0;
    width: 100%; text-align: center;
    font-size: 5.5rem; font-weight: 800; letter-spacing: .18em;
    color: rgba(185, 134, 0, .10);
    transform: rotate(-24deg); transform-origin: center;
    pointer-events: none; z-index: 0; white-space: nowrap;
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
.agr-sheet.is-draft > * { position: relative; z-index: 1; }

/* A line to sign on, where a signed copy would carry a date. */
.agr-blank {
    display: inline-block; min-width: 110px;
    border-bottom: 1px solid var(--line-2); vertical-align: -2px;
}

.agr-parties { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; }
.agr-party { padding: 24px; background: var(--surface-2); border: 1px solid var(--line); }
.agr-party h3 {
    margin: 0 0 8px; font-size: .875rem; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}
.agr-party-n { margin: 0 0 4px !important; font-size: 1.25rem; font-weight: 700; }
.agr-party address { font-style: normal; font-size: .95rem; color: var(--ink-2); line-height: 1.6; }
.agr-lic { font-weight: 600; color: var(--licensed-fg); }

.agr-terms { margin: 0; padding-inline-start: 24px; }
.agr-terms > li { margin-bottom: 12px; }
.agr-terms ul { margin: 6px 0 0; padding-inline-start: 20px; }
.agr-terms ul li { margin-bottom: 3px; color: var(--ink-2); }

.agr-table { width: 100%; border-collapse: collapse; font-size: .95rem; }
.agr-table th {
    text-align: start; padding: 16px; background: var(--surface-2);
    border-bottom: 1px solid var(--line-2);
    font-size: .8rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}
.agr-table td { padding: 16px; border-bottom: 1px solid var(--line); vertical-align: top; }
.agr-table .num { text-align: end; white-space: nowrap; }
.agr-when { display: block; font-size: .74rem; color: var(--muted); margin-top: 2px; }
.agr-table tfoot td {
    background: var(--surface-3); border-top: 2px solid var(--ink); border-bottom: none;
    font-weight: 800; font-size: .95rem;
}

.agr-close { margin-top: 40px; padding-top: 20px; border-top: 3px solid var(--surface-3); }
.agr-witness { text-align: center; font-style: italic; color: var(--ink-2); margin-bottom: 34px; }
.agr-signs { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; }
/* Room above the rule for a pen — the point of putting this on paper at all. */
.agr-rule { height: 46px; border-bottom: 1px solid var(--ink); margin-bottom: 7px; }
.agr-sign-r {
    margin: 0 !important; font-size: .68rem; letter-spacing: .06em;
    text-transform: uppercase; color: var(--muted);
}
.agr-sign-n { margin: 2px 0 0 !important; font-weight: 700; }
.agr-sign-d { margin: 4px 0 0 !important; font-size: .8rem; color: var(--muted); }
.agr-note {
    margin-top: 34px !important; padding-top: 12px; border-top: 1px solid var(--line);
    font-size: .74rem; line-height: 1.6; color: var(--muted);
}

@media (max-width: 700px) {
    .agr-sheet { padding: 22px 18px; margin: 14px auto; }
    .agr-parties, .agr-signs { grid-template-columns: 1fr; }
    .agr-head h1 { font-size: 1.5rem; }
}

/* On paper: the sheet is the page.
   An unnamed `@page` is global to the whole stylesheet, not to the file that happens to be
   open — so when the workspace's Gantt block declared a bare landscape one further down, it
   won on source order and every contract printed sideways. Having its own .html file bought
   the agreement nothing; they share this stylesheet.
   The fix is the other way round: portrait stays the unnamed default here, and the Gantt's
   landscape is NAMED (`@page chart`). A contract that must be portrait should not depend on
   named-page support; a chart that would merely prefer landscape can. */
@media print {
    @page { size: A4 portrait; margin: 14mm; }

    .agr-bar, .notice { display: none !important; }
    .agr-sheet {
        max-width: none; margin: 0; padding: 0;
        box-shadow: none; border: none; font-size: 10.5pt;
    }
    .agr-sec, .agr-party, .agr-close { break-inside: avoid; }
    .agr-table { break-inside: auto; }
    .agr-table tr { break-inside: avoid; }
    .agr-party, .agr-table th, .agr-table tfoot td {
        print-color-adjust: exact; -webkit-print-color-adjust: exact;
    }

    /* The printable width is 182mm ≈ 688px, which trips the ≤700px phone rules above and
       stacks the two-column blocks — so put them back; on paper there is room. */
    .agr-parties, .agr-signs { grid-template-columns: 1fr 1fr; }

    /* And pull the screen spacing back in. The screen sheet scrolls, so it can afford the
       mockups' 48px rhythm; a sheet of A4 cannot. `font-size: 10.5pt` above cannot help —
       every one of these is a rem or a px, anchored to the root, so print never scaled them.
       Without this the contract runs to 2.4 pages and `break-inside: avoid` throws the whole
       signature block onto a third sheet, leaving page two a fifth empty. */
    .agr-head { padding-bottom: 16px; margin-bottom: 26px; }
    /* The letterhead must print — it is the one thing that says whose contract this is.
       Browsers drop background images by default but not <img>, which is why the logo is
       an element rather than a background. It steps down with the rest of the spacing. */
    .agr-logo { width: 58px; height: 58px; print-color-adjust: exact; -webkit-print-color-adjust: exact; }
    .agr-brand { gap: 14px; }
    .agr-head h1 { font-size: 1.7rem; }
    .agr-sec { margin-bottom: 22px; }
    .agr-sec h2 { font-size: 1.15rem; margin-bottom: 12px; padding-bottom: 6px; }
    .agr-parties { gap: 16px; }
    .agr-party { padding: 14px 16px; }
    .agr-party-n { font-size: 1.05rem; }
    .agr-terms > li { margin-bottom: 8px; }
    /* The annexed names must PRINT — they are part of what was agreed. Only the fact that
       they were pressable goes. */
    .agr-annex { text-decoration: none; color: inherit; }
    .agr-table th, .agr-table td { padding: 9px 10px; }
    .agr-close { margin-top: 28px; padding-top: 16px; }
    .agr-witness { margin-bottom: 24px; }
}

/* The agreement used to be a hidden block inside the room, printed by putting a class on
   <body> and injecting an @page rule at print time — a hack that existed only because it
   shared a stylesheet with the workspace's landscape Gantt. It has its own page now
   (agreement.html), so both the block and the hack are gone. */

/* ---- Work breakdown: the checklist as a tree ----
   Rows are one flat list with an indent class, so a sub-item lines up under its parent
   without any nested markup. Every indent is logical (padding-inline-start), which mirrors
   itself in Arabic. */
.pms-item > .pms-item-lbl { flex: 1; min-width: 0; }
.pms-item > .pms-when, .pms-item > .pms-cost, .pms-item > .pms-item-tools { flex: 0 0 auto; }
.pms-item.lvl-2, .pms-subadd.lvl-2, .pms-idates.lvl-2 { padding-inline-start: 26px; }
.pms-item.lvl-3, .pms-subadd.lvl-3, .pms-idates.lvl-3 { padding-inline-start: 52px; }

/* Every row offers the same three things, which on a long checklist is a wall of buttons.
   They step back until the row is pointed at — dimmed, never hidden, so a touch screen
   (which never hovers) can still reach every one of them. */
.pms-item-tools, .pms-cost.ghost { opacity: .4; transition: opacity .15s; }
.pms-item:hover .pms-item-tools, .pms-item:hover .pms-cost.ghost,
.pms-item-tools:focus-within, .pms-cost.ghost:focus { opacity: 1; }

/* An item that was broken down is a mirror of its sub-items, not a button. */
.pms-check.derived { opacity: .5; border-style: dashed; cursor: default; }

/* ---- Renaming: the name IS the control ----
   The label of an editable item is a button wearing no button clothes, so the row looks
   exactly as it did — until it is pointed at, when the pencil comes up beside it. */
.pms-item-lbl.pms-nm {
    display: flex; align-items: center; gap: 6px;
    background: none; border: none; padding: 0;
    font: inherit; color: inherit; text-align: start; cursor: pointer;
}
.pms-item-lbl.pms-nm:hover { color: var(--amber-dark); }
.pms-item.done > .pms-item-lbl.pms-nm:hover { color: var(--amber-dark); }
/* Gap, never margin-inline: the icon font forces direction:ltr on itself, so a logical
   margin resolves to the same physical side in both languages.

   Dimmed, NEVER hidden — the same .4 as the row's other tools twenty lines above, and for
   the same reason: a touch screen never hovers, so a pencil at opacity 0 leaves an
   editable name looking exactly like a read-only one, and the only way to discover it is
   to tap the name and have it turn into a box unasked. */
.pms-nm-pen { font-size: 15px; color: var(--muted); opacity: .4; transition: opacity .15s; }
.pms-item:hover .pms-nm-pen, .pms-item-lbl.pms-nm:focus .pms-nm-pen { opacity: 1; }

/* The box that replaces a name while it is being changed — one shape for both the item
   row and the stage header, so the two feel like the same act. */
.pms-nm-edit { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pms-nm-edit.in-row { flex: 1; min-width: 0; }
.pms-nm-edit.is-stage { padding: 12px 18px; border-bottom: 1px solid var(--line); }
.pms-nm-edit .pms-input { flex: 1; min-width: 140px; }

.pms-item-tools { display: inline-flex; gap: 2px; align-items: center; }
.pms-mini {
    border: none; background: none; cursor: pointer; white-space: nowrap;
    color: var(--muted); font-size: .72rem; padding: 3px 6px; border-radius: 6px;
}
.pms-mini:hover { color: var(--amber); background: var(--surface-3); }
/* The first part of a plan cannot move up and the last cannot move down. Shown greyed and
   inert rather than hidden, so the row of controls keeps the same shape all the way down
   the plan and nothing jumps sideways as parts are reordered. */
.pms-mini:disabled { opacity: .3; cursor: default; }
.pms-mini:disabled:hover { color: var(--muted); background: none; }
.pms-mini .material-symbols-outlined { font-size: 1.05rem; vertical-align: -3px; }
.pms-when { font-size: .72rem; color: var(--muted); white-space: nowrap; }

/* The contractor's private figure — never rendered for anyone else, and never printed. */
.pms-cost {
    font-size: .74rem; font-weight: 700; white-space: nowrap;
    color: #157f56; background: rgba(26, 158, 99, .10);
    border: 1px solid rgba(26, 158, 99, .28); border-radius: 999px; padding: 2px 9px;
}
button.pms-cost { cursor: pointer; }
.pms-cost.ghost {
    color: var(--muted); background: none; font-weight: 600;
    border-style: dashed; border-color: var(--line-2);
}
.pms-cost-edit { display: inline-flex; gap: 6px; align-items: center; }
.pms-cost-edit .pms-input { flex: 0 0 110px; min-width: 90px; padding: 5px 8px; font-size: .8rem; }
.pms-stage-costs { display: inline-block; margin-inline-start: 10px; color: #157f56; font-weight: 700; }

.pms-subadd, .pms-idates {
    display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
    padding: 8px 0; border-bottom: 1px solid var(--line);
}
.pms-subadd .pms-input { min-width: 120px; }
.pms-idates label { display: flex; align-items: center; gap: 6px; font-size: .78rem; color: var(--muted); }

/* ---- Drilling into the timeline: a bar that holds work opens its own chart ---- */
.pms-gantt-lbl.drillable, .pms-item-lbl.drillable { cursor: pointer; }
.pms-gantt-lbl.drillable:hover, .pms-item-lbl.drillable:hover { color: var(--amber); }
.pms-drill-mark { color: var(--amber); font-size: .72rem; }
.pms-gantt-drillhead { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; }
.pms-gantt-none { font-size: .72rem; color: var(--muted); align-self: center; }

/* An item nobody planned individually: drawn in outline across whatever holds it, so it
   still shows how far it has got without pretending to a date it was never given. */
.pms-gantt-bar.unscheduled { background: none; border: 1px dashed var(--line-2); }
.pms-gantt-bar.unscheduled i { opacity: .45; }
.pms-gantt-bar.unscheduled b { color: var(--ink-2); }

/* ============================================================================
   THE LEGAL PAGES — privacy.html and disclaimer.html
   ============================================================================
   Both pages carry their whole text TWICE, once per language, and CSS shows one.
   No JavaScript decides this: the inline script in every page's <head> already sets
   html[lang] before the body paints, and BF.setLang() rewrites the same attribute, so
   the right language is correct on the first frame AND switches live with no flash and
   no redraw. The alternative — putting legal prose through the strings table — would
   have added several kilobytes to the bundle that EVERY page of the site downloads,
   for two pages almost nobody opens twice.

   Master copies of both texts: Documents/BuildFinder-Privacy-Policy.md and
   Documents/BuildFinder-Disclaimer.md. Change those first, then re-bake the pages. */
html[lang="ar"] .lg-en,
html[lang="en"] .lg-ar { display: none; }

.legal-doc {
    /* Legal text is read, not scanned. Capping the measure at ~68 characters is what
       makes that possible on a wide screen — the site's other cards are sized for
       forms and tables, which is why this cannot just reuse .card's width. */
    max-width: 68ch;
    margin-inline: auto;
    padding: 28px 24px 34px;
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-2);
}
.legal-doc h1 { font-size: 1.6rem; color: var(--ink); margin: 0 0 6px; }
.legal-updated {
    font-size: .82rem; color: var(--muted); margin: 0 0 22px;
    padding-bottom: 18px; border-bottom: 1px solid var(--line);
}
.legal-lede { font-size: .98rem; color: var(--ink-2); margin: 0 0 26px; line-height: 1.85; }
.legal-doc h2 {
    font-size: 1.06rem; color: var(--ink); margin: 26px 0 10px;
    display: flex; gap: 9px; align-items: baseline;
}
/* The clause number, kept out of the heading text so it can never be translated,
   re-ordered by the bidirectional algorithm, or read aloud as part of the sentence. */
.legal-doc h2 > b {
    flex: none; min-width: 1.4em; color: var(--amber-dark);
    font-size: .95rem; font-variant-numeric: tabular-nums;
}
.legal-doc p, .legal-doc li { color: var(--ink-2); line-height: 1.9; font-size: .93rem; }
.legal-doc p { margin: 0 0 12px; }
.legal-doc ul { margin: 0 0 12px; padding-inline-start: 22px; }
.legal-doc li { margin-bottom: 8px; }
.legal-doc strong { color: var(--ink); font-weight: 700; }
.legal-doc a { color: var(--amber-dark); }
@media (max-width: 600px) {
    .legal-doc { padding: 22px 18px 26px; border-radius: var(--radius-sm); }
    .legal-doc h1 { font-size: 1.35rem; }
}

/* ---- The small-print lines that point at those two pages ----
   Used under the Create-account button, at the foot of a project workspace, under the
   request form, and beside the Accept button in the deal room. Muted on purpose: it must
   be findable and never compete with the action it sits beneath. */
.legal-note {
    /* NOT flex-wrap: wrap. With wrapping on, a sentence this long is wider than a narrow
       card (the deal room's quote column), so the browser moves the whole text onto a
       second flex line and strands the glyph alone above it. Without wrapping the text
       shrinks and wraps inside itself instead, which is what "icon, then paragraph" means. */
    display: flex; align-items: flex-start; gap: 7px;
    margin: 14px 0 0; font-size: .8rem; line-height: 1.7; color: var(--muted);
}
.legal-note .ms, .legal-note .material-symbols-outlined {
    font-size: 1.05rem; flex: none; color: var(--ink-3); margin-top: 1px;
}
/* The text beside the glyph: allowed to shrink below its longest line. */
.legal-note > :not(.ms):not(.material-symbols-outlined) { min-width: 0; }
.legal-note a { color: var(--ink-2); text-decoration: underline; }
.legal-note a:hover { color: var(--amber-dark); }
/* At the foot of a long page it gets a rule above it, so it reads as the page's small
   print rather than as a stray sentence after the last card. */
.legal-foot {
    justify-content: center; text-align: center;
    margin-top: 26px; padding-top: 16px; border-top: 1px solid var(--line);
}

/* The pair of links in the home page's footer — the only way back to either page for
   somebody who is already signed in and so never sees the registration form again. */
.footer-legal { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 12px; }
.footer-legal a {
    color: var(--muted); font-size: .85rem; font-weight: 600; text-decoration: underline;
}
.footer-legal a:hover { color: var(--amber-dark); }

/* ============================================================================
   test01.html — the fixture dashboard (DEVELOPMENT ONLY)
   ============================================================================
   Goes when the page goes. Nothing else on the site uses these rules. */
.tf-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 20px; flex-wrap: wrap; margin-bottom: 18px;
}
/* Allowed to shrink, so the reset button stays on the same line as the title instead of
   being pushed under it once the sub-heading grew. */
.tf-head > div:first-child { flex: 1 1 420px; min-width: 0; }
/* Scoped to .tf-head on purpose. `.section-sub` is used on nearly every page of the site
   and carries no size of its own, so setting one unscoped here would quietly enlarge the
   sub-heading on the home page, the calculator and everything else. */
.tf-head .section-sub { font-size: 1.12rem; line-height: 1.7; }
/* The reset button follows you down a long page — it is the only thing here to press,
   and hunting for it back at the top would be the page's main annoyance. */
.tf-actions {
    position: sticky; top: 14px; z-index: 5;
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.tf-file { font-size: .74rem; color: var(--muted); }
/* Stacks the loud reset button over the quiet "what's new" button, so the second, minor
   action sits under the first instead of competing with it for width. */
.tf-action-btns { display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
.tf-action-btns .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; }
.tf-action-btns .btn .material-symbols-outlined { font-size: 1.05rem; }

.tf-auth { padding: 18px 20px; margin-bottom: 18px; border-inline-start: 4px solid var(--amber); }
.tf-auth p { margin: 0 0 12px; font-size: .88rem; color: var(--ink-2); }
.tf-auth-row { display: flex; gap: 10px; flex-wrap: wrap; }
.tf-auth-row input {
    flex: 1 1 220px; min-width: 0; padding: 10px 14px;
    border: 1px solid var(--line-2); border-radius: var(--radius-box); background: var(--card);
}

.tf-h2 { font-size: 1.1rem; color: var(--ink); margin: 30px 0 4px; }
.tf-count {
    display: inline-block; min-width: 28px; padding: 3px 10px; margin-inline-start: 8px;
    background: var(--surface-3); color: var(--ink-3); border-radius: 999px;
    font-size: .95rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
.tf-hint { font-size: 1rem; color: var(--muted); margin: 0 0 14px; line-height: 1.7; }

/* The table scrolls inside its own card rather than pushing the page sideways. */
.tf-wrap { padding: 0; overflow-x: auto; }
.tf-table { width: 100%; border-collapse: collapse; min-width: 760px; }
/* Everything in these tables reads a size up from the site's small print, because this is
   a page you scan rather than a card you read — the one exception is the villa's own name
   below, which was already the largest thing in the row and needs no help. The padding
   grows with it: the same 12px around bigger text reads as cramped. */
.tf-table th {
    text-align: start; font-size: .88rem; font-weight: 800; text-transform: uppercase;
    letter-spacing: .04em; color: var(--ink-3);
    padding: 15px 17px; border-bottom: 1px solid var(--line); background: var(--surface-2);
    white-space: nowrap;
}
.tf-table td { padding: 15px 17px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tf-table tr:last-child td { border-bottom: 0; }

.tf-row { cursor: pointer; transition: background .12s ease; }
.tf-row:hover, .tf-row:focus-visible { background: var(--surface-2); outline: none; }
.tf-row:focus-visible { box-shadow: inset 0 0 0 2px var(--amber); }
.tf-row:hover .tf-chev { color: var(--amber-dark); transform: translateX(-3px); }
html[dir="ltr"] .tf-row:hover .tf-chev { transform: translateX(3px); }

.tf-n {
    width: 48px; color: var(--ink-3); font-weight: 800;
    font-size: 1.02rem; font-variant-numeric: tabular-nums;
}
/* The two sizes deliberately left alone — the villa's name and the row number. Everything
   around them has been taken up twice at the owner's request, which means the name is now
   SMALLER than the line beneath it and carries its weight through boldness and ink colour
   instead of size. That is the owner's call, made knowingly; do not "fix" it silently. */
.tf-about b { display: block; color: var(--ink); font-size: .92rem; margin-bottom: 3px; }
.tf-about span { display: block; font-size: .99rem; color: var(--muted); line-height: 1.6; }
.tf-next { font-size: .99rem; color: var(--ink-2); line-height: 1.6; max-width: 300px; }
.tf-state { white-space: nowrap; }
.tf-pct {
    display: inline-block; margin-inline-start: 8px; font-size: .95rem;
    font-weight: 800; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.tf-go { width: 1%; white-space: nowrap; text-align: end; }
.tf-second { font-size: .92rem; color: var(--muted); text-decoration: underline; margin-inline-end: 12px; }
.tf-second:hover { color: var(--amber-dark); }
.tf-chev { color: var(--line-2); font-size: 1.48rem; vertical-align: middle; transition: all .12s ease; }
/* The glyph font forces direction: ltr so its ligature renders, so this arrow has to be
   flipped by hand — chevron_left points the right way in Arabic and the wrong way in
   English. Same trap as the auth-page field icons. */
html[dir="ltr"] .tf-chev { transform: scaleX(-1); }

.tf-badge {
    display: inline-block; padding: 5px 13px; border-radius: 999px;
    font-size: .9rem; font-weight: 800; white-space: nowrap;
    background: var(--surface-3); color: var(--ink-2);
}
/* Colour carries the meaning at a glance: amber = waiting on somebody, blue = an offer
   or a claim is on the table, green = money or work confirmed, red = refused, grey = over. */
.tf-pending, .tf-discussion, .tf-submitted { background: var(--amber-soft); color: var(--amber-dark); }
.tf-quoted, .tf-approved, .tf-paid        { background: var(--verified-bg); color: var(--verified-fg); }
.tf-active, .tf-confirmed                 { background: var(--licensed-bg); color: var(--licensed-fg); }
.tf-declined, .tf-rejected                { background: var(--red-bg); color: var(--red); }
.tf-completed                             { background: #e8f5e9; color: #1b5e20; }
.tf-on_hold                               { background: var(--surface-3); color: var(--ink-2); }
.tf-cancelled                             { background: var(--surface-3); color: var(--muted); }

/* ---- The sign-in credentials, at the top of the page ----
   Amber rather than grey: on a page handed to somebody who has never seen the site, this
   is the first thing they need and the one line that must not be skimmed past. */
.tf-login-note {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin: 0 0 20px; padding: 12px 16px;
    background: var(--amber-soft); border: 1px solid var(--amber);
    border-radius: var(--radius-box);
    font-size: 1rem; line-height: 1.7; color: var(--ink);
}
.tf-login-note .material-symbols-outlined { font-size: 1.25rem; color: var(--amber-dark); flex: none; }
.tf-cred {
    display: inline-block; margin: 0 5px; padding: 2px 10px;
    background: var(--card); border: 1px solid var(--amber); border-radius: 999px;
    font-weight: 800; font-size: .95rem;
    /* User-select so a tester can copy them straight out. */
    user-select: all;
}

/* ---- The sign-in gate ---- */
.tf-gate { padding: 26px 24px; text-align: center; }
.tf-gate p { font-size: 1.05rem; color: var(--ink-2); margin: 0 0 16px; }
.tf-creds { font-size: 1rem; }

/* ---- Notes: the button on each row ---- */
.tf-notecell { width: 1%; white-space: nowrap; text-align: center; }
.tf-note-btn {
    position: relative; display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 38px; padding: 0; cursor: pointer;
    border: 1px solid var(--line-2); border-radius: var(--radius-box);
    background: var(--card); color: var(--ink-3);
    transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.tf-note-btn:hover { background: var(--amber-soft); color: var(--amber-dark); border-color: var(--amber); }
.tf-note-btn .material-symbols-outlined { font-size: 1.3rem; }
/* A row that already carries feedback should say so without being opened. */
.tf-note-btn.has { background: var(--amber-soft); color: var(--amber-dark); border-color: var(--amber); }
.tf-badge-n {
    position: absolute; top: -7px; inset-inline-end: -7px;
    min-width: 20px; height: 20px; padding: 0 5px;
    display: flex; align-items: center; justify-content: center;
    background: var(--ink); color: #fff; border-radius: 999px;
    font-size: .72rem; font-weight: 800; font-variant-numeric: tabular-nums;
}

/* ---- Notes: the dialog ----
   A real <dialog>, so the modal behaviour, the Escape key and the focus trap come from
   the browser rather than from three hundred lines of our own. */
.tf-modal {
    width: min(660px, 94vw); max-height: 88vh; padding: 0;
    border: 0; border-radius: var(--radius); background: var(--card);
    box-shadow: var(--shadow-3); color: var(--ink);
    /* Centred by hand. A modal <dialog> is centred by the browser through `inset: 0` plus
       `margin: auto`, and giving it an explicit width is enough to leave it stuck against
       the inline-start edge — which in an RTL page is the right-hand side. */
    inset: 0; margin: auto;
}
.tf-modal::backdrop { background: rgba(10, 25, 47, .55); }
.tf-modal-in { display: flex; flex-direction: column; max-height: 88vh; }
.tf-modal-head {
    display: flex; align-items: flex-start; gap: 14px; justify-content: space-between;
    padding: 22px 24px 16px; border-bottom: 1px solid var(--line);
}
.tf-modal-head h2 { margin: 0 0 4px; font-size: 1.2rem; color: var(--ink); }
.tf-modal-head p { margin: 0; font-size: .9rem; color: var(--muted); line-height: 1.6; }
.tf-x {
    flex: none; width: 36px; height: 36px; display: flex; align-items: center;
    justify-content: center; cursor: pointer;
    border: 0; border-radius: 999px; background: var(--surface-3); color: var(--ink-2);
}
.tf-x:hover { background: var(--red-bg); color: var(--red); }

/* The thread scrolls; the form under it never leaves the screen. */
.tf-notes { flex: 1 1 auto; overflow-y: auto; padding: 16px 24px; min-height: 90px; }
.tf-none { font-size: .95rem; color: var(--muted); text-align: center; padding: 18px 0; margin: 0; }
.tf-note {
    padding: 12px 14px; margin-bottom: 10px;
    background: var(--surface-2); border-radius: var(--radius-box);
    border-inline-start: 3px solid var(--line-2);
}
.tf-note header { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.tf-note header b { font-size: .92rem; color: var(--ink); }
.tf-note header time { font-size: .78rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.tf-note-del {
    margin-inline-start: auto; border: 0; background: none; cursor: pointer;
    font-size: .78rem; color: var(--muted); text-decoration: underline; padding: 0;
}
.tf-note-del:hover { color: var(--red); }
.tf-note p { margin: 0; font-size: .95rem; line-height: 1.75; color: var(--ink-2); white-space: pre-wrap; }

.tf-note-form { padding: 16px 24px 22px; border-top: 1px solid var(--line); background: var(--surface-2); }
.tf-note-form input, .tf-note-form textarea {
    width: 100%; padding: 11px 14px; margin-bottom: 10px;
    border: 1px solid var(--line-2); border-radius: var(--radius-box);
    background: var(--card); color: var(--ink); font: inherit; font-size: .95rem;
}
.tf-note-form textarea { resize: vertical; min-height: 84px; line-height: 1.7; }
.tf-note-form input:focus, .tf-note-form textarea:focus {
    outline: none; border-color: var(--amber); box-shadow: 0 0 0 3px var(--amber-soft);
}
.tf-who { max-width: 260px; }
.tf-note-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tf-left { font-size: .85rem; color: var(--muted); }

/* ---- Notes: the two panes ----
   The list of issues on a villa, and one of them opened as a conversation. Only one is in
   the page at a time — the other is `hidden`, not merely pushed off the side — so the
   dialog is always the height of what you are actually reading, and nothing off-screen can
   be reached by Tab or read out by a screen reader. `overflow: hidden` on the box is what
   lets the arriving pane slide in from beyond its edge without widening the page. */
.tf-modal-in { overflow: hidden; }
.tf-pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; max-height: 88vh; }
/* Focus lands on these headings when a pane arrives, and a ring round a title reads as a
   mistake — the pane changing IS the feedback. */
#dlgTitle:focus, #thTitle:focus, #updTitle:focus { outline: none; }

/* The conversation always arrives from the RIGHT and the list always comes back from the
   LEFT — in BOTH languages, not mirrored. That follows from the header below: the back
   button and the close button keep the same physical corners in Arabic as in English, so the
   motion has to agree with them or a left-hand back button would undo a leftward slide.
   translateX is physical (positive is always rightwards, whatever the writing direction),
   which is exactly why no per-direction override belongs here. */
@keyframes tf-from-right { from { transform: translateX(100%);  opacity: .25; } }
@keyframes tf-from-left  { from { transform: translateX(-100%); opacity: .25; } }
.tf-in-fwd  { animation: tf-from-right .26s cubic-bezier(.22, .61, .36, 1) both; }
.tf-in-back { animation: tf-from-left  .26s cubic-bezier(.22, .61, .36, 1) both; }
@media (prefers-reduced-motion: reduce) {
    .tf-in-fwd, .tf-in-back { animation: none; }
}

.tf-thread-head { align-items: center; }
.tf-thread-id { flex: 1 1 auto; min-width: 0; }
.tf-thread-id h2 { margin: 0 0 5px; font-size: 1.05rem; }
.tf-thread-id p { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.tf-back {
    flex: none; width: 36px; height: 36px; display: flex; align-items: center;
    justify-content: center; cursor: pointer;
    border: 0; border-radius: 999px; background: var(--surface-3); color: var(--ink-2);
}
.tf-back:hover { background: var(--amber-soft); color: var(--amber-dark); }

/* ---- THE HEADER IS THE ONE THING NOT MIRRORED ----
   The owner's instruction, 2026-08-25: the ✕ and the back arrow must sit in the SAME PLACE
   in Arabic as in English — back at the top-left, close at the top-right — instead of
   swapping sides with the language.

   Reversing the row is what does it. In an RTL page a reversed row runs left-to-right, so
   the DOM order (back · title · close) lands physically the same way round as it does in
   English; and because visual order then matches DOM order, Tab still moves the way the eye
   reads the header.

   Three things follow from it, and all three are deliberate:
     - `arrow_back` is NOT flipped any more. It used to be turned round for Arabic, where
       back is rightwards — but a right-pointing arrow in the top-LEFT corner reads as
       "next". The button's corner now decides the arrow, not the language.
     - The panes slide the same way in both languages (see the keyframes above).
     - The title travels with them, so its box is aligned to the left as well. `direction` is
       deliberately untouched: the Arabic still renders right-to-left inside its own box —
       only the box is aligned to the other edge.
   Everything below this header stays Arabic-first: the notes, the replies, the buttons. */
html[dir="rtl"] .tf-modal-head { flex-direction: row-reverse; }
html[dir="rtl"] .tf-modal-head h2,
html[dir="rtl"] .tf-modal-head > div > p { text-align: left; }
/* That sub-line is a flex row in the conversation pane, where text-align does nothing —
   flex-end is the left-hand edge on an RTL page. */
html[dir="rtl"] .tf-thread-id p { justify-content: flex-end; }

/* ---- Notes: one issue in the list ---- */
.tf-thread {
    display: block; width: 100%; text-align: start; cursor: pointer; font: inherit;
    padding: 12px 14px; margin-bottom: 10px; color: inherit;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--radius-box);
    transition: background .12s ease, border-color .12s ease;
}
.tf-thread:hover { background: var(--card); border-color: var(--amber); }
.tf-thread:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.tf-thread-top {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 8px;
}
.tf-thread-n {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: .82rem; color: var(--muted); white-space: nowrap;
}
.tf-thread-n .material-symbols-outlined { font-size: 1.05rem; }
/* Two lines and no more: the card says what the issue is, the conversation says the rest. */
.tf-thread-text {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; margin-bottom: 6px;
    font-size: .95rem; line-height: 1.7; color: var(--ink-2);
}
.tf-thread-by { display: block; font-size: .78rem; color: var(--muted); }

/* ---- Notes: the conversation ----
   A timeline, not chat bubbles. Everybody testing signs in as user1, so "mine on the right,
   theirs on the left" would be inventing a distinction the data cannot support: who wrote a
   message is the name they typed, and it is printed beside every one of them. */
.tf-msg { display: flex; gap: 10px; padding: 12px 0; }
.tf-msg + .tf-msg { border-top: 1px solid var(--line); }
.tf-msg-report {
    padding: 12px 14px; margin-bottom: 4px;
    background: var(--surface-2); border-radius: var(--radius-box);
    border-inline-start: 3px solid var(--amber);
}
.tf-msg-report + .tf-msg { border-top: 0; }
.tf-avatar {
    flex: none; width: 32px; height: 32px; border-radius: 999px;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-3); color: var(--ink-2); font-weight: 800; font-size: .9rem;
}
.tf-msg-body { flex: 1 1 auto; min-width: 0; }
.tf-msg-body header {
    display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 5px;
}
.tf-msg-body header b { font-size: .9rem; color: var(--ink); }
.tf-msg-body time { font-size: .76rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.tf-msg-body p { margin: 0; font-size: .95rem; line-height: 1.75; color: var(--ink-2); white-space: pre-wrap; }
/* Written from the administrator account. Stamped when the reply was saved, not worked out
   now — "the owner said this" has to stay true whatever happens to the account later. */
.tf-owner {
    padding: 2px 8px; border-radius: 999px; background: var(--ink); color: #fff;
    font-size: .68rem; font-weight: 800;
}
.tf-set {
    display: inline-flex; align-items: center; gap: 5px; margin-bottom: 6px;
    padding: 3px 11px; border-radius: 999px; font-size: .8rem; font-weight: 800;
}
.tf-set .material-symbols-outlined { font-size: 1rem; }

.tf-acts { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.tf-act { font-size: .85rem; padding: 8px 14px; white-space: nowrap; }

/* ---- Notes: the summary over all 23 villas ---- */
.tf-sum { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; margin: 0 0 20px; }
.tf-sum-i {
    display: inline-flex; align-items: center; gap: 5px; padding: 5px 12px;
    border-radius: 999px; background: var(--surface-3); color: var(--ink-2);
    font-size: .9rem; font-weight: 700;
}
.tf-sum-i .material-symbols-outlined { font-size: 1.1rem; }

/* ---- The four colours an issue can wear ----
   Deliberately NOT reusing .tf-confirmed and friends above: those are the colours of a
   PAYMENT, and one of them shares a name with one of these by coincidence. Two unrelated
   meanings on one class is a bug waiting for whichever changes first.
   Amber = somebody has to do something, blue = a claim is on the table, green = agreed and
   over, red = it is broken again. Written after .tf-badge and .tf-sum-i so it wins on both.
   Laid out with flex `gap` rather than a margin on the glyph. A margin would have to be
   margin-inline-END — because .material-symbols-outlined forces direction: ltr on itself,
   so its own inline-end is the right-hand side in BOTH languages, and in Arabic the word
   sits on its left. `gap` has no side at all. Same trap as .tf-chev and the back arrow;
   this is the third place it has come up. */
.tf-badge .material-symbols-outlined { font-size: 1.02rem; }
.tf-s-open, .tf-s-fixed, .tf-s-confirmed, .tf-s-reopened {
    display: inline-flex; align-items: center; gap: 5px;
}
.tf-s-open      { background: var(--amber-soft);  color: var(--amber-dark); }
.tf-s-fixed     { background: var(--verified-bg); color: var(--verified-fg); }
.tf-s-confirmed { background: var(--licensed-bg); color: var(--licensed-fg); }
.tf-s-reopened  { background: var(--red-bg);      color: var(--red); }

/* The row's button wears whatever most needs attention on that villa, so the board can be
   read down the notes column without opening anything. */
.tf-note-btn.tf-w-fixed     { background: var(--verified-bg); color: var(--verified-fg); border-color: var(--verified-fg); }
.tf-note-btn.tf-w-confirmed { background: var(--licensed-bg); color: var(--licensed-fg); border-color: var(--licensed-fg); }
.tf-note-btn.tf-w-reopened  { background: var(--red-bg);      color: var(--red);         border-color: var(--red); }

/* ---- What's new: a short, static, owner-edited bulletin (UPDATES in app.js) ---- */
.tf-updates { flex: 1 1 auto; overflow-y: auto; padding: 6px 24px 22px; }
.tf-upd-item { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; }
.tf-upd-item + .tf-upd-item { border-top: 1px solid var(--line); }
.tf-upd-icon {
    flex: none; width: 30px; height: 30px; margin-top: 1px; border-radius: 999px;
    display: flex; align-items: center; justify-content: center;
}
.tf-upd-icon .material-symbols-outlined { font-size: 1.05rem; }
.tf-upd-item p { margin: 0; font-size: .95rem; line-height: 1.75; color: var(--ink-2); }
/* Same four tokens the note statuses use, under their own names — a changelog entry and an
   issue's status are two different ideas, and coupling their classes would break the moment
   either one changes (see the note above .tf-s-open and friends). */
.tf-upd-feature  { background: var(--verified-bg); color: var(--verified-fg); }
.tf-upd-fix      { background: var(--red-bg);      color: var(--red); }
.tf-upd-improve  { background: var(--amber-soft);  color: var(--amber-dark); }
.tf-upd-design   { background: var(--licensed-bg); color: var(--licensed-fg); }

@media (max-width: 700px) {
    /* The payments table already scrolls sideways on a phone, so every pixel the Action
       column gains is a pixel further to scroll before the client can reach Approve. Now
       that the claim document sits there too, the buttons stack instead of queueing: the
       column is as wide as its widest button rather than the sum of three.

       SCOPED to the payments cell, not to .pms-row-actions alone. The Documents tab uses
       that same class for a plain div in a row that does NOT scroll sideways, and stacking
       it there took every document row from 62.8px to 97.8px on a phone — a screen this
       change has no business touching. .pms-cell-actions exists on the payments <td> and
       nowhere else. */
    .pms-cell-actions .pms-row-actions { flex-direction: column; align-items: stretch; }
    .pms-cell-actions .pms-row-actions .btn { width: 100%; }
    /* The "take a whole line" basis is about the row direction; stacked it would be read as
       a height, so it is handed back to the content. */
    .pms-cell-actions .pms-row-actions .pms-gate { flex-basis: auto; }

    .tf-actions { position: static; }
    .tf-next { display: none; }          /* the row still opens the screen that explains it */
    .tf-modal { width: 100vw; max-width: 100vw; max-height: 92vh; border-radius: 0; }
    .tf-pane { max-height: 92vh; }
    .tf-who { max-width: none; }
    /* Full-width buttons rather than three cramped ones sharing a line. */
    .tf-note-actions { flex-wrap: wrap; }
    .tf-acts { width: 100%; }
    .tf-act { flex: 1 1 auto; }
}

/* ---- Printing: the timeline and the numbers, nothing else ---- */
@media print {
    /* NAMED, so it cannot become the whole stylesheet's default and turn the agreement
       sideways — which is exactly what the bare version of this rule used to do. The
       agreement keeps the unnamed `@page`, because if a browser ever ignores named pages
       the wrong outcome is a cramped chart, not a contract printed landscape. */
    @page chart { size: A4 landscape; margin: 12mm; }
    /* By id, not by `.pms-panel` — the deal room's cards carry that class too, and naming it
       here would print the negotiation room sideways as well. These six ids exist only in
       project.html. */
    #panel-dash, #panel-stages, #panel-time,
    #panel-money, #panel-docs, #panel-tasks { page: chart; }

    .site-header, .site-footer, .pms-tabs, .pms-head-actions,
    .pms-addrow, .pms-row-actions, #editCard, .notice { display: none !important; }
    /* A printout is the easiest thing in the world to hand across a table. */
    .pms-cost, .pms-cost-edit, .pms-stage-costs, .pms-item-tools { display: none !important; }
    /* The names print; the pencils that change them do not. */
    .pms-stage-edit, .pms-nm-pen { display: none !important; }

    /* A figure and the one it replaced are both facts about the payment and both print —
       a printed ledger that hid a price change would be the wrong record to hand across a
       table. The Confirm button and the dialog are controls, and do not. */
    .pms-amt-ok, .pms-dlg { display: none !important; }
    .pms-amt-link { border: 0; color: inherit; font-weight: 700; }

    /* The payments cell is hidden with the rest, EXCEPT the payment's documents — the
       invoice and the receipt, which are facts about the payment, not controls. Without
       this the ledger printed the red "sent without an invoice" for rows that have none
       and nothing at all for rows that do: it advertised the absence and hid the presence.
       They print as plain text, since a button on paper is a thing nobody can press. */
    .pms-cell-actions .pms-row-actions { display: flex !important; }
    .pms-cell-actions .btn, .pms-cell-actions .pms-gate { display: none !important; }
    .pms-cell-actions .pms-btn-doc {
        display: inline-flex !important;
        border: none; background: none; padding: 0; font-weight: 600;
    }
    .pms-panel[hidden] { display: block !important; }
    .pms-gantt-wrap { overflow: visible; }
    .pms-gantt { min-width: 0; }
    .card, .pms-kpi { border: 1px solid #999; box-shadow: none; break-inside: avoid; }
    .pms-gantt-bar, .pms-bar i, .pms-ring {
        print-color-adjust: exact; -webkit-print-color-adjust: exact;
    }
}

/* ---- tutorial.html — the how-to guide ----
   The welcome dialog and the role switch are fully reused (.pms-dlg, .pms-tabs/.pms-tab) —
   everything below is genuinely new, kept under its own .tut- prefix. */
.tut-acc {
    background: var(--card); border-radius: 14px;
    box-shadow: var(--ring), var(--shadow-2);
    margin-bottom: 12px; overflow: hidden;
}
.tut-acc-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 16px 20px; cursor: pointer; list-style: none;
}
.tut-acc-head::-webkit-details-marker { display: none; }
.tut-acc-head::after { content: '+'; font-weight: 800; color: var(--amber-dark); flex: 0 0 auto; }
.tut-acc[open] .tut-acc-head::after { content: '\2212'; }
.tut-acc-tx { display: flex; align-items: center; gap: 12px; font-weight: 700; font-size: .98rem; color: var(--ink); }
.tut-acc-tx .material-symbols-outlined { font-size: 22px; color: var(--amber-dark); flex: 0 0 auto; }
.tut-acc-n {
    flex: 0 0 auto; font-size: .74rem; font-weight: 700; color: var(--muted);
    background: var(--surface-2); border-radius: 999px; padding: 3px 10px;
}
.tut-steps { border-top: 1px solid var(--line); }
.tut-step {
    display: flex; flex-direction: column; gap: 14px;
    padding: 24px 20px;
}
.tut-step + .tut-step { border-top: 1px dashed var(--line); }
.tut-step-tx { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.tut-step-n {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 999px; flex: 0 0 auto;
    background: var(--ink); color: var(--amber); font-size: .78rem; font-weight: 800;
}
.tut-step-tx h3 { margin: 2px 0 0; font-size: .96rem; color: var(--ink); }
.tut-step-tx p { margin: 0; font-size: .88rem; line-height: 1.75; color: var(--ink-2); }
.tut-step-fig {
    margin: 0 auto; width: 100%; max-width: 860px;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    overflow: hidden; background: var(--surface-2); box-shadow: var(--shadow-2);
}
.tut-step-fig img { display: block; width: 100%; height: auto; }

/* Applied to one element right before a tutorial screenshot is captured — never seen live,
   only in the pictures themselves, so it stays on the page rather than injected per shot. */
.tut-shot-highlight {
    outline: 3px solid var(--amber); outline-offset: 3px;
    box-shadow: 0 0 0 8px var(--amber-soft); border-radius: var(--radius-sm);
}


/* ---- A photo of the finished work, on a ticked checklist item ----
   Sits between the item's cost and its tools. Always visible once it exists — it is the
   evidence the client came to look at, not a power-user tool — so unlike .pms-item-tools it
   does not dim until the row is pointed at. */
.pms-item > .pms-proof { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 2px; }
.pms-proof-btn {
    display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
    font: inherit; font-size: .74rem; font-weight: 700; white-space: nowrap;
    padding: 4px 10px; border-radius: 999px; border: 1px solid var(--line-2);
    background: var(--card); color: var(--ink-2);
}
.pms-proof-btn .material-symbols-outlined { font-size: 16px; }
.pms-proof-btn.has { background: var(--amber-soft); border-color: var(--amber); color: var(--amber-dark); }
.pms-proof-btn:hover { border-color: var(--amber); color: var(--amber-dark); }
.pms-proof .pms-mini { cursor: pointer; display: inline-flex; align-items: center; }
@media (max-width: 560px) {
    /* On a phone the row wraps; the photo button takes its own line rather than squeezing the name. */
    .pms-item { flex-wrap: wrap; }
    .pms-item > .pms-proof { flex: 1 0 100%; margin-inline-start: 38px; }
}
