/* =============================================================================
   blueprint.css — the CMS component layer
   Consumes blueprint-tokens.css and nothing else. Loaded only by
   layouts/cms.blade.php, which loads no legacy stylesheet, so nothing here can
   reach a screen that has not been migrated.

   Authored from docs/design-brief/design_handoff_cms/prototypes/CMS App.dc.html.
   That prototype is a design-tool export: its styling lives in inline `style`
   attributes, so it cannot be copied — every rule below is the same value
   expressed as a real class. Where the handoff and the prototype disagree the
   handoff wins; where the prototype shows a value the handoff does not name
   (badge sizes, the AI card's three states) the prototype is the source.

   Rules the design is strict about, and this file enforces:
     · surfaces have NO border — depth is --shadow-1 and nothing else;
     · radii are 14 input / 16 card / 20 panel / 24 hero / 999 pill;
     · --cms-accent (#FFB800) means exactly three things — critical path,
       AI proposal, primary on-site action. It is never decoration;
     · the blueprint grid goes on navy surfaces and the page background,
       never behind a table;
     · Georgian text is never uppercased and never letter-spaced. There is no
       `text-transform` in this file, and that is deliberate.

   Sections
     1  base + animations
     2  layout shell (rail, header, main)
     3  buttons + inputs
     4  surfaces (card, hero, panel)
     5  pills, badges, avatars
     6  numbers + progress
     7  data table + grouped list
     8  overlays (panel, modal, sheet, dropdown, palette, toast)
     9  states (skeleton, empty, error)
    10  AI proposal card
    11  responsive: tablet (<=1100) and narrow (<=820)
    12  print
   ========================================================================== */

/* ── 1. base ──────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
    font-family: var(--font-ui);
    font-variant-numeric: tabular-nums;   /* figures line up in every column */
    color: var(--ink);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    scrollbar-width: none;
}
html::-webkit-scrollbar { display: none; }

body {
    margin: 0;
    font-size: var(--fs-14);
    line-height: var(--lh-body);
    background: var(--bg);
    color: var(--ink);
}

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

button { font-family: inherit; cursor: pointer; border: 0; background: none; color: inherit; }

/* Every overlay below sets its own `display`, and a `display` declaration beats
   the `hidden` attribute's UA `display:none` — so without this, every panel,
   modal, sheet and palette in the document renders on page load. blueprint.js
   opens and closes them by toggling `hidden`, which makes this rule the thing
   that makes them closed at all. */
[hidden] { display: none !important; }

/* The focus ring is the accent on purpose: it is the one place the yellow is
   allowed outside its three meanings, because an invisible focus ring fails AA
   and a blue one disappears against --primary. */
:focus-visible { outline: 3px solid var(--cms-accent); outline-offset: 2px; }

.bp-mono { font-family: var(--font-mono); }
.bp-muted { color: var(--muted); }
.bp-sr {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* The blueprint grid. Two 1px gradients at --grid-step; the navy variant
   carries its own background colour and the lighter line. */
.bp-grid-bg {
    background-image:
        linear-gradient(var(--grid) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid) 1px, transparent 1px);
    background-size: var(--grid-step) var(--grid-step);
}
.bp-navy-grid {
    background-color: var(--cms-navy);
    color: #fff;
    background-image:
        linear-gradient(var(--grid-line-on-navy) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line-on-navy) 1px, transparent 1px);
    background-size: var(--grid-step) var(--grid-step);
}
.bp-navy-grid--sm { background-size: var(--grid-step-sm) var(--grid-step-sm); }

@keyframes bp-rise    { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes bp-fade    { from { opacity: 0; } to { opacity: 1; } }
@keyframes bp-slide-in{ from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }
@keyframes bp-sheet   { from { transform: translateY(100%); } to { transform: none; } }
@keyframes bp-pop     { 0% { transform: scale(.96); } 60% { transform: scale(1.02); } 100% { transform: none; } }
@keyframes bp-grow    { from { width: 0; } }
@keyframes bp-toast-in{ from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }

.bp-anim-rise  { animation: bp-rise  var(--dur-slow) var(--ease-out) both; }
.bp-anim-fade  { animation: bp-fade  var(--dur-slow) var(--ease-out) both; }
.bp-anim-pop   { animation: bp-pop   var(--dur-slow) var(--ease-out) both; }

/* Page load staggers in 50ms steps. Six are enough for any screen's top row;
   past that the eye stops reading it as a sequence. */
.bp-stagger > *              { animation: bp-rise .5s var(--ease-out) both; }
.bp-stagger > *:nth-child(1) { animation-delay: .05s; }
.bp-stagger > *:nth-child(2) { animation-delay: .10s; }
.bp-stagger > *:nth-child(3) { animation-delay: .15s; }
.bp-stagger > *:nth-child(4) { animation-delay: .20s; }
.bp-stagger > *:nth-child(5) { animation-delay: .25s; }
.bp-stagger > *:nth-child(6) { animation-delay: .30s; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

/* ── 2. layout shell ──────────────────────────────────────────────────── */

.bp-shell {
    min-height: 100vh;
    display: grid;
    grid-template-columns: var(--rail) minmax(0, 1fr);
    /* The blueprint grid belongs to the shell, not to <body>: the shell paints
       its own background over the whole viewport, so a grid on the body behind
       it is never seen. */
    background-color: var(--bg);
    background-image:
        linear-gradient(var(--grid) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid) 1px, transparent 1px);
    background-size: var(--grid-step) var(--grid-step);
    color: var(--ink);
    font-size: var(--fs-14);
    position: relative;
    overflow-x: clip;
    transition: background var(--dur-slow), color var(--dur-slow),
                grid-template-columns var(--dur-slow) var(--ease-out);
}
.bp-shell[data-expanded="1"] { grid-template-columns: var(--rail-expanded) minmax(0, 1fr); }

/* Rail — a floating navy panel, not a wall: it is inset by 16px and casts a
   shadow, so the page background reads behind it. */
.bp-rail {
    padding: var(--sp-4) 0 var(--sp-4) var(--sp-4);
    display: flex; flex-direction: column;
    position: sticky; top: 0; align-self: start;
    height: 100vh;
}
.bp-rail__box {
    flex: 1; min-height: 0;
    background: var(--cms-navy);
    border-radius: var(--r-20);
    display: flex; flex-direction: column;
    padding: var(--sp-3); gap: var(--sp-1);
    box-shadow: var(--shadow-3);
    overflow: auto; scrollbar-width: none;
    animation: bp-rise .5s var(--ease-out) both;
    transition: width var(--dur-slow) var(--ease-out);
}
.bp-rail__box::-webkit-scrollbar { display: none; }

.bp-rail__logo {
    display: flex; align-items: center; gap: 10px;
    height: var(--control); padding: 0 6px; margin-bottom: var(--sp-2); flex: none;
}
.bp-rail__logo svg { flex: none; }
.bp-rail__wordmark {
    font-family: var(--font-display); font-weight: 900;
    font-size: var(--fs-20); letter-spacing: -.04em; color: #fff;
    animation: bp-fade var(--dur-base) var(--ease-out) both;
}

/* Collapsed is the default: 88px of rail holds an icon and nothing else.
   Every piece of text in it — the wordmark, the nav labels, the tool labels,
   the account name — appears only once the rail is expanded to 256px, and the
   short labels appear only once it has become a bottom bar. Leaving any of
   them visible at 88px clips a Georgian word to its first letter. */
.bp-rail__wordmark,
.bp-rail__label,
.bp-rail__short,
.bp-rail__me-name { display: none; }

.bp-shell[data-expanded="1"] .bp-rail__wordmark,
.bp-shell[data-expanded="1"] .bp-rail__label,
.bp-shell[data-expanded="1"] .bp-rail__me-name { display: block; }
.bp-shell[data-expanded="1"] .bp-rail__me-name { display: flex; }

/* With the text gone, the icon is the whole item, so it centres. Expanded, the
   row goes back to icon-then-label with the padding the design specifies. */
.bp-rail__item,
.bp-rail__tool,
.bp-rail__me,
.bp-rail__logo { justify-content: center; padding-left: 0; padding-right: 0; }
.bp-shell[data-expanded="1"] .bp-rail__item,
.bp-shell[data-expanded="1"] .bp-rail__tool { justify-content: flex-start; padding: 0 var(--sp-3); }
.bp-shell[data-expanded="1"] .bp-rail__me { justify-content: flex-start; padding: 0 2px; }
.bp-shell[data-expanded="1"] .bp-rail__logo { justify-content: flex-start; padding: 0 6px; }

.bp-rail__item {
    height: var(--control); flex: none;
    border-radius: var(--r-14);
    background: transparent; color: #C9D1EA;
    display: flex; align-items: center; gap: var(--sp-3);
    padding: 0 var(--sp-3);
    position: relative;
    font-weight: 600; font-size: var(--fs-14);
    text-align: left; white-space: nowrap; overflow: hidden;
    transition: background var(--dur-base), color var(--dur-base);
}
.bp-rail__item svg { flex: none; }
.bp-rail__item:hover { background: rgba(255, 255, 255, .08); color: #fff; text-decoration: none; }
/* The current page is the one place the rail carries the accent. */
.bp-rail__item[aria-current] { background: var(--cms-accent); color: var(--cms-navy); }
.bp-rail__item[aria-current] svg { stroke: var(--cms-navy); }
.bp-rail__label { flex: 1; animation: bp-fade var(--dur-base) var(--ease-out) both; }
/* The expand button's two words: the one that says what pressing it will do. */
.bp-shell[data-expanded="1"] .bp-rail__label--closed,
.bp-shell:not([data-expanded="1"]) .bp-rail__label--open { display: none; }
.bp-rail__tool--expand .bp-rail__tool-icon { transition: transform var(--dur-base); }
.bp-shell[data-expanded="1"] .bp-rail__tool--expand .bp-rail__tool-icon { transform: scaleX(-1); }

/* How much is late in this module — and a way straight to it.

   Asked for by the person who uses it, in place of the prototype's red dot on
   the corner of the icon: with the rail open, the number sits at the end of
   the row, in a pill, the way a count reads in a list. The pill is always the
   inverse of the row it sits on — navy on the yellow current row, yellow on
   the navy rail — so it is the brand's two colours and never a third. With the
   rail closed there is no row end to sit at, so it goes back to the corner of
   the icon, small. */
.bp-rail__badge {
    position: absolute; top: 4px; right: 6px;
    min-width: 18px; height: 16px; padding: 0 5px;
    border-radius: var(--r-pill);
    background: var(--cms-accent); color: var(--cms-navy);
    font-size: 10px; font-weight: 700; font-family: var(--font-mono);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background var(--dur-base), color var(--dur-base), transform var(--dur-base);
}
.bp-rail__badge:hover { transform: scale(1.08); }
.bp-rail__item[aria-current] .bp-rail__badge,
.bp-more__item[aria-current] .bp-rail__badge { background: var(--cms-navy); color: #fff; }

.bp-shell[data-expanded="1"] .bp-rail__badge {
    position: static; flex: none; margin-left: auto;
    min-width: 28px; height: 20px; padding: 0 9px;
    font-size: var(--fs-11);
}

.bp-rail__foot {
    margin-top: auto; flex: none;
    display: flex; flex-direction: column; gap: var(--sp-1);
    padding-top: var(--sp-2);
    border-top: 1px solid rgba(255, 255, 255, .1);
    /* ⚠️ Pinned to the bottom of the rail. With twenty-odd tools the box scrolls, and the
       foot — expand, theme, account — used to scroll with it, below the fold at 900px tall.
       Sticky inside the scrolling box: the nav slides under it, and the navy fill hides what
       is underneath. The padding/negative margin pair covers the box's own bottom padding, so
       at the end of the scroll it sits exactly where it always did. */
    position: sticky; bottom: 0; z-index: 1;
    background: var(--cms-navy);
    padding-bottom: var(--sp-3); margin-bottom: calc(-1 * var(--sp-3));
}
.bp-rail__tool {
    height: var(--control); border-radius: var(--r-14);
    background: transparent; color: #C9D1EA;
    display: flex; align-items: center; gap: var(--sp-3); padding: 0 var(--sp-3);
    font-weight: 600; font-size: var(--fs-13);
    white-space: nowrap; overflow: hidden;
}
.bp-rail__tool:hover { background: rgba(255, 255, 255, .08); text-decoration: none; }
.bp-rail__tool--filled { background: rgba(255, 255, 255, .08); color: #fff; }
.bp-rail__tool-icon { width: 20px; flex: none; display: inline-flex; justify-content: center; }

.bp-rail__me {
    height: var(--input); display: flex; align-items: center; gap: 10px;
    padding: 0 2px; border-radius: var(--r-14);
    background: transparent; text-align: left;
    white-space: nowrap; overflow: hidden;
}
.bp-rail__me:hover { background: rgba(255, 255, 255, .08); text-decoration: none; }
/* No `display` here: the collapsed/expanded rules above own it, and a
   `display:flex` at this point in the file would quietly win over them. */
.bp-rail__me-name { flex-direction: column; line-height: 1.2; animation: bp-fade var(--dur-base) var(--ease-out) both; }
.bp-rail__me-name b { font-size: var(--fs-13); font-weight: 600; color: #fff; }
.bp-rail__me-name span { font-size: var(--fs-11); color: #8E97B8; }

/* Only shown once the rail has become a bottom bar. */
.bp-rail__cam,
.bp-rail__more { display: none; }

.bp-main {
    display: flex; flex-direction: column; min-width: 0;
    padding: var(--sp-4) var(--sp-6) var(--sp-6) var(--sp-5);
    gap: var(--sp-5);
}

.bp-header {
    display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
    animation: bp-rise .5s .05s var(--ease-out) both;
    position: relative; z-index: 30;
}
.bp-header__logo { display: none; align-items: center; gap: var(--sp-2); height: var(--control); flex: none; }
/* display:contents so a screen's header buttons sit in the header's own flex
   row at full width; at phone width the wrapper becomes a row of its own. */
.bp-header__actions { display: contents; }
/* The bell's dropdown is positioned against this, so the flex child in the
   header is the wrapper, not the button — which is what has to carry the
   phone ordering below. */
.bp-header__bell { position: relative; flex: none; }

/* No signal, or posts waiting to go out. Hidden while there is nothing to say —
   a permanent "online" badge tells somebody on a site nothing they did not know,
   and the moment it matters it has to be the thing they notice. */
.bp-offline {
    display: inline-flex; align-items: center; gap: 7px; flex: none;
    height: var(--control); padding: 0 var(--sp-3);
    border-radius: var(--r-pill); background: var(--surface);
    box-shadow: var(--shadow-1);
    font-size: var(--fs-12); font-weight: 600; white-space: nowrap;
}
.bp-offline .bp-dot { background: var(--warning); }
.bp-offline[data-state="offline"] { background: var(--cms-navy); color: #fff; }
.bp-offline[data-state="offline"] .bp-dot { background: var(--cms-accent); }
.bp-offline .bp-dot { border-radius: 50%; }
.bp-offline[hidden] { display: none; }

/* The dictation button while it is listening. */
.bp-iconbtn.is-on { background: var(--cms-accent); }
.bp-header__logo span {
    font-family: var(--font-display); font-weight: 900;
    font-size: var(--fs-20); letter-spacing: -.04em; color: var(--ink);
}

.bp-project {
    height: var(--control); padding: 0 var(--sp-4) 0 var(--sp-2);
    border-radius: var(--r-pill);
    background: var(--surface); color: var(--ink);
    box-shadow: var(--shadow-1);
    display: flex; align-items: center; gap: 10px;
}
.bp-project:hover { text-decoration: none; }
.bp-project__mark {
    width: 28px; height: 28px; border-radius: 50%;
    background: var(--primary); color: #fff;
    font-size: var(--fs-11); font-weight: 700;
    display: flex; align-items: center; justify-content: center; flex: none;
}
.bp-project__name { font-weight: 600; }
.bp-project__caret { color: var(--muted); font-size: var(--fs-12); }

.bp-crumb { font-size: var(--fs-13); color: var(--muted); display: inline-flex; align-items: center; gap: var(--sp-2); }
.bp-crumb__sep { opacity: .5; }
/* The crumb says where you are, not what the record is called: a document
   title long enough to wrap pushes the account off the header's first row. The
   heading below carries the full name. */
.bp-crumb__here {
    font-weight: 600; color: var(--ink);
    max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The search gives way before the header wraps: a screen with two long action
   buttons was pushing the bell and the account onto a second row, and a
   narrower search box costs nothing — it is a button that opens a palette. */
.bp-search {
    margin-left: auto; height: var(--control);
    flex: 0 1 260px; min-width: 120px;
    border-radius: var(--r-pill);
    background: var(--surface); color: var(--muted);
    box-shadow: var(--shadow-1);
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 var(--sp-2) 0 var(--sp-4); font-size: var(--fs-13);
}
.bp-search kbd {
    font-family: var(--font-mono); font-size: var(--fs-11);
    background: var(--surface2); border-radius: var(--r-pill); padding: 4px var(--sp-2);
}

.bp-iconbtn {
    height: var(--control); width: var(--control); border-radius: 50%;
    background: var(--surface); box-shadow: var(--shadow-1);
    display: flex; align-items: center; justify-content: center;
    position: relative; flex: none;
}
/* A row action: small, quiet, square-ish. Not the 44px header button — a
   listing with three of those per row is all buttons and no list. */
.bp-iconbtn--sm {
    width: 32px; height: 32px; border-radius: var(--r-8);
    background: var(--surface2); box-shadow: none;
    font-size: var(--fs-13);
}
.bp-iconbtn--sm:hover { background: var(--border); text-decoration: none; }

/* The square tile that carries a file's kind — a folder glyph, or the
   extension set in mono. */
.bp-file-tile {
    width: 34px; height: 34px; flex: none;
    border-radius: var(--r-8);
    display: grid; place-items: center;
}

.bp-iconbtn__dot {
    position: absolute; top: -2px; right: -2px;
    min-width: 18px; height: 18px; padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--danger); color: #fff;
    font-size: 10px; font-family: var(--font-mono);
    display: flex; align-items: center; justify-content: center;
}

/* KA/EN. The filled pill slides between the two halves — a transform would be
   cheaper, but the pill also changes width between the labels. */
.bp-lang {
    height: var(--control); padding: 0 var(--sp-1);
    border-radius: var(--r-pill);
    background: var(--surface); box-shadow: var(--shadow-1);
    display: flex; align-items: center;
    font-size: var(--fs-12); font-weight: 600;
    position: relative; flex: none;
}
.bp-lang__slider {
    position: absolute; top: 4px; height: 36px;
    border-radius: var(--r-pill); background: var(--cms-navy);
    transition: left .26s cubic-bezier(.4, 0, .2, 1), width .26s cubic-bezier(.4, 0, .2, 1);
}
.bp-lang__opt {
    position: relative; width: var(--control); height: 36px;
    border-radius: var(--r-pill); background: transparent;
    color: var(--muted); transition: color var(--dur-slow);
}
.bp-lang__opt[aria-pressed="true"] { color: #fff; }

.bp-avatar {
    width: var(--control); height: var(--control); border-radius: 50%;
    background: var(--cms-accent); color: var(--cms-navy);
    font-weight: 700; font-size: var(--fs-13);
    display: flex; align-items: center; justify-content: center;
    flex: none; position: relative;
}
.bp-avatar--sm { width: 28px; height: 28px; font-size: var(--fs-11); }
.bp-avatar--md { width: 36px; height: 36px; font-size: var(--fs-12); }
.bp-avatar--neutral { background: var(--surface2); color: var(--ink); }
.bp-avatar__warn {
    position: absolute; top: -1px; right: -1px;
    width: 12px; height: 12px; border-radius: 50%;
    background: var(--danger); border: 2px solid var(--bg);
}

/* Role preview. Yellow because it is a state of the whole screen, and the
   screen is read-only while it is up. */
.bp-banner {
    height: var(--row); border-radius: var(--r-pill);
    background: var(--cms-accent); color: var(--cms-navy);
    display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
    font-size: var(--fs-13); font-weight: 600;
    animation: bp-rise var(--dur-base) var(--ease-out) both;
    position: relative; z-index: 20;
}

/* ── 2b. the signed-out shell ─────────────────────────────────────────────
   Two panels: the product on the left, the one thing the visitor came to do on
   the right. Below 820 the left becomes a band across the top — on a phone the
   form is the page, and a marketing panel above the fold is in the way. */

.bp-auth {
    min-height: 100vh;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(360px, 520px);
}

.bp-auth__brand {
    background-color: var(--cms-navy);
    color: #fff;
    display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-6);
    padding: var(--sp-12) var(--sp-8);
    position: relative; overflow: hidden; min-height: 0;
    background-image:
        linear-gradient(var(--grid-line-on-navy) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line-on-navy) 1px, transparent 1px);
    background-size: var(--grid-step) var(--grid-step);
}
/* The same two marks as the dashboard hero: a soft blue disc bleeding off the
   corner, and the solid accent square. */
.bp-auth__brand::before {
    content: ""; position: absolute; right: -140px; top: -140px;
    width: 360px; height: 360px; border-radius: 50%;
    background: var(--cms-primary); opacity: .6;
}
.bp-auth__brand::after {
    content: ""; position: absolute; right: var(--sp-8); top: var(--sp-8);
    width: 40px; height: 40px; background: var(--cms-accent);
}
.bp-auth__brand > * { position: relative; z-index: 1; }

.bp-auth__mark { display: flex; align-items: center; gap: var(--sp-3); }
.bp-auth__wordmark {
    font-family: var(--font-display); font-weight: 900;
    font-size: var(--fs-28); letter-spacing: -.04em;
}
.bp-auth__pitch { display: flex; flex-direction: column; gap: var(--sp-4); max-width: 520px; padding-right: var(--sp-6); }
/* Archivo, and Latin only: this is the one display setting in the design, and
   a Georgian string must never land in it. */
.bp-auth__headline {
    font-family: var(--font-display); font-weight: 800;
    font-size: clamp(34px, 4.5vw, 56px); line-height: 1; letter-spacing: -.03em;
}
.bp-auth__tagline { font-size: var(--fs-16); color: #C9D6FF; line-height: 1.55; }
.bp-auth__foot { font-size: var(--fs-12); color: #8E97B8; }

.bp-auth__panel {
    background: var(--surface); color: var(--ink);
    display: flex; flex-direction: column; justify-content: center;
    padding: var(--sp-12) var(--sp-12);
    position: relative; overflow: auto; min-height: 0;
    animation: bp-slide-in var(--dur-slow) var(--ease-out) both;
}
.bp-auth__inner { display: flex; flex-direction: column; gap: var(--sp-6); width: 100%; }
.bp-auth__form { display: flex; flex-direction: column; gap: var(--sp-3); }

.bp-auth__note {
    padding: var(--sp-3) var(--sp-4); border-radius: var(--r-14);
    background: var(--success-bg); color: var(--success);
    font-size: var(--fs-13); line-height: 1.5;
}
.bp-auth__note--bad { background: var(--danger-bg); color: var(--danger); }

.bp-auth__rule {
    display: flex; align-items: center; gap: var(--sp-3);
    color: var(--muted); font-size: var(--fs-12);
}
.bp-auth__rule::before,
.bp-auth__rule::after { content: ""; flex: 1; height: 1px; background: var(--border); }

.bp-auth__bottom {
    display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3);
    font-size: var(--fs-12); color: var(--muted);
}
.bp-auth__lang {
    padding: 6px 10px; border-radius: var(--r-pill);
    background: transparent; color: var(--muted); font-weight: 600;
}
.bp-auth__lang[aria-pressed="true"] { color: var(--ink); background: var(--surface2); }

.bp-auth__theme {
    position: absolute; top: var(--sp-5); right: var(--sp-5);
    width: var(--control); height: var(--control); border-radius: 50%;
    background: var(--surface2); color: var(--ink);
    display: flex; align-items: center; justify-content: center;
}

@media (max-width: 820px) {
    .bp-auth { grid-template-columns: minmax(0, 1fr); }
    .bp-auth__brand {
        padding: var(--sp-6) var(--sp-5);
        gap: var(--sp-4);
        flex-direction: row; align-items: center; justify-content: flex-start;
    }
    .bp-auth__brand::before { width: 200px; height: 200px; right: -100px; top: -100px; }
    .bp-auth__brand::after { width: 24px; height: 24px; right: var(--sp-5); top: var(--sp-5); }
    .bp-auth__pitch, .bp-auth__foot { display: none; }
    .bp-auth__panel { padding: var(--sp-6) var(--sp-5) var(--sp-12); justify-content: flex-start; }
}

/* ── 3. buttons + inputs ──────────────────────────────────────────────── */

.bp-btn {
    height: var(--control); padding: 0 var(--sp-5);
    border-radius: var(--r-pill);
    font: 600 var(--fs-14) var(--font-ui);
    display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
    white-space: nowrap;
    transition: transform var(--dur-fast), background var(--dur-base), color var(--dur-base);
}
.bp-btn:hover { transform: scale(1.03); text-decoration: none; }
.bp-btn:active { transform: scale(.98); }
.bp-btn[disabled], .bp-btn[aria-disabled="true"] {
    background: #DDE1EC; color: #8E97B8; cursor: not-allowed; transform: none;
}

.bp-btn--primary   { background: var(--primary); color: #fff; }
.bp-btn--navy      { background: var(--cms-navy); color: #fff; }
.bp-btn--accent    { background: var(--cms-accent); color: var(--cms-navy); }
.bp-btn--secondary { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-1); }
.bp-btn--quiet     { background: var(--surface2); color: var(--ink); }
.bp-btn--danger    { background: var(--danger); color: #fff; }
.bp-btn--ghost     { background: transparent; color: var(--ink); }
.bp-btn--ghost:hover { background: var(--surface2); transform: none; }
.bp-btn--link      { background: transparent; color: var(--primary); padding: 0; height: auto; font-size: var(--fs-13); }
.bp-btn--link:hover { transform: none; text-decoration: underline; }
.bp-btn--outline   { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }

.bp-btn--36 { height: 36px; padding: 0 var(--sp-3); font-size: var(--fs-13); }
.bp-btn--40 { height: var(--row); padding: 0 18px; }
.bp-btn--48 { height: var(--input); padding: 0 var(--sp-6); }
.bp-btn--52 { height: 52px; padding: 0 var(--sp-6); font-size: var(--fs-15); }
.bp-btn--block { width: 100%; }

/* Two backgrounds, and which one depends on what is behind the field.
   --surface2 and --bg are the same value in light mode, so a field painted in
   --surface2 on the page background cannot be seen at all: a search box next
   to a table looked like an empty gap. Inside a card — where the design puts
   every form — --surface2 is the recessed field the handoff specifies, and the
   rule below restores it. */
.bp-input, .bp-textarea, .bp-select {
    width: 100%; height: var(--input);
    border: 0; border-radius: var(--r-14);
    background: var(--surface); color: var(--ink);
    box-shadow: var(--shadow-1);
    padding: 0 var(--sp-4);
    font: var(--fs-14) var(--font-ui); line-height: var(--lh-body);
    outline: 0;
}
.bp-card .bp-input,
.bp-card .bp-textarea,
.bp-card .bp-select,
.bp-panel .bp-input,
.bp-panel .bp-textarea,
.bp-panel .bp-select,
.bp-modal .bp-input,
.bp-modal .bp-textarea,
.bp-modal .bp-select,
.bp-sheet .bp-input,
.bp-sheet .bp-textarea,
.bp-sheet .bp-select,
.bp-auth__panel .bp-input,
.bp-auth__panel .bp-textarea,
.bp-auth__panel .bp-select { background: var(--surface2); box-shadow: none; }

/* A recessed field needs something to be recessed into. Inside a card the
   ground is --surface, so --surface2 reads as a field; inside a tile, a
   repeated row or a photo caption the ground is already --surface2, and a
   field the same colour as what is behind it is not a field at all. */
.bp-tile .bp-input, .bp-tile .bp-textarea, .bp-tile .bp-select,
.bp-repeat__row .bp-input, .bp-repeat__row .bp-textarea, .bp-repeat__row .bp-select,
.bp-report-check .bp-input, .bp-report-check .bp-textarea, .bp-report-check .bp-select,
.bp-photo-tile .bp-input { background: var(--surface); box-shadow: var(--shadow-1); }

.bp-textarea { height: auto; min-height: 96px; padding: var(--sp-3) var(--sp-4); resize: vertical; }
.bp-input:focus, .bp-textarea:focus, .bp-select:focus { box-shadow: 0 0 0 3px rgba(31, 79, 216, .25); }
.bp-input[aria-invalid="true"], .bp-textarea[aria-invalid="true"] { box-shadow: 0 0 0 2px var(--danger); }
.bp-input::placeholder, .bp-textarea::placeholder { color: var(--muted); }


/* A multi-select is a list box, not a control: it has to be allowed its own
   height or it draws outside the row it is in. */
.bp-select[multiple] {
    height: auto; min-height: 36px; max-height: 96px;
    padding: 6px 10px; overflow-y: auto;
}

.bp-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.bp-label { font-size: var(--fs-12); font-weight: 600; color: var(--muted); }
.bp-error-text { font-size: var(--fs-12); color: var(--danger); }

/* The signing PIN inside an in-app signing form (profile R2b, profile/_pin_field): four digits. */
.bp-pin { display: flex; flex-direction: column; gap: 6px; min-width: 0; margin: 0; }
.bp-pin__label { font-size: var(--fs-12); font-weight: 600; color: var(--muted); }
.bp-pin__input.bp-input { width: 120px; letter-spacing: .4em; text-align: center; font-family: var(--font-mono); }
.bp-pin--compact { flex-direction: row; align-items: center; gap: 8px; flex-wrap: wrap; }

/* A segmented control: pills inside a pill. */
/* The track is --surface, not --surface2: in light mode --surface2 is the same
   value as --bg, so a segmented control sitting on the page background had no
   visible track at all. */
.bp-seg {
    height: var(--control); padding: 0 var(--sp-1);
    border-radius: var(--r-pill); background: var(--surface); box-shadow: var(--shadow-1);
    display: inline-flex; align-items: center; gap: var(--sp-1); flex: none;
}
.bp-seg__opt {
    height: 36px; padding: 0 var(--sp-4); border-radius: var(--r-pill);
    background: transparent; color: var(--muted);
    font-size: var(--fs-13); font-weight: 600;
    /* ⚠️ Explicitly centred, because half of these are links. A <button> centres
       its own content and an <a> does not: with only a height set, the text sat
       1px from the top of a 36px box with 17px under it. Every label was high;
       it only *looked* like one tab because "ფორმა N2" has no descenders to
       disguise it. */
    display: inline-flex; align-items: center; justify-content: center;
    white-space: nowrap;
    transition: background var(--dur-base), color var(--dur-base);
}
.bp-seg__opt[aria-pressed="true"], .bp-seg__opt.is-on {
    background: var(--dark-pill); color: var(--dark-pill-ink);
}

/* What is waiting behind a tab.

   ⚠️ A count and never a total. A number that is always there stops being read within a
   week, and on the day it matters it looks exactly as it did the day before — so the only
   thing that earns this pill is a state somebody has to act on to clear.

   It lives here rather than in the finance layer because it belongs to `.bp-seg`, and
   three of the six screens that carry this strip do not load that layer at all. Mono on
   the figure, because it is a number and not a word. */
.bp-seg__n {
    margin-inline-start: 7px;
    min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: var(--r-pill);
    background: var(--surface2); color: var(--muted);
    font-family: var(--font-mono); font-size: 11px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
}

/* On the tab you are already on, the pill inverts with it. */
.bp-seg__opt.is-on .bp-seg__n { background: rgba(255, 255, 255, .22); color: var(--dark-pill-ink); }

/* A choice made by picking a card rather than a radio dot. The radio is still
   there and still does the work; :has() paints the card around it. */
.bp-choice {
    flex: 1; min-width: 0; cursor: pointer;
    border-radius: var(--r-14); padding: var(--sp-3);
    background: var(--surface2); color: var(--muted);
    text-align: center; font-size: var(--fs-13); font-weight: 600;
    transition: background var(--dur-base), color var(--dur-base);
}
.bp-choice input { position: absolute; opacity: 0; pointer-events: none; }
.bp-choice:has(input:checked) { background: var(--info-bg); color: var(--st-doing); }
.bp-choice:has(input:focus-visible) { outline: 3px solid var(--cms-accent); outline-offset: 2px; }

/* Somewhere to drop a file, and a real input behind it — a drop zone that is
   only a drop zone cannot be reached from a keyboard. */
.bp-drop {
    display: block; cursor: pointer; text-align: center;
    border-radius: var(--r-16); padding: 34px var(--sp-5);
    background: var(--surface2);
    box-shadow: inset 0 0 0 2px var(--border);
    transition: background var(--dur-base), box-shadow var(--dur-base);
}
.bp-drop.is-over { background: var(--info-bg); box-shadow: inset 0 0 0 2px var(--primary); }
.bp-drop input[type="file"] { position: absolute; opacity: 0; pointer-events: none; }

.bp-chip {
    height: 36px; padding: 0 var(--sp-3); border-radius: var(--r-pill);
    background: var(--surface); color: var(--ink); box-shadow: var(--shadow-1);
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--fs-13); font-weight: 600;
}
.bp-chip.is-on { background: var(--cms-navy); color: #fff; box-shadow: none; }

/* A real checkbox drawn as a switch. The button version below carries no value,
   which is fine for a preference the page acts on immediately — but a switch
   inside a form has to be an input, or an unchecked one submits nothing and the
   server cannot tell "off" from "not shown". */
/* Choosing rows is not answering a question: a switch says on or off about
   one thing, a checkbox says "this one, and this one". */
.bp-check {
    width: 17px; height: 17px; margin: 0; flex: none;
    accent-color: var(--cms-primary); cursor: pointer;
}

.bp-switch {
    appearance: none; -webkit-appearance: none;
    width: 40px; height: 24px; flex: none; margin: 0;
    border-radius: var(--r-pill); background: var(--border);
    position: relative; cursor: pointer;
    transition: background var(--dur-base);
}
.bp-switch::after {
    content: ""; position: absolute; top: 3px; left: 3px;
    width: 18px; height: 18px; border-radius: 50%;
    background: #fff; box-shadow: var(--shadow-1);
    transition: transform var(--dur-base) var(--ease-out);
}
.bp-switch:checked { background: var(--success); }
.bp-switch:checked::after { transform: translateX(16px); }

.bp-toggle {
    width: 44px; height: 26px; border-radius: var(--r-pill);
    background: var(--surface2); position: relative; flex: none;
    transition: background var(--dur-base);
}
.bp-toggle::after {
    content: ""; position: absolute; top: 3px; left: 3px;
    width: 20px; height: 20px; border-radius: 50%;
    background: #fff; box-shadow: var(--shadow-1);
    transition: transform var(--dur-base) var(--ease-out);
}
.bp-toggle[aria-pressed="true"] { background: var(--primary); }
.bp-toggle[aria-pressed="true"]::after { transform: translateX(18px); }

/* ── 4. surfaces ──────────────────────────────────────────────────────── */

.bp-card {
    background: var(--surface);
    border-radius: var(--r-20);
    box-shadow: var(--shadow-1);
    padding: var(--sp-5) var(--sp-6);
    display: flex; flex-direction: column; gap: var(--sp-4);
    min-width: 0;
}
.bp-card--sm   { border-radius: var(--r-16); padding: 14px var(--sp-4); gap: 6px; }
.bp-card--flat { padding: var(--sp-5); }
.bp-card--plain{ padding: 0; }

.bp-card__head { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-2); }
.bp-card__title { font-weight: 700; font-size: var(--fs-16); }
.bp-card__sub { font-size: var(--fs-12); color: var(--muted); }

.bp-hero {
    border-radius: var(--r-24);
    padding: var(--sp-8);
    display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-6);
    position: relative; overflow: hidden;
    background-color: var(--cms-navy); color: #fff;
    background-image:
        linear-gradient(var(--grid-line-on-navy) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line-on-navy) 1px, transparent 1px);
    background-size: var(--grid-step) var(--grid-step);
}
/* The two decorations the hero carries: a soft blue disc bleeding off the top
   right, and the solid accent square that is the brand's "under construction"
   marker. Both are inert. */
.bp-hero::before {
    content: ""; position: absolute; right: -90px; top: -90px;
    width: 200px; height: 200px; border-radius: 50%;
    background: var(--cms-primary); opacity: .6;
}
.bp-hero::after {
    content: ""; position: absolute; right: var(--sp-4); top: var(--sp-4);
    width: 24px; height: 24px; background: var(--cms-accent);
}
.bp-hero > * { position: relative; z-index: 1; }
.bp-hero__label { font-size: var(--fs-12); color: #C9D6FF; }
.bp-hero__foot { display: flex; justify-content: space-between; font-size: var(--fs-12); color: #C9D6FF; flex-wrap: wrap; gap: 6px; }

.bp-tile {
    background: var(--surface2); border-radius: var(--r-14);
    padding: var(--sp-3); display: flex; flex-direction: column; min-width: 0;
}
.bp-tile__n { font-family: var(--font-display); font-weight: 800; font-size: var(--fs-28); line-height: 1; }
.bp-tile__label { font-size: var(--fs-11); color: var(--muted); }

.bp-grid { display: grid; gap: var(--sp-4); }
/* Named, not inline: a media query cannot override a style attribute, so a grid
   whose columns are written inline never collapses on a phone. */
.bp-grid--hero  { grid-template-columns: 1.25fr repeat(3, minmax(180px, 1fr)); }
.bp-grid--split { grid-template-columns: minmax(260px, 1.5fr) minmax(260px, 1fr); }
.bp-grid--fill  { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
.bp-grid--kpi { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: var(--sp-3); }
.bp-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.bp-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.bp-stack { display: flex; flex-direction: column; gap: var(--sp-5); }
.bp-stack--tight { gap: var(--sp-2); }
/* A row says which way it runs. Without that, an element that is both a card
   and a row — a filter bar, the profile header — kept the card's column and
   stacked its controls down the middle. */
.bp-row { display: flex; flex-direction: row; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.bp-spacer { margin-left: auto; }

/* ── 5. pills, badges, avatars ────────────────────────────────────────── */

.bp-pill {
    height: 28px; padding: 0 var(--sp-3); border-radius: var(--r-pill);
    font: 600 var(--fs-12) var(--font-ui);
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--surface2); color: var(--ink);
    white-space: nowrap;
}
/* A square dot, not a round one: it is the same 8px block as in the icons. */
.bp-pill__dot { width: 8px; height: 8px; background: currentColor; flex: none; }
.bp-pill--mono { font-family: var(--font-mono); font-weight: 500; }
.bp-pill--sm { height: 22px; padding: 0 var(--sp-2); font-size: var(--fs-11); }

.bp-pill--todo     { color: var(--st-todo); }
.bp-pill--doing    { color: var(--st-doing); background: var(--info-bg); }
.bp-pill--paused   { color: var(--warning-ink); background: var(--warning-bg); }
.bp-pill--late     { color: var(--st-late); background: var(--late-bg); }
.bp-pill--done     { color: var(--st-done); background: var(--success-bg); }
.bp-pill--critical { color: var(--cms-navy); background: var(--cms-accent); }

.bp-qa { font-family: var(--font-mono); font-weight: 500; color: #fff; }
.bp-qa--ncr { background: var(--qa-ncr); }
.bp-qa--def { background: var(--qa-def); }
.bp-qa--wir { background: var(--qa-wir); }
.bp-qa--maf { background: var(--qa-maf); }
.bp-qa--mos { background: var(--qa-mos); }
.bp-qa--fwa { background: var(--qa-fwa); }

.bp-dot { width: 8px; height: 8px; flex: none; display: inline-block; }

/* ── 6. numbers + progress ────────────────────────────────────────────── */

/* Archivo is Latin display. A Georgian string must never be set in it, so
   these classes go on numerals and the wordmark only. */
.bp-num {
    font-family: var(--font-display); font-weight: 800;
    font-size: var(--fs-40); line-height: 1; letter-spacing: -.03em;
}
.bp-num--28 { font-size: var(--fs-28); }
.bp-num--32 { font-size: 32px; }
.bp-num--hero { font-size: var(--fs-96); line-height: .9; letter-spacing: -.04em; }
.bp-num--hero sup, .bp-num__unit { font-size: var(--fs-40); color: var(--cms-accent); }

.bp-kpi {
    background: var(--surface); color: var(--ink);
    border-radius: var(--r-16); padding: 14px var(--sp-4);
    display: flex; flex-direction: column; gap: 6px;
    box-shadow: var(--shadow-1); text-align: left; min-width: 0;
    transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base);
}
.bp-kpi:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(11, 31, 92, .12); text-decoration: none; }
.bp-kpi__label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-12); color: var(--muted); }
.bp-kpi__value { font-family: var(--font-display); font-weight: 800; font-size: 32px; line-height: 1; letter-spacing: -.03em; }

/* Progress carries an optional plan marker — the thin tick showing where the
   plan says the bar should be. It is what makes 68% against a 66% plan read
   as on track rather than as a bare number. */
/* display:block matters: the bar is often a <span> inside a table cell, and an
   inline box ignores height — the track renders as a hairline and the fill
   disappears entirely. */
.bp-progress { display: block; height: 6px; border-radius: 3px; background: var(--surface2); position: relative; }
.bp-progress--lg { height: 10px; border-radius: 5px; }
.bp-progress--onNavy { background: rgba(255, 255, 255, .15); overflow: hidden; }
.bp-progress__fill {
    display: block; height: 100%; border-radius: inherit;
    background: var(--primary);
    animation: bp-grow 1s .3s var(--ease-out) both;
}
.bp-progress--onNavy .bp-progress__fill { background: #fff; }
.bp-progress__plan {
    position: absolute; top: -3px; width: 2px; height: 16px;
    background: var(--cms-accent);
}
.bp-progress--sm .bp-progress__plan { height: 12px; top: -3px; background: var(--ink); opacity: .6; }

/* ── 7. data table + grouped list ─────────────────────────────────────── */

/* The grid rows are a real CSS grid, not a <table>: the columns are declared
   once on the wrapper and every row inherits them, so a row can be a <a> or a
   <button> and still line up. Below its min-width the whole thing scrolls
   sideways rather than squeezing — a squeezed column of Georgian is unreadable.
   No blueprint grid behind it, per the handoff. */
.bp-table-wrap { overflow-x: auto; scrollbar-width: thin; }
.bp-table { min-width: 900px; display: flex; flex-direction: column; }
.bp-table__head,
.bp-table__row {
    display: grid; grid-template-columns: var(--bp-cols, 1fr);
    align-items: center; gap: var(--sp-3);
    padding: 0 var(--sp-4);
}
.bp-table__head {
    height: 36px; font-size: var(--fs-11); font-weight: 600; color: var(--muted);
    position: sticky; top: 0; background: var(--surface); z-index: 2;
}
.bp-table__row {
    min-height: var(--row); background: var(--surface); color: var(--ink);
    text-align: left; border-radius: var(--r-12);
    transition: background var(--dur-fast);
}
.bp-table__row:hover { background: var(--surface2); text-decoration: none; }
.bp-table__row + .bp-table__row { margin-top: 2px; }
.bp-table__cell { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A cell that is itself a link still reads as a row. Blue underlined text in a
   register makes every row look like prose. */
a.bp-table__cell, .bp-table__cell a { color: inherit; }
a.bp-table__cell:hover, .bp-table__cell a:hover { text-decoration: none; }
/* A row that is one link and still carries a second one — "open the draft" as
   the row, "open it in Gmail" as an icon at the end. Nested <a> is not HTML, so
   the row is a plain element with an invisible anchor stretched over it, and the
   cell holding the other link is raised above that. The stretched anchor is out
   of the grid flow, so it takes no column. */
.bp-table__row--multi { position: relative; }
.bp-table__row--multi > .bp-stretch { position: absolute; inset: 0; border-radius: inherit; }
.bp-table__cell--above { position: relative; z-index: 1; }
.bp-table__cell--wrap { white-space: normal; overflow-wrap: anywhere; }
.bp-table__cell--num { font-family: var(--font-mono); font-size: var(--fs-12); color: var(--muted); }

/* Pagination. Numbers are mono so the row does not jitter as the digits change,
   and the count on the right is what people actually read — "51–100 / 384"
   answers "how much is there" in a way a page number never does. */
.bp-pager {
    display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap;
    padding: var(--sp-3) 0;
}
.bp-pager__page,
.bp-pager__step {
    min-width: 36px; height: 36px; padding: 0 var(--sp-2);
    border-radius: var(--r-12);
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-mono); font-size: var(--fs-13);
    color: var(--ink); background: var(--surface);
    box-shadow: var(--shadow-1);
}
.bp-pager__page:hover,
.bp-pager__step:hover { background: var(--surface2); text-decoration: none; }
.bp-pager__page.is-current { background: var(--dark-pill); color: var(--dark-pill-ink); box-shadow: none; }
.bp-pager__step[aria-disabled="true"] { color: var(--muted); box-shadow: none; background: transparent; }
.bp-pager__gap { padding: 0 var(--sp-1); color: var(--muted); }
.bp-pager__count { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-12); color: var(--muted); }

/* A repeatable sub-record inside a form. A dropped row stays on the page,
   faded and marked, because the server has to be told to delete it — and
   because the person can change their mind before saving. */
.bp-repeat { display: flex; flex-direction: column; gap: var(--sp-3); }
.bp-repeat__row {
    background: var(--surface2); border-radius: var(--r-14);
    padding: 14px; display: grid; gap: 10px; align-items: start;
}
.bp-repeat__row.is-dropped { opacity: .45; background: var(--danger-bg); }

.bp-group { display: flex; flex-direction: column; gap: var(--sp-2); }
.bp-group__head {
    display: flex; align-items: center; gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4);
    font-weight: 700; font-size: var(--fs-13);
}
.bp-group__count { font-family: var(--font-mono); font-size: var(--fs-12); color: var(--muted); }

.bp-list-row {
    text-align: left; display: flex; gap: 14px; align-items: center;
    padding: var(--sp-3) 14px; border-radius: var(--r-14);
    background: var(--surface2); color: var(--ink);
    transition: transform var(--dur-fast);
}
.bp-list-row:hover { transform: translateX(4px); text-decoration: none; }
.bp-list-row__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bp-list-row__title { font-weight: 600; line-height: 1.4; }
.bp-list-row__sub { font-size: var(--fs-12); color: var(--muted); }
.bp-list-row__chev { margin-left: auto; color: var(--muted); }

/* ── 8. overlays ──────────────────────────────────────────────────────── */

.bp-scrim {
    position: fixed; inset: 0; z-index: 44;
    background: rgba(11, 31, 92, .45);
    animation: bp-fade .2s var(--ease-out) both;
}
.bp-scrim--strong { background: rgba(11, 31, 92, .5); }

.bp-dropdown {
    position: absolute; right: 0; top: 52px; width: 340px; z-index: 35;
    background: var(--surface); border-radius: var(--r-20);
    box-shadow: 0 16px 40px rgba(11, 31, 92, .2);
    padding: var(--sp-2);
    animation: bp-rise var(--dur-base) var(--ease-out) both;
}
.bp-dropdown__head { display: flex; justify-content: space-between; align-items: center; padding: 10px var(--sp-3); }
.bp-dropdown__item {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 10px var(--sp-3); border-radius: var(--r-12);
    line-height: 1.4; width: 100%; text-align: left;
    /* A menu line is a menu line whether it is a link, a button or a note: the
       link colour belongs to links in running text, not to a list of places. */
    color: var(--ink); font-size: var(--fs-13); font-weight: 500;
}
.bp-dropdown__item:hover { background: var(--surface2); text-decoration: none; }
.bp-dropdown__item.is-unread { background: var(--info-bg); }

/* A notification's own words, under its subject: two lines of them, because the
   tray is 340px wide and the whole message belongs on the screen it points at. */
.bp-notif__body {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: var(--fs-12); font-weight: 400; color: var(--muted);
    margin-top: 2px;
}

/* Side panel: 420–460, slides in from the right, full height. */
.bp-panel {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 48;
    width: min(460px, 100vw);
    background: var(--surface); color: var(--ink);
    box-shadow: var(--shadow-modal);
    display: flex; flex-direction: column;
    animation: bp-slide-in var(--dur-base) var(--ease-out) both;
}
.bp-panel__head {
    padding: var(--sp-5) var(--sp-6); flex: none;
    display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3);
}
.bp-panel__body { padding: 0 var(--sp-6) var(--sp-6); overflow-y: auto; display: flex; flex-direction: column; gap: var(--sp-4); }
.bp-panel__foot { margin-top: auto; padding: var(--sp-4) var(--sp-6); flex: none; display: flex; gap: var(--sp-2); }

.bp-modal-wrap {
    position: fixed; inset: 0; z-index: 48;
    display: flex; align-items: center; justify-content: center; padding: var(--sp-4);
}
.bp-modal {
    width: min(560px, 100%); max-height: 90vh;
    background: var(--surface); color: var(--ink);
    border-radius: var(--r-24); box-shadow: var(--shadow-modal);
    display: flex; flex-direction: column; overflow: hidden;
    animation: bp-pop var(--dur-slow) var(--ease-out) both;
}
.bp-modal__head { padding: var(--sp-6) var(--sp-6) var(--sp-3); display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); }
.bp-modal__title { font-weight: 700; font-size: var(--fs-18); }
.bp-modal__body { padding: 0 var(--sp-6); overflow-y: auto; display: flex; flex-direction: column; gap: var(--sp-3); }
.bp-modal__foot { padding: var(--sp-4) var(--sp-6) var(--sp-6); display: flex; gap: var(--sp-2); justify-content: flex-end; }

/* Bottom sheet — the phone and narrow-tablet form surface. */
.bp-sheet {
    position: fixed; left: 0; right: 0; bottom: 0; margin: 0 auto; z-index: 48;
    width: min(560px, 100vw); max-height: 92vh;
    background: var(--surface); color: var(--ink);
    border-radius: 28px 28px 0 0;
    box-shadow: 0 -12px 40px rgba(11, 31, 92, .25);
    display: flex; flex-direction: column; overflow: hidden;
    animation: bp-rise var(--dur-base) var(--ease-out) both;
}
.bp-sheet__grip { width: 40px; height: 4px; border-radius: 2px; background: #C5CBDD; margin: 10px auto 0; flex: none; }
.bp-sheet__body { padding: var(--sp-3) var(--sp-5) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-3); overflow-y: auto; }

.bp-palette-wrap {
    position: fixed; inset: 0; z-index: 48;
    display: flex; align-items: flex-start; justify-content: center;
    padding: 12vh var(--sp-4) var(--sp-4);
}
.bp-palette {
    width: min(560px, 100%);
    background: var(--surface); border-radius: var(--r-20);
    box-shadow: var(--shadow-modal); overflow: hidden;
    animation: bp-pop var(--dur-slow) var(--ease-out) both;
}
.bp-palette__input {
    width: 100%; height: 56px; border: 0; outline: 0;
    background: transparent; color: var(--ink);
    padding: 0 var(--sp-5); font: var(--fs-16) var(--font-ui);
}
.bp-palette__list { max-height: 50vh; overflow-y: auto; padding: var(--sp-2); }
.bp-palette__item {
    width: 100%; text-align: left; display: flex; align-items: center; gap: var(--sp-3);
    height: var(--input); padding: 0 var(--sp-3); border-radius: var(--r-12);
}
.bp-palette__item:hover, .bp-palette__item.is-active { background: var(--surface2); text-decoration: none; }
.bp-palette__hint { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-11); color: var(--muted); }

/* ── the palette as the design draws it (CMS App.dc.html) ─────────────────
   blueprint.js frames it on opening: a search icon and an „esc" key in the box, a
   heading over each section, the actions as coloured tiles, the tasks as code, name
   and state. Without the script it is the plain list above, and still works. */
.bp-palette a.bp-palette__item { color: var(--ink); }
.bp-palette__bar {
    display: flex; align-items: center; gap: 10px; padding: 0 var(--sp-4);
    box-shadow: inset 0 -1px 0 var(--border);
}
.bp-palette__bar .bp-palette__input { flex: 1; min-width: 0; padding: 0; }
.bp-palette__glass { color: var(--muted); flex: none; }
.bp-palette__esc {
    flex: none; height: 24px; padding: 0 8px; border: 0; border-radius: var(--r-8); cursor: pointer;
    background: var(--surface2); color: var(--muted); font: 600 var(--fs-11) var(--font-mono);
}
.bp-palette__esc:hover { color: var(--ink); }
.bp-palette__group { padding: 12px 12px 4px; font-size: var(--fs-11); font-weight: 600; color: var(--muted); }
.bp-palette__group[hidden] { display: none; }
.bp-palette__item--action { height: 48px; }
.bp-palette__item--action .bp-palette__hint { display: none; }
.bp-palette__item--action svg {
    box-sizing: content-box; padding: 6px; border-radius: var(--r-8); flex: none;
    background: var(--surface2); color: var(--muted) !important;
}
.bp-palette__item--action[data-bp-tone="primary"] svg { background: var(--primary); color: #fff !important; }
.bp-palette__item--action[data-bp-tone="accent"] svg { background: var(--cms-accent); color: var(--cms-navy) !important; }
.bp-palette__item--action[data-bp-tone="info"] svg { background: var(--info-bg); color: var(--primary) !important; }
.bp-palette__item--action[data-bp-tone="danger"] svg { background: var(--danger-bg); color: var(--danger) !important; }
.bp-palette__code { flex: none; min-width: 64px; font-family: var(--font-mono); font-size: var(--fs-12); color: var(--muted); }
.bp-palette__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bp-palette__item .bp-pill { flex: none; }

.bp-toast-dock {
    position: fixed; left: 0; right: 0; bottom: var(--sp-6); z-index: 60;
    display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
    pointer-events: none;
}
.bp-toast {
    pointer-events: auto;
    max-width: min(520px, calc(100vw - 32px));
    padding: var(--sp-3) var(--sp-5);
    border-radius: var(--r-pill);
    background: var(--cms-navy); color: #fff;
    box-shadow: var(--shadow-2);
    font-size: var(--fs-13); font-weight: 600;
    display: flex; align-items: center; gap: var(--sp-3);
    animation: bp-toast-in var(--dur-base) var(--ease-out) both;
}
.bp-toast--ok   { background: var(--success); }
.bp-toast--bad  { background: var(--danger); }
.bp-toast--warn { background: var(--cms-accent); color: var(--cms-navy); }

/* ── 8b. the portfolio ────────────────────────────────────────────────────
   The company's home page, built to export/PORTFOLIO-SPEC.md.

   ⚠️ One set of rows, two shapes. The cards and the table are the same markup
   with a different grid on it, so the search and the filters cannot show a
   project in one view and hide it in the other — which is what two lists of
   the same thing always end up doing.

   ⚠️ No borders, elevation only (handoff: "white cards on light grid
   background, --shadow-1"). The one exception is the table, whose rows are
   separated by hairlines because a shadow per row is a corduroy.

   ⚠️ A project's name is NOT uppercased and NOT letter-spaced. The monogram
   and the code are, because a code like PRJ-104 is written that way already —
   Georgian has no case, and the tracking that travels with capitals pulls the
   word apart. Archivo is for the monogram and the KPI numbers; Latin display
   only, exactly as the handoff says. */

.bp-portfolio { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; gap: var(--sp-5); }

/* ── the four figures ───────────────────────────────────────────────── */

.bp-kpi--navy { background: var(--cms-navy); color: #fff; }
.bp-kpi--navy .bp-kpi__label,
.bp-kpi--navy .bp-card__sub { color: #8E97B8; }
.bp-kpi--alert { background: var(--danger-bg); }
.bp-kpi--alert .bp-num,
.bp-kpi--alert .bp-kpi__label { color: var(--danger); }
.bp-kpi--alert .bp-card__sub { color: #B0555C; }

.bp-kpi__n {
    font-family: var(--font-display); font-weight: 900;
    font-size: 34px; line-height: 1;
    /* ⚠️ -.02em, not the -.04em the spec asks for. Archivo has no lari sign, so ₾
       comes from the fallback face, and the tighter tracking overlaps it with the
       first digit. Half a hair at 34px against a currency symbol you cannot read. */
    letter-spacing: -.02em;
}
.bp-kpi__unit { font-size: var(--fs-13); font-weight: 600; }

/* ── a card ─────────────────────────────────────────────────────────── */

.bp-proj {
    position: relative;
    display: flex; flex-direction: column;
    background: var(--surface); color: var(--ink);
    border-radius: var(--r-20); overflow: hidden;
    box-shadow: var(--shadow-1);
    transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out);
}
.bp-proj:hover {
    transform: translateY(-3px);
    box-shadow: 0 14px 32px rgba(11, 31, 92, .14);
    text-decoration: none;
}

/* The thumb: the photograph when there is one, a tint from the palette when
   there is not. Navy-family surfaces carry the blueprint grid, so it does too. */
.bp-proj__banner {
    position: relative; display: block; height: 132px; overflow: hidden; flex: none;
    background-image:
        linear-gradient(rgba(255, 255, 255, .07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .07) 1px, transparent 1px);
    background-size: 24px 24px;
}
.bp-proj__shot { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Over a photograph the chips need something to sit on. */
.bp-proj__banner:has(.bp-proj__shot)::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(transparent 45%, rgba(0, 0, 0, .35));
}
.bp-proj__mark {
    position: absolute; left: 14px; bottom: 10px;
    font-family: var(--font-display); font-weight: 900; font-size: 44px; line-height: 1;
    color: rgba(255, 255, 255, .22); letter-spacing: -.04em;
}
.bp-proj__code {
    position: absolute; top: 10px; left: 10px; z-index: 1;
    padding: 3px 8px; border-radius: var(--r-6);
    background: rgba(0, 0, 0, .28); color: #fff;
    font-size: var(--fs-11); font-weight: 500;
}

/* On a card the stage sits over the thumb; in a row it is a column of its own. */
.bp-proj__stage { position: absolute; top: 10px; right: 10px; z-index: 1; }
.bp-proj__stage-pill {
    display: inline-flex; align-items: center; height: 24px; padding: 0 10px;
    border-radius: var(--r-pill);
    font-size: var(--fs-11); font-weight: 600; white-space: nowrap;
    background: var(--surface2); color: var(--ink);
}
/* Each stage gets the pair the spec names, so the colour says which and not just "a stage". */
.bp-stage--tender       { background: #FFF3D6; color: #8A5A00; }
.bp-stage--design       { background: #F0EAFF; color: #6E4BD8; }
.bp-stage--construction { background: #E4EBFF; color: #1F4FD8; }
.bp-stage--handover     { background: #E3F4EC; color: #1B8A5A; }
.bp-stage--warranty     { background: var(--surface2); color: var(--muted); }

.bp-proj__title { display: flex; flex-direction: column; gap: 2px; padding: 12px 16px 0; min-width: 0; }
.bp-proj__name { font-size: var(--fs-15); font-weight: 700; line-height: 1.35; }
.bp-proj__code-row { font-size: var(--fs-11); color: var(--muted); font-weight: 500; }

.bp-proj__where { padding: 4px 16px 0; font-size: 12.5px; color: var(--muted); }

.bp-proj__progress { display: flex; align-items: center; gap: 8px; padding: 12px 16px 0; }
.bp-proj__progress .bp-progress { flex: 1; height: 6px; border-radius: var(--r-pill); }
.bp-proj__pct { font-size: var(--fs-12); font-weight: 700; flex: none; }

.bp-proj__value { display: none; }        /* a column of the table, not of the card */

.bp-proj__foot {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    padding: 10px 16px 14px; margin-top: auto;
    font-size: var(--fs-12); color: var(--muted);
}
/* A square dot, not a round one: the same 7px block the icons are built from. */
.bp-proj__dot { width: 7px; height: 7px; flex: none; background: currentColor; }
.bp-proj__state { font-weight: 600; display: inline-flex; align-items: center; gap: 6px; }
.bp-proj__why { margin-left: auto; }

/* One set of three colours for the bar, the percentage and the word, so they
   cannot disagree about the same job. ⚠️ On schedule the bar is blue, not
   green: green is reserved for the health dot, and a green bar next to a green
   dot reads as one signal twice. */
.bp-proj__pct--ok,   .bp-proj__state--ok   { color: var(--success); }
.bp-proj__pct--warn, .bp-proj__state--warn { color: var(--warning); }
.bp-proj__pct--bad,  .bp-proj__state--bad  { color: var(--danger); }
.bp-proj__bar--ok   { background: var(--primary); }
.bp-proj__bar--warn { background: var(--warning); }
.bp-proj__bar--bad  { background: var(--danger); }
.bp-chip--ok.is-on   { background: var(--success); }
.bp-chip--warn.is-on { background: var(--warning); }
.bp-chip--bad.is-on  { background: var(--danger); }
.bp-chip__dot { width: 7px; height: 7px; flex: none; }
.bp-chip--ok   .bp-chip__dot { background: var(--success); }
.bp-chip--warn .bp-chip__dot { background: var(--warning); }
.bp-chip--bad  .bp-chip__dot { background: var(--danger); }
.bp-chip.is-on .bp-chip__dot { background: #fff; }

.bp-proj-head { display: none; }

/* ── the same rows as a table ───────────────────────────────────────── */

[data-bp-projects-grid].is-list {
    grid-template-columns: 1fr; gap: 0;
    background: var(--surface); border-radius: var(--r-20);
    box-shadow: var(--shadow-1); overflow: hidden;
}

[data-bp-projects-grid].is-list .bp-proj-head,
[data-bp-projects-grid].is-list .bp-proj {
    display: grid;
    grid-template-columns: minmax(230px, 2.2fr) minmax(150px, 1.6fr) 140px 150px 120px;
    align-items: center; gap: var(--sp-4);
    padding: 0 var(--sp-4);
}

[data-bp-projects-grid].is-list .bp-proj-head {
    height: 40px; border-bottom: 1px solid var(--line);
    font-size: 10.5px; font-weight: 700; color: var(--muted);
}

[data-bp-projects-grid].is-list .bp-proj {
    position: relative; min-height: 60px;
    border-radius: 0; background: transparent; box-shadow: none;
    border-bottom: 1px solid var(--line);
}
[data-bp-projects-grid].is-list .bp-proj:last-child { border-bottom: 0; }
[data-bp-projects-grid].is-list .bp-proj:hover { transform: none; box-shadow: none; background: var(--surface2); }

/* The thumb becomes the little tile in front of the name. */
[data-bp-projects-grid].is-list .bp-proj__banner {
    position: absolute; left: var(--sp-4); top: 50%; transform: translateY(-50%);
    width: 34px; height: 34px; border-radius: var(--r-12);
    background-size: 12px 12px;
}
[data-bp-projects-grid].is-list .bp-proj__banner::after { content: none; }
[data-bp-projects-grid].is-list .bp-proj__mark {
    /* inset alone. Adding left:auto/bottom:auto after it anchors the box to the
       top-right corner with no width, and the two letters spill out of the tile. */
    position: absolute; inset: 0; padding: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-12); letter-spacing: 0; color: rgba(255, 255, 255, .92);
}
[data-bp-projects-grid].is-list .bp-proj__code { display: none; }
[data-bp-projects-grid].is-list .bp-proj__title { padding: 0 0 0 46px; }
[data-bp-projects-grid].is-list .bp-proj__where { padding: 0; }
[data-bp-projects-grid].is-list .bp-proj__stage { position: static; }
[data-bp-projects-grid].is-list .bp-proj__progress { padding: 0; }
[data-bp-projects-grid].is-list .bp-proj__value {
    display: block; padding: 0; text-align: right;
    font-size: var(--fs-13); font-weight: 600;
}
/* Five columns is the table; the condition and the access pill come back when
   the rows turn into cards on a narrow screen. */
[data-bp-projects-grid].is-list .bp-proj__foot { display: none; }

/* ── the rail ───────────────────────────────────────────────────────── */

.bp-aside__label {
    font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
    color: var(--muted); text-transform: uppercase;
}
/* ⚠️ Latin only. A Georgian section label takes the plain 11px weight below:
   uppercase does nothing to it and the tracking pulls it apart. */
.bp-aside__label--ka { font-size: var(--fs-11); font-weight: 700; letter-spacing: 0; text-transform: none; }

.bp-export {
    background: var(--cms-navy); color: #fff;
    background-image:
        linear-gradient(rgba(255, 255, 255, .07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .07) 1px, transparent 1px);
    background-size: 40px 40px;
}
.bp-export .bp-card__title, .bp-export .bp-card__sub { color: #8E97B8; }
.bp-export .bp-btn { align-self: flex-start; }

@media (max-width: 1180px) {
    /* The rail goes above the list and lays its cards out side by side. */
    .bp-portfolio { grid-template-columns: 1fr; }
    .bp-portfolio > aside { order: -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
    .bp-portfolio > aside { grid-template-columns: 1fr; }
}

@media (max-width: 820px) {
    /* A five-column table does not fit a phone, and a sideways scroll on the
       company's home page is worse than cards. */
    [data-bp-projects-grid].is-list { background: transparent; box-shadow: none; gap: var(--sp-3); }
    [data-bp-projects-grid].is-list .bp-proj-head { display: none; }
    [data-bp-projects-grid].is-list .bp-proj {
        display: flex; flex-direction: column; padding: 0;
        border-bottom: 0; border-radius: var(--r-20);
        background: var(--surface); box-shadow: var(--shadow-1);
    }
    [data-bp-projects-grid].is-list .bp-proj__banner {
        position: relative; left: auto; top: auto; transform: none;
        width: 100%; height: 132px; border-radius: 0; background-size: 24px 24px;
    }
    [data-bp-projects-grid].is-list .bp-proj__mark {
        inset: auto auto 10px 14px; display: block;
        font-size: 44px; color: rgba(255, 255, 255, .22);
    }
    [data-bp-projects-grid].is-list .bp-proj__code { display: block; }
    [data-bp-projects-grid].is-list .bp-proj__title { padding: 12px 16px 0; }
    [data-bp-projects-grid].is-list .bp-proj__where { padding: 4px 16px 0; }
    [data-bp-projects-grid].is-list .bp-proj__stage { position: absolute; top: 10px; right: 10px; }
    [data-bp-projects-grid].is-list .bp-proj__progress { padding: 12px 16px 0; }
    [data-bp-projects-grid].is-list .bp-proj__value { display: none; }
    [data-bp-projects-grid].is-list .bp-proj__foot { display: flex; }
}


/* ── 9. states ────────────────────────────────────────────────────────── */

.bp-skeleton {
    background: var(--surface2); border-radius: var(--r-8);
    position: relative; overflow: hidden;
}
.bp-skeleton::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .45), transparent);
    animation: bp-shimmer 1.4s infinite;
}
@keyframes bp-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
.bp-skeleton--row { height: var(--row); border-radius: var(--r-12); }
.bp-skeleton--text { height: 12px; }

.bp-empty, .bp-error {
    display: flex; flex-direction: column; align-items: center; gap: var(--sp-3);
    padding: var(--sp-12) var(--sp-6); text-align: center;
}
.bp-empty__title, .bp-error__title { font-weight: 700; font-size: var(--fs-16); }
.bp-empty__sub, .bp-error__sub { font-size: var(--fs-13); color: var(--muted); max-width: 42ch; }
.bp-error__title { color: var(--danger); }

/* ── 10. AI proposal card ─────────────────────────────────────────────── */

/* Yellow, always, and always with all three answers. There is no state in
   which an AI suggestion has already been applied to the data. */
.bp-ai { border-radius: var(--r-20); overflow: hidden; }
.bp-ai__open {
    background: var(--cms-accent); color: var(--cms-navy);
    padding: 18px var(--sp-6);
    display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap;
}
.bp-ai__body { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 200px; flex: 1; }
.bp-ai__label { font-size: var(--fs-12); font-weight: 600; opacity: .75; }
.bp-ai__text { font-size: var(--fs-15); font-weight: 600; line-height: 1.4; }
.bp-ai__edit {
    font: 600 var(--fs-15)/1.4 var(--font-ui); color: var(--cms-navy);
    background: rgba(255, 255, 255, .55); border: 0; border-radius: var(--r-12);
    padding: 10px var(--sp-3); resize: none; width: 100%;
    outline: 2px solid var(--cms-navy);
}
.bp-ai__actions { display: flex; gap: var(--sp-2); flex: none; }
.bp-ai__accepted {
    background: var(--success); color: #fff;
    padding: 18px var(--sp-6);
    display: flex; align-items: center; gap: var(--sp-4);
    animation: bp-pop var(--dur-slow) var(--ease-out) both;
}
.bp-ai__rejected {
    background: var(--surface); color: var(--muted); box-shadow: var(--shadow-1);
    padding: 18px var(--sp-6); display: flex; align-items: center; gap: var(--sp-4);
}
.bp-ai__check {
    width: 28px; height: 28px; border-radius: 50%;
    background: #fff; color: var(--success);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; flex: none;
}

/* ── 10b. the assistant's screen ──────────────────────────────────────── */

/* A conversation beside what it is drawing on. The chat column owns its own
   scroll — the log moves, the header and the composer stay put — because the
   thing being read and the thing being written are both always wanted. */
.bp-chat-screen {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(240px, 320px);
    gap: var(--sp-4);
    height: calc(100vh - 116px); min-height: 460px;
}
.bp-chat { padding: 0; overflow: hidden; gap: 0; min-height: 0; }
.bp-chat__head {
    display: flex; align-items: center; gap: var(--sp-3); flex: none;
    padding: var(--sp-4) var(--sp-5);
}
.bp-chat__log {
    flex: 1; min-height: 0; overflow-y: auto;
    padding: var(--sp-5); display: flex; flex-direction: column; gap: 14px;
}
.bp-chat__foot {
    flex: none; padding: var(--sp-3) var(--sp-4) var(--sp-4);
    display: flex; flex-direction: column; gap: 10px;
}
.bp-chat__row { display: flex; animation: bp-rise var(--dur-base) var(--ease-out) both; }
.bp-chat__row--me { justify-content: flex-end; }
.bp-chat__turn { max-width: 78%; min-width: 0; display: flex; flex-direction: column; gap: 8px; }

.bp-bubble {
    padding: 12px 16px; border-radius: 18px;
    background: var(--surface2); color: var(--ink);
    font-size: var(--fs-14); line-height: 1.55;
    white-space: pre-wrap; overflow-wrap: anywhere;
}
.bp-bubble--me { background: var(--cms-navy); color: #fff; }
.bp-bubble--quiet { color: var(--muted); display: flex; align-items: center; gap: 10px; }

/* An answer the agent wrote in Markdown, read as what it meant: the headings,
   bold, bullets and rules it uses, and nothing else. */
.bp-bubble--rich { white-space: normal; display: flex; flex-direction: column; gap: 8px; }
.bp-bubble--rich p { margin: 0; white-space: pre-wrap; }
.bp-bubble--rich h4 { margin: 0; font-size: var(--fs-14); font-weight: 700; }
.bp-bubble--rich ul, .bp-bubble--rich ol {
    margin: 0; padding-inline-start: 22px;
    display: flex; flex-direction: column; gap: 4px;
}
.bp-bubble--rich hr { width: 100%; height: 1px; border: 0; margin: 0; background: var(--border); }
.bp-bubble--rich code {
    font: var(--fs-12) var(--font-mono);
    background: rgba(19, 26, 51, .07); border-radius: var(--r-6); padding: 1px 5px;
}
.bp-bubble--rich table {
    display: block; overflow-x: auto; width: 100%;
    border-collapse: collapse; font-size: var(--fs-12);
}
.bp-bubble--rich td { padding: 5px 8px; text-align: start; vertical-align: top; }
.bp-bubble--rich thead td { font-weight: 700; }
.bp-bubble--rich tbody tr:nth-child(odd) td { background: rgba(19, 26, 51, .05); }

/* What the agent read to answer. A chip per tool, in the AI's yellow. */
.bp-act {
    font-size: var(--fs-11); font-weight: 600;
    background: var(--warning-bg); color: var(--warning-ink);
    padding: 3px 10px; border-radius: var(--r-pill);
}

.bp-typing { display: inline-flex; gap: 4px; align-items: center; flex: none; }
.bp-typing i {
    width: 6px; height: 6px; border-radius: 50%; background: currentColor;
    animation: bp-blink 1.2s infinite ease-in-out;
}
.bp-typing i:nth-child(2) { animation-delay: .2s; }
.bp-typing i:nth-child(3) { animation-delay: .4s; }
@keyframes bp-blink {
    0%, 80%, 100% { opacity: .25; transform: translateY(0); }
    40% { opacity: 1; transform: translateY(-3px); }
}

.bp-chat__field {
    flex: 1; min-width: 0; height: var(--input);
    border: 0; outline: 0; border-radius: var(--r-pill);
    background: var(--surface2); color: var(--ink);
    padding: 12px 18px; resize: none;
    font: var(--fs-14) var(--font-ui); line-height: var(--lh-body);
}
.bp-chat__field:focus { box-shadow: 0 0 0 3px rgba(31, 79, 216, .25); }
.bp-chat__send {
    height: var(--input); width: var(--input); flex: none;
    border-radius: 50%; background: var(--cms-primary); color: #fff;
    font-size: var(--fs-18); transition: transform var(--dur-fast) var(--ease-out);
}
.bp-chat__send:hover { transform: scale(1.06); }
.bp-chat__send[disabled] { opacity: .45; transform: none; }

/* A question offered rather than typed. */
.bp-chip-ask {
    height: 32px; padding: 0 12px; border-radius: var(--r-pill);
    background: var(--surface2); color: var(--ink); font-size: var(--fs-12);
}
.bp-chip-ask:hover { background: var(--cms-accent); color: var(--cms-navy); }

/* The proposal. Yellow while it is only a proposal, green once it has become
   the data, grey when it was refused: the three states, and no fourth. */
.bp-prop {
    border-radius: var(--r-16); padding: 14px 16px;
    display: flex; flex-direction: column; gap: 10px;
    background: var(--cms-accent); color: var(--cms-navy);
    transition: background var(--dur-slow) var(--ease-out);
}
.bp-prop--done { background: var(--success); color: #fff; animation: bp-pop var(--dur-slow) var(--ease-out) both; }
.bp-prop--gone { background: var(--surface2); color: var(--muted); }
/* „დაფაზე ნახვა →" after a confirmation: the link blue on the success green was unreadable. */
.bp-prop--done .bp-btn--link { color: #fff; text-decoration: underline; }
.bp-prop__head {
    display: flex; justify-content: space-between; align-items: center; gap: 8px;
    font-size: var(--fs-11); font-weight: 700;
}
.bp-prop__group { display: flex; flex-direction: column; gap: 6px; }
.bp-prop__item { display: grid; grid-template-columns: minmax(0, 1fr) 120px 132px auto; gap: 6px; align-items: center; }
.bp-prop__line { font-size: var(--fs-12); line-height: 1.5; }
.bp-prop .bp-input, .bp-prop .bp-textarea {
    height: 36px; padding: 0 10px; font-size: var(--fs-12);
    background: rgba(255, 255, 255, .62); color: var(--cms-navy); box-shadow: none;
}
.bp-prop .bp-textarea { height: auto; min-height: 120px; padding: 8px 10px; }
.bp-prop__drop { color: var(--cms-navy); width: 26px; height: 26px; flex: none; border-radius: var(--r-8); }
.bp-prop__drop:hover { background: rgba(255, 255, 255, .5); }
.bp-prop__no {
    height: 36px; padding: 0 14px; border-radius: var(--r-pill);
    background: transparent; border: 1.5px solid currentColor; color: inherit;
    font-weight: 600; font-size: var(--fs-13);
}

/* Where an AI reading of a record is printed. The Markdown writer brings its
   own typography; this only says how big it is. */
.bp-ai-read { font-size: var(--fs-13); line-height: 1.6; }
.bp-ai-read:empty { display: none; }

/* The rail beside the chat: what the agent is briefed on, what it watches, and
   the conversations it has already had. */
.bp-chat-rail { overflow-y: auto; min-height: 0; display: flex; flex-direction: column; gap: var(--sp-4); }
/* Three Georgian words in a 320px rail: the tabs share the width rather than
   pushing a scrollbar under the card. */
.bp-chat-rail .bp-seg { display: flex; width: 100%; }
.bp-chat-rail .bp-seg__opt {
    flex: 1 1 0; min-width: 0; padding: 0 var(--sp-2);
    font-size: var(--fs-12);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bp-chat-rail__list { display: flex; flex-direction: column; gap: 6px; font-size: var(--fs-13); }
.bp-chat-rail__row { display: flex; justify-content: space-between; gap: var(--sp-2); }

@media (max-width: 1100px) {
    /* The rail stops being a rail: the conversation takes the width and what it
       draws on follows underneath. */
    .bp-chat-screen { grid-template-columns: minmax(0, 1fr); height: auto; }
    .bp-chat { height: 70vh; min-height: 420px; }
    .bp-chat-rail { overflow: visible; }
}

@media (max-width: 820px) {
    .bp-chat__turn { max-width: 92%; }
    .bp-prop__item { grid-template-columns: minmax(0, 1fr) auto; }
    /* The promise that nothing is written without a confirmation keeps its
       place on a phone — on its own line, rather than squeezing the name it
       sits beside into three. */
    .bp-chat__head { flex-wrap: wrap; padding: var(--sp-3) var(--sp-4); }
    .bp-chat__head .bp-spacer { margin-left: 0; }
}

/* Two things the shared conversation templates carry that only the drawer shows: the time
   under each turn, and the short „წერს…" in place of the page's longer wait notice. The full
   page keeps the look it was compared against. */
.bp-chat__when { display: none; }
.bp-chat__think-short { display: none; }

/* Where an answer points: light buttons that navigate and change nothing — the tint the
   prototype gives „გრაფიკში ნახვა" beside the navy „დადასტურება". */
.bp-chat__links { display: flex; gap: 6px; flex-wrap: wrap; }
.bp-chat__link {
    height: 32px; padding: 0 12px; border-radius: var(--r-pill);
    background: var(--ai-tint, #F0F4FF); color: var(--ai-tint-ink, #1F4FD8);
    font-size: var(--fs-12); font-weight: 600;
    display: inline-flex; align-items: center; white-space: nowrap;
}
.bp-chat__link:hover { text-decoration: none; filter: brightness(.97); }

/* ── 10b′. the AI drawer (⌘J) ─────────────────────────────────────────────
   The assistant over any page (prototype: CMS Dashboard v2 → „AI ⌘J"). Values are the
   handoff's own: a 44px yellow pill in the header, a 440px white drawer 16px off three edges,
   a navy head on the 24px grid. ⚠️ Three of its light greys are not tokens — #F6F7FB for the
   AI's bubble and the field, #F0F4FF / #1F4FD8 for the chips — so they are local variables
   here, swapped for the dark theme's surfaces below rather than left glaring on navy. */

.bp-ai-btn {
    position: relative; flex: none;
    height: var(--control); padding: 0 14px 0 6px;
    border-radius: var(--r-pill);
    background: var(--cms-accent); color: var(--cms-navy);
    box-shadow: 0 6px 16px rgba(255, 184, 0, .3);
    display: inline-flex; align-items: center; gap: 8px;
    font: 700 13px var(--font-ui);
    transition: transform .15s, background var(--dur-base), color var(--dur-base), box-shadow var(--dur-base);
}
.bp-ai-btn:hover { transform: translateY(-1px); }
.bp-ai-btn__mark {
    width: 32px; height: 32px; border-radius: 50%; flex: none;
    background: var(--cms-navy); color: var(--cms-accent); --i-accent: var(--cms-accent);
    display: flex; align-items: center; justify-content: center;
}
.bp-ai-btn__kbd {
    font: 600 11px var(--font-mono);
    background: rgba(11, 31, 92, .12); border-radius: var(--r-pill); padding: 3px 7px;
}
/* Open: the pill turns navy, which is how it says the drawer belongs to it. */
.bp-ai-btn.is-open { background: var(--cms-navy); color: #fff; box-shadow: 0 6px 16px rgba(11, 31, 92, .25); }

/* ⚠️ The AI pill made the header one item longer, and at 1440 a screen with its own header
   action (the dashboard's Sheet sync) pushed the account onto a second row. Below 1600 the
   pill and the search give up their key hints first — both shortcuts still work, and the
   title attribute still names them — and the search may shrink further before anything wraps. */
@media (max-width: 1600px) {
    .bp-ai-btn__kbd, .bp-search kbd { display: none; }
    .bp-search { min-width: 96px; }
}
/* At laptop widths the search becomes the round ⌘K button it already is on a phone. */
@media (max-width: 1400px) {
    .bp-search { flex: 0 0 var(--control); width: var(--control); min-width: 0; padding: 0; justify-content: center; }
    .bp-search span { display: none; }
    .bp-search::after { content: "⌘K"; font-family: var(--font-mono); font-size: var(--fs-11); }
}
.bp-ai-btn.is-open .bp-ai-btn__kbd { background: rgba(255, 255, 255, .15); }
/* A proposal nobody has decided on. Yellow, as the design asks — with a navy ring, because a
   yellow dot on a yellow pill is no dot at all. */
.bp-ai-btn__dot {
    position: absolute; top: -3px; right: -3px;
    width: 12px; height: 12px; border-radius: 50%;
    background: var(--cms-accent); border: 2px solid var(--cms-navy);
}

.bp-ai-drawer {
    --ai-quiet: #F6F7FB;
    --ai-tint: #F0F4FF;
    --ai-tint-ink: #1F4FD8;
    position: fixed; top: 16px; right: 16px; bottom: 16px; z-index: 81;
    width: 440px; max-width: calc(100vw - 32px);
    background: var(--surface); color: var(--ink);
    border-radius: 24px; box-shadow: 0 24px 60px rgba(11, 31, 92, .3);
    display: flex; flex-direction: column; overflow: hidden;
    animation: bp-ai-in .3s cubic-bezier(.2, .8, .2, 1) both;
}
:root[data-theme="dark"] .bp-ai-drawer { --ai-quiet: var(--surface2); --ai-tint: var(--info-bg); --ai-tint-ink: #C9D6FF; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .bp-ai-drawer { --ai-quiet: var(--surface2); --ai-tint: var(--info-bg); --ai-tint-ink: #C9D6FF; }
}
@keyframes bp-ai-in {
    from { opacity: 0; transform: translateX(32px); }
    to   { opacity: 1; transform: none; }
}
/* The scrim the overlay stack puts in front of the drawer: lighter than a modal's, because
   the page under it is still the subject — and above every panel, as the drawer is. */
.bp-scrim:has(+ .bp-ai-drawer) { z-index: 80; background: rgba(11, 31, 92, .2); }

.bp-ai-drawer__head {
    flex: none; display: flex; align-items: center; gap: 12px;
    padding: 16px 18px;
    background-color: var(--cms-navy); color: #fff;
    background-image:
        linear-gradient(rgba(255, 255, 255, .07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .07) 1px, transparent 1px);
    background-size: 24px 24px;
}
.bp-ai-drawer__mark {
    width: 36px; height: 36px; border-radius: 50%; flex: none;
    background: var(--cms-accent); color: var(--cms-navy); --i-accent: var(--cms-navy);
    display: flex; align-items: center; justify-content: center;
}
.bp-ai-drawer__titles { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.bp-ai-drawer__title { font-weight: 700; font-size: 15px; }
.bp-ai-drawer__sub {
    font-size: 11.5px; color: #C9D1EA;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bp-ai-drawer__full {
    flex: none; height: 32px; padding: 0 12px; border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .12); color: #fff;
    font-size: 12px; font-weight: 600; white-space: nowrap;
    display: inline-flex; align-items: center;
}
.bp-ai-drawer__full:hover { background: rgba(255, 255, 255, .2); text-decoration: none; }
.bp-ai-drawer__x {
    flex: none; width: 32px; height: 32px; border-radius: 50%;
    background: rgba(255, 255, 255, .12); color: #fff; font-size: 16px;
    display: flex; align-items: center; justify-content: center;
}
.bp-ai-drawer__x:hover { background: rgba(255, 255, 255, .2); }

.bp-ai-drawer__log {
    flex: 1; min-height: 0; overflow-y: auto;
    padding: 16px 18px; display: flex; flex-direction: column; gap: 12px;
}
.bp-ai-drawer .bp-chat__turn { max-width: 88%; gap: 4px; }
.bp-ai-drawer .bp-chat__row--me .bp-chat__turn { align-items: flex-end; }
.bp-ai-drawer .bp-bubble {
    padding: 11px 14px; border-radius: 16px;
    background: var(--ai-quiet); font-size: 13.5px; line-height: 1.5;
}
.bp-ai-drawer .bp-bubble--me { background: var(--cms-navy); color: #fff; }
.bp-ai-drawer .bp-bubble--quiet { padding: 10px 14px; font-size: 13px; color: #8E97B8; }
.bp-ai-drawer .bp-chat__when {
    display: block;
    font: 10.5px var(--font-mono); color: #8E97B8;
}
.bp-ai-drawer .bp-chat__think-long { display: none; }
.bp-ai-drawer .bp-chat__think-short { display: inline; }
/* The proposal's buttons at the drawer's 32px. */
.bp-ai-drawer .bp-prop [data-bp-prop-apply] { height: 32px; padding: 0 14px; font-size: 13.5px; }
.bp-ai-drawer .bp-prop__no { height: 32px; }
/* A proposed task's four fields in 400px: the name and the remove button on one line, the
   group and the date under it. Named placements — auto-placement would put the group in the
   remove button's 26px column. */
.bp-ai-drawer .bp-prop__item { grid-template-columns: minmax(0, 1fr) 132px 26px; }
.bp-ai-drawer .bp-prop__item [data-bp-prop-desc] { grid-column: 1 / 3; grid-row: 1; }
.bp-ai-drawer .bp-prop__item [data-bp-prop-drop] { grid-column: 3; grid-row: 1; }
.bp-ai-drawer .bp-prop__item [data-bp-prop-category] { grid-column: 1; grid-row: 2; }
.bp-ai-drawer .bp-prop__item [data-bp-prop-end] { grid-column: 2 / 4; grid-row: 2; }

.bp-ai-drawer__chips { flex: none; padding: 10px 18px 0; display: flex; gap: 6px; flex-wrap: wrap; }
.bp-ai-drawer__chip {
    height: 30px; padding: 0 11px; border-radius: var(--r-pill);
    background: var(--ai-tint); color: var(--ai-tint-ink);
    font-size: 12px; font-weight: 600;
}
.bp-ai-drawer__chip:hover { filter: brightness(.97); }

.bp-ai-drawer__compose { flex: none; padding: 12px 18px 16px; display: flex; gap: 8px; align-items: center; }
.bp-ai-drawer__field {
    flex: 1; min-width: 0; height: 46px;
    border: 0; outline: 0; border-radius: var(--r-pill);
    background: var(--ai-quiet); color: var(--ink);
    padding: 0 16px; font: 13.5px var(--font-ui);
}
.bp-ai-drawer__field:focus { box-shadow: 0 0 0 3px rgba(31, 79, 216, .25); }
.bp-ai-drawer__send {
    flex: none; width: 46px; height: 46px; border-radius: 50%;
    background: var(--cms-accent); color: var(--cms-navy);
    display: flex; align-items: center; justify-content: center;
    transition: transform var(--dur-fast) var(--ease-out);
}
.bp-ai-drawer__send:hover { transform: scale(1.06); }
.bp-ai-drawer__send[disabled] { opacity: .45; transform: none; }

/* ── agentic mode: the mode row and the plan card (screens/ai/01–04) ──────
   Prototype: CMS Dashboard v2 → AI ⌘J. The step's state is `data-status` on
   the row, painted by blueprint-assistant.js from what the server said; the
   circle, its mark's colour, the caption's colour and the row's tint are all
   here, so one table decides the look of a state. */

/* Back from a plan step's page change: already open, so no slide-in. */
.bp-ai-drawer.is-resumed { animation: none; }

.bp-ai-mode {
    flex: none; display: flex; align-items: center; gap: 6px;
    padding: 10px 16px; border-bottom: 1px solid var(--border);
}
.bp-ai-mode__label { font-size: 10.5px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.bp-ai-mode__track {
    flex: 1; min-width: 0; display: flex; gap: 2px; padding: 3px;
    border-radius: var(--r-pill); background: var(--ai-quiet);
}
.bp-ai-mode__pill {
    /* ⚠️ Sized by their words, not three equal parts: equal thirds cut „ყოველ ნაბიჯზე" and
       „სრული მართვა" to an ellipsis in a 440px drawer while „ჩაწერაზე" had room to spare. */
    flex: 1 1 auto; min-width: 0; height: 28px; padding: 0 7px; border-radius: var(--r-pill);
    background: transparent; color: var(--muted);
    font-size: 10.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bp-ai-mode__pill[aria-checked="true"] { background: var(--cms-navy); color: #fff; }

.bp-plan {
    width: 100%; overflow: hidden;
    border: 1px solid var(--border); border-radius: 16px; background: var(--surface);
}
/* The card takes the turn's full width, not the bubble's 88%. */
.bp-chat__turn:has(.bp-plan),
.bp-ai-drawer .bp-chat__turn:has(.bp-plan) { max-width: 100%; width: 100%; }
.bp-plan__head {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 14px; background: var(--ai-quiet, var(--surface2));
}
.bp-plan__mark { width: 8px; height: 8px; flex: none; background: var(--cms-accent); }
.bp-plan__title { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 700; color: var(--ink); }
.bp-plan__count { font-size: 11px; color: var(--muted); }
.bp-plan__stop {
    height: 24px; padding: 0 10px; border-radius: var(--r-pill);
    background: var(--danger-bg); color: var(--danger); font-size: 11px; font-weight: 700;
}
.bp-plan__steps { display: flex; flex-direction: column; }
.bp-plan__step {
    --step-dot: var(--border); --step-mark: var(--muted); --step-ink: #8E97B8; --step-bg: transparent;
    display: flex; gap: 10px; padding: 9px 14px;
    border-top: 1px solid var(--border); background: var(--step-bg);
}
.bp-plan__step[data-status="running"]   { --step-dot: var(--info);    --step-mark: #fff;          --step-ink: var(--info);        --step-bg: var(--ai-tint); }
.bp-plan__step[data-status="waiting"]   { --step-dot: var(--cms-accent); --step-mark: var(--cms-navy); --step-ink: var(--warning-ink); --step-bg: var(--warning-bg); }
.bp-plan__step[data-status="done"]      { --step-dot: var(--success); --step-mark: #fff;          --step-ink: var(--success); }
.bp-plan__step[data-status="skipped"]   { --step-dot: var(--border);  --step-mark: var(--muted);  --step-ink: #8E97B8; }
.bp-plan__step[data-status="stopped"],
.bp-plan__step[data-status="forbidden"],
.bp-plan__step[data-status="error"]     { --step-dot: var(--danger);  --step-mark: #fff;          --step-ink: var(--danger);      --step-bg: var(--danger-bg); }
.bp-plan__dot {
    width: 20px; height: 20px; flex: none; margin-top: 1px; border-radius: 50%;
    background: var(--step-dot); color: var(--step-mark);
    display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800;
}
.bp-plan__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.bp-plan__line { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }
.bp-plan__kind {
    flex: none; padding: 2px 7px; border-radius: var(--r-pill);
    background: var(--ai-tint); color: var(--ai-tint-ink); font-size: 10.5px;
}
.bp-plan__label { font-size: 12.5px; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.bp-plan__detail, .bp-plan__message { font-size: 11.5px; line-height: 1.45; color: var(--muted); overflow-wrap: anywhere; }
.bp-plan__decide { display: flex; gap: 6px; margin-top: 4px; flex-wrap: wrap; }
.bp-plan__yes, .bp-plan__no {
    height: 28px; padding: 0 12px; border-radius: var(--r-pill); font-size: 11.5px;
}
.bp-plan__yes { background: var(--cms-navy); color: #fff; font-weight: 700; }
.bp-plan__no { background: var(--surface); color: var(--muted); font-weight: 600; box-shadow: inset 0 0 0 1px var(--border); }
.bp-plan__status { font-size: 10.5px; font-weight: 600; color: var(--step-ink); }
.bp-plan__status:empty { display: none; }
.bp-plan__undo {
    align-self: flex-start; padding: 0; background: none;
    color: var(--info); font-size: 11px; font-weight: 600; text-decoration: underline;
}
/* The result bubble's first button is the way to what was made: navy, as in the design. */
.bp-chat__link--primary { background: var(--cms-navy); color: #fff; }

/* A record's own history: what the assistant wrote on it, with „გაუქმება" for 24h. */
.bp-ai-hist { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.bp-ai-hist__title { font-size: var(--fs-12, 12px); font-weight: 700; color: var(--muted); }
.bp-ai-hist__row {
    display: flex; align-items: flex-start; gap: 10px; padding: 8px 10px;
    border-radius: 12px; background: var(--ai-tint, var(--info-bg));
}
.bp-ai-hist__row.is-undone { opacity: .6; }
.bp-ai-hist__badge {
    flex: none; height: 20px; padding: 0 6px; border-radius: var(--r-pill);
    background: var(--cms-accent); color: var(--cms-navy);
    font-size: 10.5px; font-weight: 800; display: inline-flex; align-items: center;
}
.bp-ai-hist__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
.bp-ai-hist__label { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.bp-ai-hist__line, .bp-ai-hist__undone { color: var(--muted); font-size: 11.5px; }
.bp-ai-hist__undo {
    flex: none; height: 26px; padding: 0 10px; border-radius: var(--r-pill);
    background: var(--surface); color: var(--danger); box-shadow: inset 0 0 0 1px var(--border);
    font-size: 11.5px; font-weight: 700;
}

/* Live form fill: a field the assistant has just written lights up in the AI tint and fades back
   (blueprint-assistant.js adds the class; the reduced-motion rule above shortens the fade). */
.bp-ai-filled {
    animation: bp-ai-filled 1.8s ease-out 1;
}
@keyframes bp-ai-filled {
    /* No closing frame: it fades back to the field's own colours, whatever they are. */
    0%, 35% { background-color: var(--ai-tint); box-shadow: 0 0 0 2px var(--info); }
}

/* A phone: the button folds to its 44px circle, and the drawer becomes a sheet from the
   bottom, the full height of the screen. In the phone header the button sits where the design
   puts it — after the search, before the bell (orders 3 and 4 there). */
@media (max-width: 820px) {
    .bp-ai-btn {
        order: 3; width: var(--control); padding: 0; justify-content: center; gap: 0;
    }
    .bp-ai-btn__label, .bp-ai-btn__kbd { display: none; }

    .bp-ai-drawer {
        top: 12px; left: 0; right: 0; bottom: 0;
        width: auto; max-width: none;
        border-radius: 24px 24px 0 0;
        padding-bottom: env(safe-area-inset-bottom, 0px);
        animation-name: bp-ai-up;
    }
    .bp-ai-drawer .bp-chat__turn { max-width: 92%; }
}
@keyframes bp-ai-up {
    from { opacity: 0; transform: translateY(40px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .bp-ai-drawer { animation: none; }
}
@media print {
    .bp-ai-btn, .bp-ai-drawer { display: none !important; }
}

/* ── 10c. the composer ────────────────────────────────────────────────── */

.bp-compose-screen {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
    gap: var(--sp-4); align-items: start;
}

/* Addresses offered while one is typed. A menu, so it floats over what is
   under it rather than pushing the form down a row at a time. */
.bp-suggest {
    position: absolute; left: 0; right: 0; top: 100%; z-index: 30;
    margin-top: 4px; overflow: hidden;
    border-radius: var(--r-14); background: var(--surface);
    box-shadow: var(--shadow-3);
    display: flex; flex-direction: column;
}
.bp-suggest__row {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px; text-align: start; width: 100%;
    background: transparent;
}
.bp-suggest__row:hover { background: var(--surface2); }

/* A setting with two ends and no numbers on the track — the readout beside it
   is where the number is. */
.bp-range {
    width: 100%; height: 20px; margin: 0;
    accent-color: var(--cms-primary); background: transparent;
}

@media (max-width: 1100px) {
    .bp-compose-screen { grid-template-columns: minmax(0, 1fr); }
}

/* ── 11. responsive ───────────────────────────────────────────────────── */

/* Tablet and below: the rail leaves the side and becomes a floating bottom bar
   with the raised capture button in the middle. The grid loses its first
   column; the rail is fixed, so it no longer occupies one. */
@media (max-width: 1100px) {
    .bp-shell,
    .bp-shell[data-expanded="1"] { grid-template-columns: minmax(0, 1fr); }

    .bp-grid--hero  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .bp-grid--split { grid-template-columns: minmax(0, 1fr); }

    .bp-rail {
        position: fixed; left: var(--sp-4); right: var(--sp-4); bottom: var(--sp-4);
        top: auto; height: auto; padding: 0; z-index: 45;
    }
    .bp-rail__box {
        flex: none; flex-direction: row; align-items: center;
        height: var(--tab-height); width: auto;
        padding: 0 var(--sp-2); gap: var(--sp-1);
        /* Visible, not hidden: the capture button is raised half out of the bar and
           its ring is a cut-out in the page colour. Clipped, it is a half-circle. */
        border-radius: var(--r-24); overflow: visible;
    }
    .bp-rail__logo { display: none; }
    .bp-header__logo { display: flex; }

    .bp-shell .bp-rail__item,
    .bp-shell[data-expanded="1"] .bp-rail__item {
        flex: 1 1 0; width: auto; min-width: 0; height: 56px;
        flex-direction: column; justify-content: center; gap: 2px;
        padding: 0 var(--sp-1); border-radius: var(--r-14);
        font-size: 10px; line-height: 1.1;
        white-space: normal; text-align: center;
    }
    .bp-rail__item svg { width: 20px; height: 20px; }
    /* The label is the short form down here; the long one would wrap to three
       lines in Georgian. The [data-expanded] selector has to be matched rather
       than merely overridden, or a rail left expanded on a desktop brings the
       long labels back when the window narrows. */
    .bp-shell .bp-rail__label,
    .bp-shell[data-expanded="1"] .bp-rail__label,
    .bp-shell[data-expanded="1"] .bp-rail__wordmark,
    .bp-shell[data-expanded="1"] .bp-rail__me-name { display: none; }
    .bp-shell .bp-rail__short {
        display: block; font-size: 10px; font-weight: 600;
        max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    /* The bottom bar has no row end: back to the corner of the icon, whatever the
       rail was left as on a desk. */
    .bp-rail__badge,
    .bp-shell[data-expanded="1"] .bp-rail__badge {
        position: absolute; top: 4px; right: 6px; margin: 0;
        min-width: 18px; height: 16px; padding: 0 5px; font-size: 10px;
    }

    /* Bar order: the capture button in the middle, the items split around it.
       Each item carries its own even number (--o, written by the layout) and the
       camera an odd one for the width in play, so the middle stays the middle
       however many items this person's tools put on the bar. Without an explicit
       order the camera sorts to the end, every other child being at 0. */
    .bp-rail__item { order: var(--o, 0); }
    .bp-rail__cam {
        display: flex; order: var(--cam-bar, 1); flex: 1 1 0; min-width: 0;
        justify-content: center; align-items: center; height: 56px;
    }
    .bp-rail__more { order: 1001; }
    .bp-rail__foot { order: 1101; }
    .bp-rail__cam button {
        width: var(--capture); height: var(--capture); border-radius: 50%;
        /* Half out of the bar: the button's centre sits on the bar's top edge, and
           the 5px ring is the page showing through. */
        background: var(--cms-accent); margin-top: -36px;
        border: 5px solid var(--bg);
        display: flex; align-items: center; justify-content: center;
        box-shadow: 0 8px 20px rgba(11, 31, 92, .35);
        transition: transform var(--dur-fast);
    }
    .bp-rail__cam button:active { transform: scale(.94); }

    .bp-rail__foot {
        position: static; background: none;
        margin: 0 0 0 var(--sp-1); padding: 0 0 0 var(--sp-2);
        border-top: 0; border-left: 1px solid rgba(255, 255, 255, .1);
        flex-direction: row; align-items: center;
    }
    .bp-rail__foot .bp-rail__tool,
    .bp-rail__me { padding: 0 var(--sp-2); }
    /* There is no width to expand into down here. */
    .bp-rail__tool--expand { display: none; }

    /* The bar sits over the page, so the page needs room under it. */
    .bp-main { padding: var(--sp-4) var(--sp-4) calc(var(--tab-height) + 40px); }
    .bp-toast-dock { bottom: calc(var(--tab-height) + 32px); }
    /* The search becomes a round button. flex and min-width have to go with the
       width: a 260px basis with a 120px floor beats a width outright, which is how
       it kept a whole header row to itself and pushed the bell and the account onto
       a second one. */
    .bp-search {
        flex: 0 0 var(--control); width: var(--control); min-width: 0;
        padding: 0; justify-content: center;
    }
    .bp-search span, .bp-search kbd { display: none; }
    .bp-search::after { content: "⌘K"; font-family: var(--font-mono); font-size: var(--fs-11); }
    .bp-crumb { display: none; }
}

/* The bar is Home / Tasks / Gantt / ● / Reports / QA / More — the design's middle
   bar, nine slots — and everything else is in the "მეტი" sheet, the theme and the
   language with it.

   The design's widest tablet bar carries its tier-3 items too, but it is drawing
   ten of them; this platform has fifteen tools and sixteen slots across 1024px
   ellipse every Georgian label to four letters. Above 1100px the full rail is back
   at the side, which is the better answer to "show me everything" anyway. */
@media (max-width: 1100px) {
    .bp-shell .bp-rail__item--t3,
    .bp-shell .bp-rail__foot { display: none; }
    .bp-rail__more {
        display: flex; flex: 1 1 0; min-width: 0; height: 56px;
        flex-direction: column; align-items: center; justify-content: center; gap: 2px;
        border-radius: var(--r-14);
        background: transparent; color: #C9D1EA;
        font-size: 10px; font-weight: 600; line-height: 1.1;
    }
    .bp-rail__more.is-on { background: var(--cms-accent); color: var(--cms-navy); }
    .bp-rail__more.is-on svg { stroke: var(--cms-navy); }

    .bp-more {
        position: fixed; left: var(--sp-4); right: var(--sp-4); bottom: 104px; z-index: 46;
        background-color: var(--cms-navy); color: #fff;
        border-radius: var(--r-24); padding: var(--sp-3);
        display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
        box-shadow: 0 24px 60px rgba(11, 31, 92, .4);
        animation: bp-rise var(--dur-base) var(--ease-out) both;
        background-image:
            linear-gradient(rgba(255, 255, 255, .06) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255, 255, 255, .06) 1px, transparent 1px);
        background-size: var(--grid-step-sm) var(--grid-step-sm);
    }
    .bp-more__item {
        position: relative;
        height: var(--tab-height); border-radius: var(--r-16);
        background: rgba(255, 255, 255, .08); color: #C9D1EA;
        display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
        font-size: var(--fs-12); font-weight: 600; text-align: center; padding: 0 6px;
    }
    .bp-more__item[aria-current] { background: var(--cms-accent); color: var(--cms-navy); }
    .bp-more__item[aria-current] svg { stroke: var(--cms-navy); }
    .bp-more__item span {
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
    }
    /* The sheet is what the bar dropped, and at this width the bar still has its
       tier-2 items. Listing them twice would make the sheet a second menu rather
       than the rest of this one. */
    .bp-more__item--t2 { display: none; }
}

/* Phone: the bar is Home / Tasks / ● / QA / More and nothing else — five 10px
   Georgian labels across 390px already ellipse to one letter each, and eight are
   unreadable. Everything the bar drops is in the sheet. */
@media (max-width: 820px) {
    .bp-shell .bp-rail__item--t2 { display: none; }
    .bp-rail__cam { order: var(--cam-phone, 1); }
    /* …and here the bar has given them up, so the sheet takes them back. */
    .bp-more__item--t2 { display: flex; }

    /* Five slots across 390px: every pixel between them comes off the label, and
       "სამუშაოები" is the longest of the five by some way. The capture column is
       only ever as wide as its button, so it is given that and no share of the
       rest — which is what buys the longest label the room to read whole. */
    .bp-rail__box { padding: 0 var(--sp-1); gap: 2px; }
    .bp-shell .bp-rail__item,
    .bp-shell[data-expanded="1"] .bp-rail__item { padding: 0 1px; }
    /* Narrower than its button, which simply overhangs into the gaps either side —
       it is raised out of the bar and drawn over everything anyway. The four label
       columns stay equal, so the capture button stays on the bar's centre line. */
    .bp-rail__cam { flex: 0 0 48px; }

    .bp-grid--2, .bp-grid--3, .bp-grid--hero, .bp-grid--fill { grid-template-columns: minmax(0, 1fr); }

    /* A segmented control is one row of pills at a desk and two on a phone:
       four Georgian words do not fit across 390px, and a track that runs off
       the card takes the last choice with it. */
    /* max-width is what makes the wrap happen at all: an inline-flex track
       sizes to its content, so without a bound there is nothing to wrap at. */
    .bp-seg { flex-wrap: wrap; height: auto; max-width: 100%; padding: var(--sp-1); border-radius: var(--r-20); }

    /* ── the phone header ──────────────────────────────────────────────
       One deterministic row — mark, project, ⌘K, bell, account — and then the
       screen's own buttons on a row of their own beneath it. Letting the
       header simply wrap put those buttons somewhere different on every
       screen, and keeping them on the first row squeezed the project name to
       nothing. The language pill leaves entirely: switching language is in the
       "more" sheet, which is where the design puts it. */
    .bp-header { gap: var(--sp-2); flex-wrap: wrap; }
    .bp-lang { display: none; }
    /* The mark alone is the brand at this size. */
    .bp-header__logo span { display: none; }

    .bp-header__logo    { order: 1; }
    /* basis 0, not auto: a long project name is the chip's intrinsic width, and
       with an auto basis it claims a whole row for itself and pushes the rest of
       the header onto a third and fourth line. */
    .bp-project         { order: 2; flex: 1 1 0; min-width: 0; padding-right: var(--sp-2); }
    .bp-search          { order: 3; margin-left: 0; }
    .bp-header__bell    { order: 4; }
    .bp-avatar          { order: 5; }
    /* A screen's own buttons wrap: Tasks puts a segmented control and four
       buttons here, and a row that cannot wrap loses the last of them off the
       side of the phone. */
    .bp-header__actions { display: flex; order: 6; flex: 1 1 100%; gap: var(--sp-2); flex-wrap: wrap; }
    .bp-header__actions .bp-btn { flex: 1 1 auto; }
    .bp-header__actions .bp-seg { flex: 1 1 100%; }

    .bp-project__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    .bp-panel { width: 100vw; }
}

/* ── a phone held sideways ─────────────────────────────────────────────────
   390px of height with a 72px bar across the bottom leaves nothing to work in,
   so the design puts the rail back on the left: 64px of it in a 96px column,
   icons only, the capture button no longer raised and no longer ringed. The
   items are the phone's five — turning the phone does not change what the
   person can reach.

   Keyed on height, not width. A phone in landscape is 844×390 and a tablet is
   1024×768; both are under 1100px wide, and only the first one is out of room. */
@media (max-width: 1100px) and (orientation: landscape) and (max-height: 540px) {
    .bp-shell,
    .bp-shell[data-expanded="1"] { grid-template-columns: 96px minmax(0, 1fr); }

    /* Back in the flow, so it takes the grid column it is given. Fixed — which is
       what makes a bottom bar float over the page — would leave the column empty
       and the header would run underneath it. */
    .bp-rail {
        position: sticky; top: 0; align-self: start;
        left: auto; right: auto; bottom: auto;
        width: auto; height: 100vh; padding: 0;
        display: flex; align-items: stretch;
    }
    .bp-rail__box {
        flex-direction: column; align-items: center; justify-content: flex-start;
        width: 64px; height: auto; max-height: 100%;
        margin: var(--sp-4) 0 var(--sp-4) var(--sp-4);
        padding: 12px 0; gap: 6px;
        border-radius: var(--r-20); overflow: auto;
    }

    /* The phone's five, whatever the width says. */
    .bp-shell .bp-rail__item--t2,
    .bp-shell .bp-rail__item--t3,
    .bp-shell .bp-rail__foot { display: none; }
    .bp-rail__cam { order: var(--cam-phone, 1); }
    .bp-more__item--t2 { display: flex; }

    .bp-shell .bp-rail__item,
    .bp-shell[data-expanded="1"] .bp-rail__item {
        flex: none; width: 52px; height: 52px;
        gap: 0; padding: 0; border-radius: var(--r-14);
    }
    .bp-shell .bp-rail__short { display: none; }

    .bp-rail__cam { flex: none; width: 52px; height: 52px; }
    .bp-rail__cam button {
        width: 52px; height: 52px;
        margin-top: 0; border-width: 0; box-shadow: none;
    }
    .bp-rail__cam svg { width: 24px; height: 24px; }

    .bp-rail__more {
        flex: none; width: 52px; height: 52px;
        gap: 0; font-size: 0; border-radius: var(--r-14);
    }

    /* 390px of height is the whole budget, so the header is the phone's: one row,
       the language pill in the sheet, and a long project name clipped rather than
       allowed to push the account onto a second line. */
    .bp-header { gap: var(--sp-2); }
    .bp-lang { display: none; }
    .bp-header__logo span { display: none; }
    .bp-project { flex: 1 1 0; min-width: 0; padding-right: var(--sp-2); }
    .bp-project__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* Nothing is under the bar any more, so nothing needs room for it. */
    .bp-main { padding: var(--sp-4); }
    .bp-toast-dock { bottom: var(--sp-4); }
    .bp-more {
        left: 96px; bottom: var(--sp-4);
        grid-template-columns: repeat(4, 1fr);
    }
}

/* Every target is at least 48px once there is no mouse. */
@media (pointer: coarse) {
    .bp-btn, .bp-iconbtn, .bp-chip, .bp-seg__opt { min-height: var(--touch); }
    .bp-btn--36, .bp-btn--40 { height: var(--touch); }
}

/* ── 12. print ────────────────────────────────────────────────────────── */

@media print {
    .bp-rail, .bp-header, .bp-banner, .bp-toast-dock,
    .bp-scrim, .bp-panel, .bp-modal-wrap, .bp-no-print { display: none !important; }
    /* The sheet is the page when printing: nothing around it, and no stack gap
       pushing it down. */
    .bp-stack { gap: 0; }
    .bp-shell { grid-template-columns: minmax(0, 1fr); background: #fff; }
    .bp-main { padding: 0; }
    .bp-card { box-shadow: none; border: 1px solid #C5CBDD; }
    .bp-grid-bg, .bp-navy-grid { background-image: none; }
}

/* A4 document preview, on screen and on paper. 595px is A4 at 72dpi, which is
   what the print templates are laid out against. */
.bp-a4 {
    width: 595px; max-width: 100%; margin: 0 auto;
    /* Always the paper's own colours, in either theme: this is a document, and
       a printed NCR is black on white whatever the screen was set to. */
    background: #fff; color: #131A33;
    padding: 40px 44px;
    box-shadow: var(--shadow-2);
}
/* Which language a bilingual document is read in. "both" is the absence of a
   rule, so nothing is hidden unless it was asked for. */
[data-lang="ka"] .bp-only-en,
[data-lang="ka"] .bp-lang-sep,
[data-lang="en"] .bp-only-ka,
[data-lang="en"] .bp-lang-sep { display: none; }
.bp-only-en { color: #555; }

.bp-a4__head {
    display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-4);
    padding-bottom: 14px; margin-bottom: 18px;
}
.bp-a4__table { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
.bp-a4__table th,
.bp-a4__table td { border: 1px solid #DDE1EC; padding: 8px 10px; vertical-align: top; text-align: left; }
.bp-a4__table th { width: 36%; background: #F7F8FB; font-weight: 600; }
.bp-a4__photo {
    width: 100%; height: 200px; object-fit: cover;
    border: 1px solid #DDE1EC; border-radius: 6px;
}
/* A captured photo, with the one action it needs. The button is the full
   width of the tile because on site this is pressed with a glove. */
/* A small AI action that fills the field it sits in and nothing else, so it
   lives in the corner of that field rather than beside it. Yellow, because
   what it writes is an AI output. */
.bp-ai-chip {
    position: absolute; right: 5px; top: 5px;
    width: 30px; height: 30px; border-radius: var(--r-8);
    background: var(--warning-bg); color: var(--warning-ink);
    font-size: 10px; font-weight: 700;
}
.bp-ai-chip--sm { width: 26px; height: 26px; right: 4px; top: 4px; }
.bp-ai-chip:hover { background: var(--cms-accent); color: var(--cms-navy); }
.bp-ai-chip[disabled] { opacity: .5; cursor: progress; }

/* −/+ either side of a number: a headcount is entered on a tablet, on site,
   through a glove. The field stays a field for anyone with a keyboard. */
.bp-stepper {
    display: flex; align-items: center; min-width: 0;
    background: var(--surface); border-radius: var(--r-14); box-shadow: var(--shadow-1);
    overflow: hidden;
}
.bp-stepper button {
    width: 38px; height: 40px; flex: none;
    font-size: var(--fs-16); font-weight: 600; color: var(--ink);
}
.bp-stepper button:hover { background: var(--border); }
.bp-stepper input {
    flex: 1; min-width: 0; width: 100%; height: 40px; border: 0; outline: 0;
    background: transparent; color: var(--ink);
    text-align: center; font: 500 var(--fs-14) var(--font-mono);
}

/* The report editor's rows. Named rather than written inline: a media query
   cannot override a style attribute, so columns written on the element itself
   would never stack on a phone. */
.bp-report-line {
    display: grid; grid-template-columns: minmax(0, 1.6fr) 140px minmax(0, 1fr) auto;
    gap: var(--sp-2); align-items: center;
}
.bp-report-staff {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)) auto;
    gap: 6px; align-items: center;
}
.bp-report-check {
    display: grid; grid-template-columns: minmax(0, 1.2fr) auto minmax(0, 1.6fr);
    gap: var(--sp-3); align-items: center;
    background: var(--surface2); border-radius: var(--r-14); padding: var(--sp-3);
}

@media (max-width: 820px) {
    /* The contractor takes the whole row and the rest of the line follows
       underneath it: a name in a 200px track is a caret and nothing else. */
    .bp-report-line  { grid-template-columns: 140px minmax(0, 1fr) auto; }
    .bp-report-line > .bp-select { grid-column: 1 / -1; }
    .bp-report-staff { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .bp-report-check { grid-template-columns: minmax(0, 1fr); }
}

.bp-photo-tile {
    margin: 0; border-radius: var(--r-12); overflow: hidden;
    background: var(--surface2); display: flex; flex-direction: column;
}
.bp-photo-tile img { width: 100%; height: 130px; object-fit: cover; display: block; }
.bp-photo-tile__drop {
    width: 100%; min-height: 32px; padding: 6px;
    font-size: var(--fs-11); color: var(--danger); background: none;
}
.bp-photo-tile__drop:hover { background: var(--danger-bg); }

.bp-a4__block { margin-bottom: 18px; break-inside: avoid; }
/* The black band above a section is how this industry's reports are read —
   it is the section heading, so it is an <h2>. */
.bp-a4__banner {
    margin: 0; background: #222; color: #fff; text-align: center;
    padding: 6px; font-weight: 700; font-size: var(--fs-13);
    border-radius: 6px 6px 0 0;
}
.bp-a4__table--grid { font-size: var(--fs-12); }
.bp-a4__table--grid th { width: auto; background: #F0F0F2; text-align: left; padding: 6px; }
.bp-a4__table--grid td { padding: 6px; }
.bp-a4__photo-card { margin: 0; border: 1px solid #DDE1EC; border-radius: 6px; overflow: hidden; break-inside: avoid; }
.bp-a4__photo-card img { width: 100%; height: 230px; object-fit: cover; display: block; }
.bp-a4__photo-card figcaption { padding: 6px 8px; font-size: var(--fs-11); text-align: center; background: #FAFAFB; }
/* Neither a table row nor a photo may be split across two sheets. */
.bp-a4__table tr, .bp-a4__photo { break-inside: avoid; }
@media print {
    .bp-a4 { width: auto; box-shadow: none; padding: 0; }
    @page { size: A4; margin: 14mm; }
}

/* ── Attachments ──────────────────────────────────────────────────────────
   Files hanging on a record or on a comment. Photographs are shown rather
   than listed: on a punch item the picture is the information, and a row of
   file names says nothing anybody can act on. */
.bp-attachments {
    display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: 6px;
}
.bp-attach {
    position: relative; display: flex; align-items: center;
    border: 1px solid var(--line); border-radius: var(--r-10);
    background: var(--surface2); overflow: hidden; max-width: 100%;
}
.bp-attach__open {
    display: flex; align-items: center; gap: 8px; min-width: 0;
    padding: 8px 10px; text-decoration: none; color: var(--ink); font-size: var(--fs-12);
}
.bp-attach__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px; }
.bp-attach__size { color: var(--muted); font-size: var(--fs-11); }
/* A thumbnail is a square tile; the long edge of the original decides nothing
   about the grid, so twelve photographs stay a grid and not a staircase. */
.bp-attach--image { width: 104px; height: 104px; }
.bp-attach--image .bp-attach__open { padding: 0; width: 100%; height: 100%; }
.bp-attach--image img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bp-attach__badge {
    position: absolute; left: 4px; bottom: 4px; font-size: 11px; line-height: 1;
    padding: 3px 4px; border-radius: 6px; background: var(--surface); border: 1px solid var(--line);
}
.bp-attach__remove { position: absolute; top: 2px; right: 2px; }
.bp-attach__remove .bp-iconbtn { background: var(--surface); border: 1px solid var(--line); }

/* The controls that put them there. The file inputs are hidden inside their
   labels, so the buttons are the buttons. */
.bp-attach-field { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.bp-attach-field .bp-btn { cursor: pointer; }
.bp-attach-field__names {
    flex: 1 1 140px; min-width: 0; font-size: var(--fs-11); color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bp-attach-field__pick { flex: 1 1 100%; font-size: var(--fs-12); }
.bp-attach-field__pick > summary { cursor: pointer; color: var(--muted); padding: 4px 0; }
.bp-attach-field__pick .bp-select { margin-top: 4px; }

/* ── The file card ────────────────────────────────────────────────────────
   The design's own tile, from the prototype: a wash of colour behind a badge
   with the extension on it, the name and one line of meta underneath. Three
   screens draw it — the file manager, the picker on a comment, and the strip
   of what is already attached — so it is one set of classes and one palette
   (App\Support\FileKinds). --tint and --badge come from there. */
.bp-filegrid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--sp-3);
}
.bp-filecard {
    position: relative; display: flex; flex-direction: column; min-width: 0;
    background: var(--surface); border-radius: var(--r-16); box-shadow: var(--shadow-1);
    overflow: hidden; transition: transform var(--dur-base), box-shadow var(--dur-base);
}
.bp-filecard:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(11, 31, 92, .14); }
.bp-filecard__open {
    display: flex; flex-direction: column; flex: 1; min-width: 0; color: inherit; text-decoration: none;
}
.bp-filecard__open:hover { text-decoration: none; }
.bp-filecard__thumb {
    height: 110px; display: flex; align-items: center; justify-content: center;
    background-image: var(--tint);
}
/* The washes are light by design; on a dark page they would glare, so the hue
   stays and the light goes. */
:root[data-theme="dark"] .bp-filecard__thumb,
:root[data-theme="dark"] .bp-filepick__card { filter: saturate(.6) brightness(.45); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .bp-filecard__thumb,
    :root:not([data-theme="light"]) .bp-filepick__card { filter: saturate(.6) brightness(.45); }
}
.bp-filecard__badge {
    height: 24px; padding: 0 10px; border-radius: var(--r-pill); background: var(--badge);
    color: #fff; font-family: var(--font-mono); font-size: var(--fs-11); font-weight: 600;
    display: inline-flex; align-items: center;
}
.bp-filecard__body { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.bp-filecard__name {
    font-weight: 600; font-size: var(--fs-13); line-height: 1.4;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bp-filecard__meta { font-size: var(--fs-11); color: var(--muted); font-family: var(--font-mono); }
/* The actions sit over the wash and appear on hover; a touch screen has no
   hover, so there they are simply always there. */
.bp-filecard__acts {
    position: absolute; top: 8px; right: 8px; display: flex; gap: 4px;
    opacity: 0; transition: opacity var(--dur-base);
}
.bp-filecard:hover .bp-filecard__acts,
.bp-filecard:focus-within .bp-filecard__acts { opacity: 1; }
@media (hover: none) { .bp-filecard__acts { opacity: 1; } }
.bp-filecard__acts .bp-iconbtn { background: var(--surface); box-shadow: var(--shadow-1); }
.bp-filecard__acts form { display: contents; }
/* The key-document popover (Dashboard V2's „ძირითადი დოკუმენტები", a <details> in the actions)
   is taller than the card. ⚠️ The card clips with overflow:hidden, so while it is open the card
   lets it out and sits above its neighbours — otherwise „შენახვა" is cut off and cannot be pressed. */
.bp-filecard:has(.bp-filecard__key[open]) { overflow: visible; z-index: 6; }
.bp-filecard:has(.bp-filecard__key[open]) .bp-filecard__acts { opacity: 1; }
/* A folder is the same card with no wash and a glyph instead of a badge. */
/* Same height as every other tile, or the grid steps up and down as folders
   and files alternate. */
.bp-filecard--folder .bp-filecard__thumb { background: var(--surface2); color: var(--warning-ink); }

/* Somewhere to drop them, matching the prototype's dashed strip. */
.bp-dropzone {
    position: relative;
    display: flex; align-items: center; justify-content: center; gap: 10px;
    min-height: 64px; width: 100%; padding: 0 var(--sp-4);
    border: 1.5px dashed var(--border); border-radius: var(--r-16);
    background: transparent; color: var(--muted); font-size: var(--fs-13); cursor: pointer;
    transition: border-color var(--dur-base), color var(--dur-base), background var(--dur-base);
}
.bp-dropzone:hover, .bp-dropzone.is-over { border-color: var(--primary); color: var(--primary); background: var(--surface); }
.bp-dropzone input[type="file"] { position: absolute; opacity: 0; pointer-events: none; }

/* ── The same card, miniature: picking one to hang on a comment ───────────
   A strip that scrolls sideways rather than a select box nobody can read on a
   phone. The checkbox is the control; the card is what it looks like. */
.bp-filepick { display: flex; gap: var(--sp-2); overflow-x: auto; padding: 2px 2px 6px; scrollbar-width: thin; min-width: 0; max-width: 100%; }
/* ⚠️ The strip scrolls only if everything above it may be narrower than its content: a flex or
   grid item's min-width is `auto`, so each wrapper grew to the full row of cards and the strip
   ran across the page and under the side column (punch, RFI, submittal pages). */
.bp-attach-field, .bp-attach-field__pick { min-width: 0; max-width: 100%; }
.bp-filepick__item { flex: 0 0 136px; cursor: pointer; position: relative; }
.bp-filepick__item input { position: absolute; opacity: 0; pointer-events: none; }
.bp-filepick__card {
    display: flex; flex-direction: column; gap: 6px; height: 100%;
    padding: 10px; border-radius: var(--r-12); background-image: var(--tint);
    outline: 2px solid transparent; outline-offset: -2px; transition: outline-color var(--dur-base);
}
.bp-filepick__item input:checked + .bp-filepick__card { outline-color: var(--primary); }
.bp-filepick__item input:focus-visible + .bp-filepick__card { outline-color: var(--cms-accent); }
.bp-filepick__card .bp-filecard__badge { align-self: flex-start; height: 20px; padding: 0 8px; font-size: 10px; }
.bp-filepick__name {
    font-size: var(--fs-11); font-weight: 600; color: var(--cms-navy); line-height: 1.35;
    display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.bp-filepick__tick {
    position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; border-radius: 50%;
    background: var(--primary); color: #fff; font-size: 11px; display: none;
    align-items: center; justify-content: center;
}
.bp-filepick__item input:checked ~ .bp-filepick__tick { display: flex; }

/* ── Inspections ──────────────────────────────────────────────────────────
   The builder numbers its rows itself: a question's number is its name in a
   condition, and a CSS counter keeps it true as rows are added and removed. */
#bp-insp-rows { counter-reset: bp-q; }
.bp-insp-row {
    counter-increment: bp-q;
    display: flex; gap: var(--sp-3); align-items: flex-start;
    padding: var(--sp-3); border-radius: var(--r-12); background: var(--surface2);
}
.bp-insp-row__n {
    flex: none; width: 28px; height: 28px; border-radius: 50%;
    background: var(--cms-navy); color: #fff; font-size: var(--fs-12);
    display: inline-flex; align-items: center; justify-content: center;
}
.bp-insp-row__n::before { content: counter(bp-q); }
.bp-insp-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.bp-insp-row__section { height: 36px; font-size: var(--fs-12); }
.bp-insp-row__opts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.bp-insp-row__opts .bp-select { width: auto; height: 36px; }

/* The walk: one question, big targets, built for a phone held in one hand. */
.bp-insp-q {
    display: flex; flex-direction: column; gap: var(--sp-2);
    padding: var(--sp-3) 0; border-top: 1px solid var(--line);
    scroll-margin-top: 80px;
}
.bp-insp-q:first-of-type { border-top: 0; }
.bp-insp-q.is-fail { box-shadow: inset 3px 0 0 var(--danger); padding-left: var(--sp-3); }
.bp-insp-q__head { display: flex; gap: var(--sp-2); align-items: flex-start; }
.bp-insp-q__n {
    flex: none; min-width: 24px; height: 24px; padding: 0 6px; border-radius: var(--r-pill);
    background: var(--surface2); font-size: var(--fs-11);
    display: inline-flex; align-items: center; justify-content: center;
}
.bp-insp-q__prompt { font-size: var(--fs-14); font-weight: 600; line-height: 1.45; }
.bp-insp-q__answers { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.bp-insp-q__answers .bp-choice { min-width: 96px; min-height: 44px; }
/* The answer says what it means: pass green, fail red, not applicable grey. */
.bp-choice--pass:has(input:checked), .bp-choice--yes:has(input:checked) { background: var(--success-bg); color: var(--success); }
.bp-choice--fail:has(input:checked), .bp-choice--no:has(input:checked) { background: var(--danger-bg); color: var(--danger); }
.bp-choice--na:has(input:checked) { background: var(--surface2); color: var(--muted); }

/* Save and finish stay in reach at the bottom of a long list. */
.bp-insp-bar {
    position: sticky; bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px)); z-index: 5;
    display: flex; justify-content: flex-end; gap: var(--sp-2);
    padding: var(--sp-3); border-radius: var(--r-16);
    background: var(--surface); box-shadow: 0 8px 24px rgba(11, 31, 92, .14);
}
@media (max-width: 1100px) {
    /* Above the phone's bottom bar, not behind it. */
    .bp-insp-bar { bottom: calc(var(--tab-height) + var(--sp-4) + env(safe-area-inset-bottom, 0px)); }
}

/* ── Capture ──────────────────────────────────────────────────────────────
   The phone bar's camera sheet, from the mobile prototype: a navy viewfinder
   to tap, the yellow shutter ringed in navy, a strip of what has been taken,
   and then the question of where it goes. */
.bp-capture [data-bp-capture-step] { display: flex; flex-direction: column; gap: var(--sp-3); }
.bp-capture [data-bp-capture-step][hidden] { display: none; }
.bp-capture__finder {
    position: relative; height: 240px; border-radius: 20px; cursor: pointer; overflow: hidden;
    background: linear-gradient(160deg, #2A3555, #0B1F5C);
}
.bp-capture__finder::after {
    content: ""; position: absolute; inset: 16px; border: 1.5px solid rgba(255, 255, 255, .35); border-radius: 12px;
}
.bp-capture__hint {
    position: absolute; top: 28px; left: 0; right: 0; text-align: center;
    color: rgba(255, 255, 255, .75); font-size: var(--fs-12);
}
.bp-capture__label {
    position: absolute; left: 24px; right: 24px; bottom: 24px; z-index: 1;
    padding: 6px 8px; border-radius: 8px; background: rgba(11, 31, 92, .75);
    color: #fff; font-size: 10px; line-height: 1.4;
}
.bp-capture__shutter {
    width: 72px; height: 72px; border-radius: 50%; flex: none;
    background: var(--cms-accent); border: 5px solid var(--cms-navy);
    display: flex; align-items: center; justify-content: center;
    transition: transform .1s;
}
.bp-capture__shutter i { width: 52px; height: 52px; border-radius: 50%; background: #fff; display: block; }
.bp-capture__shutter:active { transform: scale(.92); }
.bp-capture__shots { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; min-height: 0; }
.bp-capture__shots:empty { display: none; }
.bp-capture__shot { position: relative; width: 72px; height: 72px; flex: none; border-radius: 12px; overflow: hidden; background: #0B1F5C; }
.bp-capture__shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bp-capture__drop {
    position: absolute; top: 3px; right: 3px; width: 20px; height: 20px; border-radius: 50%;
    background: rgba(11, 31, 92, .75); color: #fff; font-size: 10px;
}
.bp-capture__tasks { display: flex; flex-direction: column; gap: 6px; max-height: 38vh; overflow-y: auto; margin-top: 6px; }
.bp-capture__task {
    /* flex: none — in a column with a max-height the rows would otherwise be squeezed
       below their text, and long Georgian titles spill over the next row. */
    flex: none; display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 8px 14px; text-align: left;
    border-radius: 14px; background: var(--surface2); color: var(--ink); font-weight: 600;
    transition: background var(--dur-base), color var(--dur-base);
}
.bp-capture__task.is-on { background: var(--cms-navy); color: #fff; }
.bp-capture__code { font-size: var(--fs-11); opacity: .7; flex: none; }
.bp-capture__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: var(--fs-13); line-height: 1.35; }
/* Three lines, not two: sibling tasks often differ only at the end ("… 400 mm" / "… 600 mm"). */
.bp-capture__name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.bp-capture__text small { font-weight: 500; font-size: var(--fs-11); opacity: .7; }

/* ── Budget ───────────────────────────────────────────────────────────────
   A money sheet, which is a table of numbers first and a page second: the
   figures are mono and right-aligned so the columns line up at a glance, and
   only two things carry colour — what is over budget, and what is not there
   at all. */
/* Six tabs of Georgian are 951px, which fits a desk and nothing else.
   ⚠️ `max-width: 100%` alone squeezed the pill's own background while its
   contents kept their width and ran out past the rounded right edge — the tabs
   looked cut off with a square corner, and the last one could not be reached.
   A scroller keeps the pill the width of what is in it and moves it instead. */
.bp-budget-tabs {
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
    /* The pill casts a shadow, and a scroll container clips it; the negative
       margin gives it room back without moving anything. */
    padding: 3px 3px 8px;
    margin: -3px -3px -8px;
}
.bp-budget-tabs::-webkit-scrollbar { display: none; }
/* C6: the way across — into the classic view, or back to „ხელშეკრულებები" — sits on the same
   line after the pill and scrolls with it. */
.bp-budget-tabs { white-space: nowrap; }
.bp-budget-tabs > .bp-btn { margin-left: var(--sp-2); vertical-align: middle; }
/* Scrolling, not wrapping — the phone rule on .bp-seg is for the controls that
   are a choice of four words, not for a row of six screen names.
   ⚠️ `width: max-content` is what makes it scroll rather than squeeze: an
   inline-flex box shrinks to the space it is offered, and its `flex: none`
   children then overflow the background they are supposed to sit on. */
.bp-budget-tabs .bp-seg {
    flex-wrap: nowrap; height: var(--control);
    max-width: none; width: max-content;
}

/* Four money KPIs do not fit across a phone the way four counts do: an amount
   is ten characters, not two. */
.bp-budget-kpis {
    display: grid; gap: var(--sp-3);
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.bp-budget-kpi { font-size: var(--fs-24); }
.bp-budget-kpi__sub { font-size: var(--fs-12); color: var(--muted); }

.bp-budget-num {
    font-family: var(--font-mono); font-size: var(--fs-12);
    text-align: right; justify-self: end; white-space: nowrap;
}
.bp-budget-num.is-over, .bp-mono.is-over { color: var(--danger); font-weight: 600; }
.bp-budget-num.is-zero { color: var(--muted); opacity: .55; }
.bp-budget-pending { display: block; font-size: 10px; color: var(--st-paused); }
.bp-budget-amount { margin-left: auto; font-size: var(--fs-13); font-weight: 600; white-space: nowrap; }

/* The BoQ's own shape: a section band, then its lines. The band carries the
   section's subtotal, which is where a QS looks first. */
.bp-budget-section { background: var(--surface2); font-weight: 700; }
.bp-budget-section:hover { background: var(--surface2); }
.bp-budget-section__name { grid-column: 1 / 3; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.bp-budget-total {
    background: var(--cms-navy); color: #fff; font-weight: 700; margin-top: var(--sp-2);
}
.bp-budget-total:hover { background: var(--cms-navy); }
.bp-budget-total .bp-budget-num { color: #fff; }
.bp-budget-total .bp-budget-num.is-over { color: var(--cms-accent); }

.bp-budget-sheet .bp-table__cell { align-self: center; }

.bp-budget-lock.is-locked { box-shadow: inset 0 0 0 2px var(--st-done); }
.bp-budget-add summary { display: inline-flex; list-style: none; cursor: pointer; }
.bp-budget-add summary::-webkit-details-marker { display: none; }

.bp-budget-figures {
    display: grid; gap: var(--sp-2);
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.bp-budget-figure {
    display: flex; flex-direction: column; gap: 2px; min-width: 0;
    padding: var(--sp-3); border-radius: var(--r-14); background: var(--surface2);
}
.bp-budget-figure.is-strong { background: var(--info-bg); }
.bp-budget-figure .bp-mono { font-size: var(--fs-14); font-weight: 600; }
.bp-budget-figure small { font-size: 10px; color: var(--muted); line-height: 1.35; }

.bp-budget-legend dl { margin: var(--sp-3) 0 0; display: grid; gap: 6px; grid-template-columns: max-content 1fr; }
.bp-budget-legend dt { font-weight: 600; font-size: var(--fs-12); }
.bp-budget-legend dd { margin: 0; font-size: var(--fs-12); color: var(--muted); }

.bp-budget-decision {
    display: flex; flex-direction: column; gap: 4px;
    padding: var(--sp-3); border-radius: var(--r-14); background: var(--surface2); font-size: var(--fs-13);
}

/* One row of money in an editor: line, what it is, how much. The labels are
   there for the phone, where the row becomes four stacked fields and a header
   row would be somewhere off the top of the screen. */
.bp-money-row {
    display: grid; gap: var(--sp-2); align-items: end;
    grid-template-columns: minmax(200px, 1.4fr) minmax(160px, 1fr) 150px 40px;
}
.bp-money-row__amount input { text-align: right; }
.bp-money-row .bp-money-row__label { display: none; }
.bp-money-row + .bp-money-row { margin-top: var(--sp-2); }

@media (max-width: 820px) {
    .bp-money-row { grid-template-columns: minmax(0, 1fr) 40px; }
    .bp-money-row .bp-field:first-of-type { grid-column: 1 / 3; }
    .bp-money-row .bp-money-row__label { display: block; }
    .bp-budget-legend dl { grid-template-columns: minmax(0, 1fr); }
}

/* ── 13. the company's own bar ────────────────────────────────────────────
   The portfolio's shell: a navy block across the top where a project's shell
   has a rail down the side. Navy carries the blueprint grid, as every navy
   surface in this language does.

   ⚠️ The tabs are Georgian words, so they are NOT uppercased and NOT tracked.
   The design's row is set in sentence case for exactly that reason. */

.bp-topbar {
    background: var(--cms-navy); color: #fff;
    border-radius: var(--r-24);
    margin-bottom: var(--sp-5);
    background-image:
        linear-gradient(rgba(255, 255, 255, .07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .07) 1px, transparent 1px);
    background-size: 40px 40px;
}

.bp-topbar__row {
    display: flex; align-items: center; gap: var(--sp-3);
    height: 72px; padding: 0 var(--sp-4);
}

.bp-topbar__logo { display: flex; align-items: center; gap: 10px; color: #fff; }
.bp-topbar__logo:hover { text-decoration: none; }
.bp-topbar__logo span {
    font-family: var(--font-display); font-weight: 900;
    font-size: 21px; letter-spacing: -.04em;
}

/* The mono trail after the mark — „/ პროექტები / ახალი". A path, so mono; never uppercased. */
.bp-topbar__crumb {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-family: var(--font-mono); font-size: 12.5px; color: #C9D1EA;
}

.bp-topbar__pick {
    display: inline-flex; align-items: center; gap: 8px;
    height: 42px; padding: 0 var(--sp-4);
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .08); color: #fff;
    font-size: var(--fs-13); font-weight: 600;
}
.bp-topbar__pick:hover { background: rgba(255, 255, 255, .14); }

/* The shell's right-hand side sits on navy here, so its pieces invert. */
.bp-topbar .bp-search { background: rgba(255, 255, 255, .08); color: #C9D1EA; box-shadow: none; }
.bp-topbar .bp-search kbd { background: rgba(255, 255, 255, .1); color: #C9D1EA; }
.bp-topbar .bp-iconbtn { background: rgba(255, 255, 255, .08); color: #fff; box-shadow: none; }
.bp-topbar .bp-iconbtn:hover { background: rgba(255, 255, 255, .14); }
.bp-topbar .bp-lang { background: rgba(255, 255, 255, .08); }
.bp-topbar .bp-lang__opt { color: #C9D1EA; }
.bp-topbar .bp-lang__slider { background: var(--cms-accent); }
.bp-topbar .bp-lang__opt[aria-pressed="true"] { color: var(--cms-navy); }
.bp-topbar .bp-offline { background: rgba(255, 255, 255, .08); color: #fff; }

.bp-topbar__tabs {
    display: flex; gap: 6px; align-items: center;
    padding: 0 var(--sp-4) var(--sp-3);
    overflow-x: auto; scrollbar-width: none;
}
.bp-topbar__tabs::-webkit-scrollbar { display: none; }

.bp-topbar__tab {
    display: inline-flex; align-items: center;
    height: 40px; padding: 0 var(--sp-4);
    border-radius: var(--r-12);
    color: #C9D1EA; font-size: var(--fs-13); font-weight: 600;
    white-space: nowrap;
    transition: background var(--dur-base), color var(--dur-base);
}
.bp-topbar__tab:hover { background: rgba(255, 255, 255, .1); color: #fff; text-decoration: none; }
.bp-topbar__tab.is-on { background: var(--cms-accent); color: var(--cms-navy); }

/* With a bar on top there is no rail beside the page, so the shell stops being
   a two-column grid at all.
   ⚠️ Block, not a one-column grid: the phone's "more" sheet is also a child of
   the shell, and as a grid item it would take a column of its own and squeeze
   the page into the other one. And the selector repeats the class because the
   `[data-expanded]` rule above carries an attribute, which outranks one class. */
.bp-shell--portfolio.bp-shell--portfolio { display: block; }

@media (max-width: 760px) {
    .bp-topbar__row { height: auto; flex-wrap: wrap; padding: var(--sp-3) var(--sp-3) 0; }
    .bp-topbar__tabs { padding: var(--sp-3); }
}

/* ── Turbo ─────────────────────────────────────────────────────────────────
   The bar Turbo draws across the top while it is fetching. It appears only
   after 500ms, so on a fast connection between screens it is never seen at
   all — which is the point of it: it exists for the visit that is slow, and
   a person who has pressed something and been given no answer.

   Turbo's own is 3px of its blue. This is the product's primary, 2px.

   ⚠️ The class is doubled deliberately. Turbo injects its own <style> into the
   head at run time, so it lands *after* this file and wins every tie. Two
   classes beat one and the bar is ours. */
.turbo-progress-bar.turbo-progress-bar {
    height: 2px;
    background: var(--primary);
    /* Turbo's default is 300ms linear, which reads as a machine counting; the
       shell's own ease reads as something arriving. The opacity half is Turbo's
       own fade-out and is kept exactly as it was. */
    transition: width .18s cubic-bezier(.2, .8, .2, 1), opacity 150ms 150ms ease-in;
}


/* ══ the task quick view ═══════════════════════════════════════════════════
   A task read without leaving the list it was found in. The dialog lives in
   the layout; TaskController::peek() renders what goes inside it.

   Two columns, and the split is the point: the left is the task, the right is
   what you do about it and what has already been done. On a phone they become
   one column and the dialog becomes a sheet that comes up from the bottom,
   because that is the hand it will be opened with. */

.bp-peek {
    position: fixed;
    z-index: 70;
    inset: 0;
    margin: auto;
    width: min(880px, calc(100vw - 32px));
    max-height: min(880px, calc(100vh - 64px));
    height: max-content;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--surface);
    border-radius: var(--r-24);
    box-shadow: var(--shadow-modal);
    animation: bp-pop .18s cubic-bezier(.2, .8, .2, 1);
}
.bp-peek[hidden] { display: none; }

.bp-peek__head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 14px 16px;
    /* Not a border: a hairline drawn inside the box, so the head keeps its own
       radius and the card keeps the rule that it has no outline. */
    box-shadow: inset 0 -1px 0 var(--border);
}

.bp-peek__body {
    display: grid;
    grid-template-columns: 1fr 236px;
    min-height: 0;
    overflow: auto;
}

.bp-peek__main {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 20px 22px 24px;
    min-width: 0;
}

.bp-peek__rail {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 20px 18px 24px;
    background: var(--surface2);
    min-width: 0;
}

/* ⚠️ Georgian, so: no text-transform and no letter-spacing. The weight and the
   size carry it; capitals would break the script and tracking would take it
   apart letter by letter. */
.bp-peek__title {
    margin: 0;
    font-size: var(--fs-20);
    font-weight: 700;
    line-height: 1.3;
}

.bp-peek__meta {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px 20px;
}
.bp-peek__cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.bp-peek__cell b { font-size: var(--fs-15); font-weight: 600; }
.bp-peek__cell--end { text-align: end; }

/* ── the number ──────────────────────────────────────────────────────────── */

.bp-peek__prog {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 18px;
    padding: 14px 16px;
    background: var(--surface2);
    border-radius: var(--r-16);
}
.bp-peek__pct { display: flex; flex-direction: column; line-height: 1; }
/* The figure and its sign on one line, as in the design („41%" with a small accent „%"). */
.bp-peek__num { white-space: nowrap; }
.bp-peek__pct b {
    font-family: var(--font-display);
    font-size: 38px;
    font-weight: 800;
    color: var(--ink);
}
.bp-peek__pct i {
    font-style: normal;
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 800;
    color: var(--cms-accent);
    margin-inline-start: 2px;
}
.bp-peek__pct .bp-label { margin-top: 6px; }
.bp-peek__progright { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* ⚠️ The box is --surface2 and so is a bar's track: on it the track vanished and the bar
   read as a short blue dash. Inside the box the track is the card's own white. */
.bp-peek__prog .bp-progress { background: var(--surface); }
.bp-peek__fill--late { background: var(--danger); }

/* ── the four states ─────────────────────────────────────────────────────── */

.bp-peek__states { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }

.bp-peek__state,
.bp-peek__done {
    border: 0;
    cursor: pointer;
    font: inherit;
    font-weight: 600;
    font-size: var(--fs-14);
    color: var(--ink);
    background: var(--surface2);
    border-radius: var(--r-14);
    padding: 12px 10px;
    transition: transform .12s cubic-bezier(.2, .8, .2, 1), background .12s;
}
.bp-peek__state:hover, .bp-peek__done:hover { transform: translateY(-1px); }
.bp-peek__state:disabled, .bp-peek__done:disabled { opacity: .55; cursor: default; transform: none; }

.bp-peek__state--doing.is-on { background: var(--primary); color: #fff; }
.bp-peek__state--late.is-on  { background: var(--warn-bg); color: var(--warning-ink); }
.bp-peek__state--todo.is-on  { background: var(--dark-pill); color: var(--dark-pill-ink); }

.bp-peek__done { width: 100%; padding: 14px; font-size: var(--fs-15); }
.bp-peek__done.is-on,
.bp-peek__done:not(:disabled):hover { background: var(--success); color: #fff; }

/* ── the weather, when there is something to say ─────────────────────────── */

.bp-peek__risk {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 14px;
    background: var(--warn-bg);
    border-radius: var(--r-14);
    /* The one place a rule is drawn on purpose: a bar down the side, which is how
       this block says "read me" without shouting. */
    box-shadow: inset 3px 0 0 var(--warning);
}
.bp-peek__risk p { margin: 0; font-size: var(--fs-13); line-height: 1.5; }
.bp-peek__risk--bad { background: var(--late-bg); box-shadow: inset 3px 0 0 var(--danger); }

/* ── what is attached ────────────────────────────────────────────────────── */

.bp-peek__rec {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--surface2);
    border-radius: var(--r-14);
    color: inherit;
    text-decoration: none;
    min-width: 0;
}
a.bp-peek__rec:hover { background: var(--info-bg); }
.bp-peek__kind {
    /* ⚠️ NOT --font-mono. This chip holds a record kind, which in Georgian reads
       as words, and Georgian is never set in IBM Plex Mono. The file extension
       beside it is Latin and gets the mono face of its own. */
    font-size: var(--fs-11);
    font-weight: 700;
    color: var(--muted);
    white-space: nowrap;
}
.bp-peek__ext { font-family: var(--font-mono); }
.bp-peek__recname {
    flex: 1;
    min-width: 0;
    font-size: var(--fs-13);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── the rail ────────────────────────────────────────────────────────────── */

.bp-peek__action { width: 100%; justify-content: center; cursor: pointer; }
.bp-peek__note { display: flex; flex-direction: column; gap: 8px; }

.bp-peek__events { display: flex; flex-direction: column; gap: 12px; }
.bp-peek__event {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: var(--fs-12);
    line-height: 1.45;
    padding-inline-start: 14px;
    position: relative;
}
.bp-peek__event::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 5px;
    width: 6px;
    height: 6px;
    background: var(--muted);
    border-radius: 2px;
}
.bp-peek__event b { font-weight: 600; }
.bp-peek__when { color: var(--muted); font-size: var(--fs-11); }

@media (max-width: 860px) {
    /* A sheet, not a dialog: it comes up from the bottom where the thumb is, and
       it keeps the top of the screen so the list underneath is still visible. */
    .bp-peek {
        inset: auto 0 0 0;
        margin: 0;
        width: 100%;
        max-height: 92vh;
        border-radius: var(--r-24) var(--r-24) 0 0;
        animation: bp-sheet .22s cubic-bezier(.2, .8, .2, 1);
    }
    .bp-peek__body { grid-template-columns: 1fr; }
    .bp-peek__rail { background: transparent; box-shadow: inset 0 1px 0 var(--border); }
    .bp-peek__prog { grid-template-columns: 1fr; gap: 12px; }
}
@media (max-width: 520px) {
    /* One row on a phone: the code and the state on the left, the arrow and the ✕ in the
       corner. „Open in full" keeps its arrow and loses its words, and a pill that still
       does not fit gives way before the ✕ is pushed onto a second line. */
    .bp-peek__head { flex-wrap: nowrap; }
    .bp-peek__head > .bp-pill { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .bp-peek__head > .bp-pill:first-child { flex: none; }
    .bp-peek__full { flex: none; padding-inline: 12px; }
    .bp-peek__full-word { display: none; }
    .bp-peek__head > .bp-iconbtn { flex: none; }
}

/* ── „სიმჭიდროვე · კომპაქტური" (profile R2d) ─────────────────────────────
   The tokens shrink in blueprint-tokens.css; these are the paddings written as
   literals, which no token reaches. A mouse only, as there. `:root[…]` in front
   so a screen's own stylesheet, loaded later, does not undo it. */
@media (pointer: fine) {
    :root[data-bp-density="cmp"] .bp-card     { padding: var(--sp-4) var(--sp-5); gap: var(--sp-3); }
    :root[data-bp-density="cmp"] .bp-card--sm { padding: 10px var(--sp-3); }
    :root[data-bp-density="cmp"] .bp-table__head { height: 30px; }
    :root[data-bp-density="cmp"] .bp-table__head,
    :root[data-bp-density="cmp"] .bp-table__row  { gap: 10px; padding: 0 var(--sp-3); }
    :root[data-bp-density="cmp"] .bp-table__row + .bp-table__row { margin-top: 1px; }
    :root[data-bp-density="cmp"] .bp-btn--36 { height: 32px; }
    :root[data-bp-density="cmp"] .reg-row  { padding: 9px 14px; }
    :root[data-bp-density="cmp"] .reg-rows { gap: 6px; }
    :root[data-bp-density="cmp"] .reg-group { padding: 12px 2px 8px; }
}
